1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 #ifndef SC_CELL_HXX
23 #define SC_CELL_HXX
24
25 #include <stddef.h>
26
27 #include <set>
28 #include <tools/mempool.hxx>
29 #include <svl/listener.hxx>
30 #include "global.hxx"
31 #include "rangenam.hxx"
32 #include "formula/grammar.hxx"
33 #include "tokenarray.hxx"
34 #include "formularesult.hxx"
35 #include <rtl/ustrbuf.hxx>
36 #include <unotools/fontcvt.hxx>
37 #include "scdllapi.h"
38
39 #include <cellform.hxx>
40
41 #define USE_MEMPOOL
42 #define TEXTWIDTH_DIRTY 0xffff
43
44 // in addition to SCRIPTTYPE_... flags from scripttypeitem.hxx:
45 // set (in nScriptType) if type has not been determined yet
46 #define SC_SCRIPTTYPE_UNKNOWN 0x08
47
48 class ScDocument;
49 class EditTextObject;
50 class ScMatrix;
51 class SvtBroadcaster;
52 class ScCodeArray;
53 class ScProgress;
54 class ScPostIt;
55
56 // ============================================================================
57
58 /** Default cell clone flags: do not start listening, do not adjust 3D refs to
59 old position, clone note captions of cell notes. */
60 const int SC_CLONECELL_DEFAULT = 0x0000;
61
62 /** If set, cloned formula cells will start to listen to the document. */
63 const int SC_CLONECELL_STARTLISTENING = 0x0001;
64
65 /** If set, relative 3D references of cloned formula cells will be adjusted to
66 old position (used while swapping cells for sorting a cell range). */
67 const int SC_CLONECELL_ADJUST3DREL = 0x0002;
68
69 /** If set, the caption object of a cell note will not be cloned (used while
70 copying cells to undo document, where captions are handled in drawing undo). */
71 const int SC_CLONECELL_NOCAPTION = 0x0004;
72
73 // ============================================================================
74
75 class SC_DLLPUBLIC ScBaseCell
76 {
77 protected:
78 ~ScBaseCell(); // nicht virtuell -> darf nicht direkt aufgerufen werden
79
80 public:
81 explicit ScBaseCell( CellType eNewType );
82
83 /** Base copy constructor. Does NOT clone cell note or broadcaster! */
84 ScBaseCell( const ScBaseCell& rCell );
85
86 /** Returns a clone of this cell at the same position, cell note and
87 broadcaster will not be cloned. */
88 ScBaseCell* CloneWithoutNote( ScDocument& rDestDoc, int nCloneFlags = SC_CLONECELL_DEFAULT ) const;
89
90 /** Returns a clone of this cell for the passed document position, cell
91 note and broadcaster will not be cloned. */
92 ScBaseCell* CloneWithoutNote( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const;
93
94 /** Returns a clone of this cell, clones cell note and caption object too
95 (unless SC_CLONECELL_NOCAPTION flag is set). Broadcaster will not be cloned. */
96 ScBaseCell* CloneWithNote( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const;
97
98 /** Due to the fact that ScBaseCell does not have a vtable, this function
99 deletes the cell by calling the appropriate d'tor of the derived class. */
100 void Delete();
101
GetCellType() const102 inline CellType GetCellType() const { return (CellType)eCellType; }
103
104 /** Returns true, if the cell is empty (neither value nor formula nor cell note).
105 Returns false for formula cells returning nothing, use HasEmptyData() for that. */
106 bool IsBlank( bool bIgnoreNotes = false ) const;
107
108 // fuer Idle-Berechnung
GetTextWidth() const109 inline sal_uInt16 GetTextWidth() const { return nTextWidth; }
SetTextWidth(sal_uInt16 nNew)110 inline void SetTextWidth( sal_uInt16 nNew ) { nTextWidth = nNew; }
111
GetScriptType() const112 inline sal_uInt8 GetScriptType() const { return nScriptType; }
SetScriptType(sal_uInt8 nNew)113 inline void SetScriptType( sal_uInt8 nNew ) { nScriptType = nNew; }
114
115 /** Returns true, if the cell contains a note. */
HasNote() const116 inline bool HasNote() const { return mpNote != 0; }
117 /** Returns the pointer to a cell note object (read-only). */
GetNote() const118 inline const ScPostIt* GetNote() const { return mpNote; }
119 /** Returns the pointer to a cell note object. */
GetNote()120 inline ScPostIt* GetNote() { return mpNote; }
121 /** Takes ownership of the passed cell note object. */
122 void TakeNote( ScPostIt* pNote );
123 /** Returns and forgets the own cell note object. Caller takes ownership! */
124 ScPostIt* ReleaseNote();
125 /** Deletes the own cell note object. */
126 void DeleteNote();
127
128 /** Returns true, if the cell contains a broadcaster. */
HasBroadcaster() const129 inline bool HasBroadcaster() const { return mpBroadcaster != 0; }
130 /** Returns the pointer to the cell broadcaster. */
GetBroadcaster() const131 inline SvtBroadcaster* GetBroadcaster() const { return mpBroadcaster; }
132 /** Takes ownership of the passed cell broadcaster. */
133 void TakeBroadcaster( SvtBroadcaster* pBroadcaster );
134 /** Returns and forgets the own cell broadcaster. Caller takes ownership! */
135 SvtBroadcaster* ReleaseBroadcaster();
136 /** Deletes the own cell broadcaster. */
137 void DeleteBroadcaster();
138
139 // String- oder EditCell
140 static ScBaseCell* CreateTextCell( const String& rString, ScDocument* );
141
142 // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
143 void StartListeningTo( ScDocument* pDoc );
144 void EndListeningTo( ScDocument* pDoc,
145 ScTokenArray* pArr = NULL,
146 ScAddress aPos = ScAddress() );
147
148 /** Error code if ScFormulaCell, else 0. */
149 sal_uInt16 GetErrorCode() const;
150 /** ScFormulaCell with formula::svEmptyCell result, or ScNoteCell (may have been
151 created due to reference to empty cell). */
152 sal_Bool HasEmptyData() const;
153 sal_Bool HasValueData() const;
154 sal_Bool HasStringData() const;
155 String GetStringData() const; // nur echte Strings
156
157 static sal_Bool CellEqual( const ScBaseCell* pCell1, const ScBaseCell* pCell2 );
158
159 private:
160 ScBaseCell& operator=( const ScBaseCell& );
161
162 private:
163 ScPostIt* mpNote; /// The cell note. Cell takes ownership!
164 SvtBroadcaster* mpBroadcaster; /// Broadcaster for changed values. Cell takes ownership!
165
166 protected:
167 sal_uInt16 nTextWidth;
168 sal_uInt8 eCellType; // enum CellType - sal_uInt8 spart Speicher
169 sal_uInt8 nScriptType;
170 };
171
172 // ============================================================================
173
174 class SC_DLLPUBLIC ScNoteCell : public ScBaseCell
175 {
176 public:
177 #ifdef USE_MEMPOOL
178 DECL_FIXEDMEMPOOL_NEWDEL( ScNoteCell )
179 #endif
180
181 /** Cell takes ownership of the passed broadcaster. */
182 explicit ScNoteCell( SvtBroadcaster* pBC = 0 );
183 /** Cell takes ownership of the passed note and broadcaster. */
184 explicit ScNoteCell( ScPostIt* pNote, SvtBroadcaster* pBC = 0 );
185
186 #ifdef DBG_UTIL
187 ~ScNoteCell();
188 #endif
189
190 private:
191 ScNoteCell( const ScNoteCell& );
192 };
193
194 // ============================================================================
195
196 class SC_DLLPUBLIC ScValueCell : public ScBaseCell
197 {
198 public:
199 #ifdef USE_MEMPOOL
200 DECL_FIXEDMEMPOOL_NEWDEL( ScValueCell )
201 #endif
202 ScValueCell();
203 explicit ScValueCell( double fValue );
204
205 #ifdef DBG_UTIL
206 ~ScValueCell();
207 #endif
208
SetValue(double fValue)209 inline void SetValue( double fValue ) { mfValue = fValue; }
GetValue() const210 inline double GetValue() const { return mfValue; }
211
212 private:
213 double mfValue;
214 };
215
216 // ============================================================================
217
218 class SC_DLLPUBLIC ScStringCell : public ScBaseCell
219 {
220 public:
221 #ifdef USE_MEMPOOL
222 DECL_FIXEDMEMPOOL_NEWDEL( ScStringCell )
223 #endif
224
225 ScStringCell();
226 explicit ScStringCell( const String& rString );
227
228 #ifdef DBG_UTIL
229 ~ScStringCell();
230 #endif
231
SetString(const String & rString)232 inline void SetString( const String& rString ) { maString = rString; }
GetString(String & rString) const233 inline void GetString( String& rString ) const { rString = maString; }
GetString() const234 inline const String& GetString() const { return maString; }
235
236 private:
237 String maString;
238 };
239
240 // ============================================================================
241
242 class SC_DLLPUBLIC ScEditCell : public ScBaseCell
243 {
244 private:
245 EditTextObject* pData;
246 String* pString; // fuer schnelleren Zugriff von Formeln
247 ScDocument* pDoc; // fuer EditEngine Zugriff mit Pool
248
249 void SetTextObject( const EditTextObject* pObject,
250 const SfxItemPool* pFromPool );
251
252 // not implemented
253 ScEditCell( const ScEditCell& );
254
255 public:
256
257 #ifdef USE_MEMPOOL
258 DECL_FIXEDMEMPOOL_NEWDEL( ScEditCell )
259 #endif
260
261 ~ScEditCell(); // wegen pData immer!
262
263 ScEditCell( const EditTextObject* pObject, ScDocument*,
264 const SfxItemPool* pFromPool /* = NULL */ );
265 ScEditCell( const ScEditCell& rCell, ScDocument& rDoc );
266 // fuer Zeilenumbrueche
267 ScEditCell( const String& rString, ScDocument* );
268
269 void SetData( const EditTextObject* pObject,
270 const SfxItemPool* pFromPool /* = NULL */ );
271 void GetData( const EditTextObject*& rpObject ) const;
272 void GetString( String& rString ) const;
273
GetData() const274 const EditTextObject* GetData() const { return pData; }
275 };
276
277 // ============================================================================
278
279 enum ScMatrixMode {
280 MM_NONE = 0, // No matrix formula
281 MM_FORMULA = 1, // Upper left matrix formula cell
282 MM_REFERENCE = 2, // Remaining cells, via ocMatRef reference token
283 MM_FAKE = 3 // Interpret "as-if" matrix formula (legacy)
284 };
285
286 class SC_DLLPUBLIC ScFormulaCell : public ScBaseCell, public SvtListener
287 {
288 private:
289 ScFormulaResult aResult;
290 formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation
291 ScTokenArray* pCode; // The (new) token array
292 ScDocument* pDocument;
293 ScFormulaCell* pPrevious;
294 ScFormulaCell* pNext;
295 ScFormulaCell* pPreviousTrack;
296 ScFormulaCell* pNextTrack;
297 sal_uLong nFormatIndex; // Number format set by calculation
298 short nFormatType; // Number format type set by calculation
299 sal_uInt16 nSeenInIteration; // Iteration cycle in which the cell was last encountered
300 sal_uInt8 cMatrixFlag; // One of ScMatrixMode
301 sal_Bool bDirty : 1; // Must be (re)calculated
302 sal_Bool bChanged : 1; // Whether something changed regarding display/representation
303 sal_Bool bRunning : 1; // Already interpreting right now
304 sal_Bool bCompile : 1; // Must be (re)compiled
305 sal_Bool bSubTotal : 1; // Cell is part of or contains a SubTotal
306 sal_Bool bIsIterCell : 1; // Cell is part of a circular reference
307 sal_Bool bInChangeTrack : 1; // Cell is in ChangeTrack
308 sal_Bool bTableOpDirty : 1; // Dirty flag for TableOp
309 sal_Bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference
310 ScToken* pValidRefToken; // i120962, get the valid reference token if the cell was applied a reference formula
311
312 enum ScInterpretTailParameter
313 {
314 SCITP_NORMAL,
315 SCITP_FROM_ITERATION,
316 SCITP_CLOSE_ITERATION_CIRCLE
317 };
318 void InterpretTail( ScInterpretTailParameter );
319
320 ScFormulaCell( const ScFormulaCell& );
321
322 public:
323
324 #ifdef USE_MEMPOOL
325 DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
326 #endif
327
328 ScAddress aPos;
329
330 ~ScFormulaCell();
331 ScFormulaCell();
332
333 /** Empty formula cell, or with a preconstructed token array. */
334 ScFormulaCell( ScDocument*, const ScAddress&, const ScTokenArray* = NULL,
335 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
336 sal_uInt8 = MM_NONE );
337
338 /** With formula string and grammar to compile with.
339 formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
340 also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefor uses the address
341 convention associated with rPos::nTab by default. */
342 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
343 const String& rFormula,
344 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
345 sal_uInt8 cMatInd = MM_NONE );
346
347 ScFormulaCell( const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, int nCloneFlags = SC_CLONECELL_DEFAULT );
348
349 void GetFormula( String& rFormula,
350 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
351 void GetFormula( rtl::OUStringBuffer& rBuffer,
352 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
353
354 void SetDirty();
SetDirtyVar()355 inline void SetDirtyVar() { bDirty = sal_True; }
356 // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
357 void SetDirtyAfterLoad();
ResetTableOpDirtyVar()358 inline void ResetTableOpDirtyVar() { bTableOpDirty = sal_False; }
359 void SetTableOpDirty();
360 sal_Bool IsDirtyOrInTableOpDirty() const;
GetDirty() const361 sal_Bool GetDirty() const { return bDirty; }
NeedsListening() const362 sal_Bool NeedsListening() const { return bNeedListening; }
SetNeedsListening(sal_Bool bVar)363 void SetNeedsListening( sal_Bool bVar ) { bNeedListening = bVar; }
364 void Compile(const String& rFormula,
365 sal_Bool bNoListening = sal_False,
366 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT );
367 void CompileTokenArray( sal_Bool bNoListening = sal_False );
368 void CompileXML( ScProgress& rProgress ); // compile temporary string tokens
369 void CalcAfterLoad();
370 bool MarkUsedExternalReferences();
371 void Interpret();
IsIterCell() const372 inline sal_Bool IsIterCell() const { return bIsIterCell; }
GetSeenInIteration() const373 inline sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
374
375 sal_Bool HasOneReference( ScRange& r ) const;
376 /* Checks if the formula contains reference list that can be
377 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
378 reference list is not required to be sorted (i.e. A3;A1;A2 is
379 still recognized as A1:A3), but no overlapping is allowed.
380 If one reference is recognized, the rRange is filled.
381
382 It is similar to HasOneReference(), but more general.
383 */
384 bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
385 sal_Bool HasRelNameReference() const;
386 sal_Bool HasColRowName() const;
387
388 void UpdateReference(UpdateRefMode eUpdateRefMode,
389 const ScRange& r,
390 SCsCOL nDx, SCsROW nDy, SCsTAB nDz,
391 ScDocument* pUndoDoc = NULL,
392 const ScAddress* pUndoCellPos = NULL );
393
394 void TransposeReference();
395 void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
396 ScDocument* pUndoDoc );
397
398 void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
399
400 void UpdateInsertTab(SCTAB nTable);
401 void UpdateInsertTabAbs(SCTAB nTable);
402 sal_Bool UpdateDeleteTab(SCTAB nTable, sal_Bool bIsMove = sal_False);
403 void UpdateMoveTab(SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo);
404 void UpdateRenameTab(SCTAB nTable, const String& rName);
405 sal_Bool TestTabRefAbs(SCTAB nTable);
406 void UpdateCompile( sal_Bool bForceIfNameInUse = sal_False );
407 sal_Bool IsRangeNameInUse(sal_uInt16 nIndex) const;
408 void FindRangeNamesInUse(std::set<sal_uInt16>& rIndexes) const;
409 void ReplaceRangeNamesInUse( const ScRangeData::IndexMap& rMap );
IsSubTotal() const410 sal_Bool IsSubTotal() const { return bSubTotal; }
IsChanged() const411 sal_Bool IsChanged() const { return bChanged; }
ResetChanged()412 void ResetChanged() { bChanged = sal_False; }
413 sal_Bool IsEmpty(); // formula::svEmptyCell result
414 // display as empty string if formula::svEmptyCell result
415 sal_Bool IsEmptyDisplayedAsString();
416 sal_Bool IsValue(); // also sal_True if formula::svEmptyCell
417 double GetValue();
418 double GetValueAlways(); // ignore errors
419 void GetString( String& rString );
420 const ScMatrix* GetMatrix();
421 sal_Bool GetMatrixOrigin( ScAddress& rPos ) const;
422 void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
423 sal_uInt16 GetMatrixEdge( ScAddress& rOrgPos );
424 sal_uInt16 GetErrCode(); // interpret first if necessary
425 sal_uInt16 GetRawError(); // don't interpret, just return code or result error
GetFormatType() const426 short GetFormatType() const { return nFormatType; }
GetFormatIndex() const427 sal_uLong GetFormatIndex() const { return nFormatIndex; }
GetFormatInfo(short & nType,sal_uLong & nIndex) const428 void GetFormatInfo( short& nType, sal_uLong& nIndex ) const
429 { nType = nFormatType; nIndex = nFormatIndex; }
GetMatrixFlag() const430 sal_uInt8 GetMatrixFlag() const { return cMatrixFlag; }
GetCode() const431 ScTokenArray* GetCode() const { return pCode; }
432
IsRunning() const433 sal_Bool IsRunning() const { return bRunning; }
SetRunning(sal_Bool bVal)434 void SetRunning( sal_Bool bVal ) { bRunning = bVal; }
435 void CompileDBFormula();
436 void CompileDBFormula( sal_Bool bCreateFormulaString );
437 void CompileNameFormula( sal_Bool bCreateFormulaString );
438 void CompileColRowNameFormula();
GetPrevious() const439 ScFormulaCell* GetPrevious() const { return pPrevious; }
GetNext() const440 ScFormulaCell* GetNext() const { return pNext; }
SetPrevious(ScFormulaCell * pF)441 void SetPrevious( ScFormulaCell* pF ) { pPrevious = pF; }
SetNext(ScFormulaCell * pF)442 void SetNext( ScFormulaCell* pF ) { pNext = pF; }
GetPreviousTrack() const443 ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
GetNextTrack() const444 ScFormulaCell* GetNextTrack() const { return pNextTrack; }
SetPreviousTrack(ScFormulaCell * pF)445 void SetPreviousTrack( ScFormulaCell* pF ) { pPreviousTrack = pF; }
SetNextTrack(ScFormulaCell * pF)446 void SetNextTrack( ScFormulaCell* pF ) { pNextTrack = pF; }
447
448 virtual void Notify( SvtBroadcaster& rBC, const SfxHint& rHint);
SetCompile(sal_Bool bVal)449 void SetCompile( sal_Bool bVal ) { bCompile = bVal; }
GetDocument() const450 ScDocument* GetDocument() const { return pDocument; }
451 void SetMatColsRows( SCCOL nCols, SCROW nRows );
452 void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
453
454 // ob Zelle im ChangeTrack und nicht im echten Dokument ist
SetInChangeTrack(sal_Bool bVal)455 void SetInChangeTrack( sal_Bool bVal ) { bInChangeTrack = bVal; }
IsInChangeTrack() const456 sal_Bool IsInChangeTrack() const { return bInChangeTrack; }
457
458 // Zu Typ und Format das entsprechende Standardformat.
459 // Bei Format "Standard" evtl. das in die Formelzelle
460 // uebernommene Format.
461 sal_uLong GetStandardFormat( SvNumberFormatter& rFormatter, sal_uLong nFormat ) const;
462
463 // For import filters!
464 void AddRecalcMode( formula::ScRecalcMode );
465 /** For import only: set a double result. */
SetHybridDouble(double n)466 void SetHybridDouble( double n ) { aResult.SetHybridDouble( n); }
467 /** For import only: set a string result.
468 If for whatever reason you have to use both, SetHybridDouble() and
469 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
470 for performance reasons.*/
SetHybridString(const String & r)471 void SetHybridString( const String& r )
472 { aResult.SetHybridString( r); }
473 /** For import only: set a temporary formula string to be compiled later.
474 If for whatever reason you have to use both, SetHybridDouble() and
475 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
476 for performance reasons.*/
SetHybridFormula(const String & r,const formula::FormulaGrammar::Grammar eGrammar)477 void SetHybridFormula( const String& r,
478 const formula::FormulaGrammar::Grammar eGrammar )
479 { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; }
480 void SetErrCode( sal_uInt16 n );
IsHyperLinkCell() const481 inline sal_Bool IsHyperLinkCell() const { return pCode && pCode->IsHyperLink(); }
482 EditTextObject* CreateURLObject() ;
483 void GetURLResult( String& rURL, String& rCellText );
484
485 /** Determines whether or not the result string contains more than one paragraph */
486 bool IsMultilineResult();
GetValidRefToken()487 ScToken* GetValidRefToken() { return pValidRefToken; } // i120962
488 };
489
490 // Iterator fuer Referenzen in einer Formelzelle
491 class ScDetectiveRefIter
492 {
493 private:
494 ScTokenArray* pCode;
495 ScAddress aPos;
496 public:
497 ScDetectiveRefIter( ScFormulaCell* pCell );
498 sal_Bool GetNextRef( ScRange& rRange );
499 };
500
501 // ============================================================================
GetValueFromCell(const ScBaseCell * pCell)502 inline double GetValueFromCell( const ScBaseCell * pCell )
503 {
504 switch (pCell->GetCellType())
505 {
506 case CELLTYPE_VALUE:
507 return ((ScValueCell*)pCell)->GetValue();
508 case CELLTYPE_FORMULA:
509 {
510 if (((ScFormulaCell*)pCell)->IsValue())
511 return ((ScFormulaCell*)pCell)->GetValue();
512 else
513 return 0.0;
514 }
515 default:
516 return 0.0;
517 }
518 }
519 // ============================================================================
520
521
GetStringFromCell(const ScBaseCell * pCell,sal_uLong nFormat,SvNumberFormatter * pFormatter)522 inline String GetStringFromCell( const ScBaseCell * pCell, sal_uLong nFormat, SvNumberFormatter* pFormatter )
523 {
524 if (pCell->GetCellType() != CELLTYPE_NOTE)
525 {
526 String strResult;
527 Color* pColor = NULL;
528 ScCellFormat::GetString( const_cast<ScBaseCell*>(pCell), nFormat, strResult, &pColor, *(pFormatter) );
529 return strResult;
530 }
531 else
532 return String();
533 }
534
535 #endif
536
537