nss: upgrade to release 3.73
[LibreOffice.git] / sc / inc / formulacell.hxx
bloba6701bcbf0bd887385aa3e979794808753253c88
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #ifndef INCLUDED_SC_INC_FORMULACELL_HXX
21 #define INCLUDED_SC_INC_FORMULACELL_HXX
23 #include <memory>
25 #include <formula/tokenarray.hxx>
26 #include <formula/errorcodes.hxx>
27 #include <svl/listener.hxx>
29 #include "types.hxx"
30 #include "interpretercontext.hxx"
31 #include "document.hxx"
32 #include "docoptio.hxx"
33 #include "formulalogger.hxx"
34 #include "formularesult.hxx"
36 namespace sc {
38 class StartListeningContext;
39 class EndListeningContext;
40 struct RefUpdateContext;
41 struct RefUpdateInsertTabContext;
42 struct RefUpdateDeleteTabContext;
43 struct RefUpdateMoveTabContext;
44 class CompileFormulaContext;
45 class FormulaGroupAreaListener;
46 class UpdatedRangeNames;
50 class ScFormulaCell;
51 class ScProgress;
52 class ScTokenArray;
53 enum class SvNumFormatType : sal_Int16;
55 struct SC_DLLPUBLIC ScFormulaCellGroup
57 private:
58 struct Impl;
59 std::unique_ptr<Impl> mpImpl;
61 public:
63 mutable size_t mnRefCount;
65 std::unique_ptr<ScTokenArray> mpCode;
66 ScFormulaCell *mpTopCell;
67 SCROW mnLength; // How many of these do we have ?
68 sal_Int32 mnWeight;
69 SvNumFormatType mnFormatType;
70 bool mbInvariant:1;
71 bool mbSubTotal:1;
72 bool mbPartOfCycle:1; // To flag FG's part of a cycle
74 sal_uInt8 meCalcState;
76 ScFormulaCellGroup();
77 ScFormulaCellGroup(const ScFormulaCellGroup&) = delete;
78 const ScFormulaCellGroup& operator=(const ScFormulaCellGroup&) = delete;
79 ~ScFormulaCellGroup();
81 void setCode( const ScTokenArray& rCode );
82 void setCode( std::unique_ptr<ScTokenArray> pCode );
83 void compileCode(
84 ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram );
86 sc::FormulaGroupAreaListener* getAreaListener(
87 ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed );
89 void endAllGroupListening( ScDocument& rDoc );
92 inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
94 p->mnRefCount++;
97 inline void intrusive_ptr_release(const ScFormulaCellGroup *p)
99 if( --p->mnRefCount == 0 )
100 delete p;
103 enum class ScMatrixMode : sal_uInt8 {
104 NONE = 0, // No matrix formula
105 Formula = 1, // Upper left matrix formula cell
106 Reference = 2 // Remaining cells, via ocMatRef reference token
109 class SC_DLLPUBLIC ScFormulaCell : public SvtListener
111 private:
112 ScFormulaCellGroupRef mxGroup; // Group of formulae we're part of
113 bool bDirty : 1; // Must be (re)calculated
114 bool bTableOpDirty : 1; // Dirty flag for TableOp
115 bool bChanged : 1; // Whether something changed regarding display/representation
116 bool bRunning : 1; // Already interpreting right now
117 bool bCompile : 1; // Must be (re)compiled
118 bool bSubTotal : 1; // Cell is part of or contains a SubTotal
119 bool bIsIterCell : 1; // Cell is part of a circular reference
120 bool bInChangeTrack : 1; // Cell is in ChangeTrack
121 bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference
122 bool mbNeedsNumberFormat : 1; // set the calculated number format as hard number format
123 bool mbAllowNumberFormatChange : 1; /* allow setting further calculated
124 number formats as hard number format */
125 bool mbPostponedDirty : 1; // if cell needs to be set dirty later
126 bool mbIsExtRef : 1; // has references in ScExternalRefManager; never cleared after set
127 bool mbSeenInPath : 1; // For detecting cycle involving formula groups and singleton formulacells
128 ScMatrixMode cMatrixFlag : 8;
129 sal_uInt16 nSeenInIteration : 16; // Iteration cycle in which the cell was last encountered
130 SvNumFormatType nFormatType : 16;
131 ScFormulaResult aResult;
132 formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation
133 // If this cell is in a cell group (mxGroup!=nullptr), then this pCode is a not-owning pointer
134 // to the mxGroup's mpCode, which owns the array. If the cell is not in a group, this is an owning pointer.
135 ScTokenArray* pCode; // The token array
136 ScDocument& rDocument;
137 ScFormulaCell* pPrevious;
138 ScFormulaCell* pNext;
139 ScFormulaCell* pPreviousTrack;
140 ScFormulaCell* pNextTrack;
143 * Update reference in response to cell copy-n-paste.
145 bool UpdateReferenceOnCopy(
146 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
148 ScFormulaCell( const ScFormulaCell& ) = delete;
150 bool CheckComputeDependencies(sc::FormulaLogger::GroupScope& rScope, bool fromFirstRow,
151 SCROW nStartOffset, SCROW nEndOffset, bool bCalcDependencyOnly = false);
152 bool InterpretFormulaGroupThreading(sc::FormulaLogger::GroupScope& aScope,
153 bool& bDependencyComputed,
154 bool& bDependencyCheckFailed,
155 SCROW nStartOffset, SCROW nEndOffset);
156 bool InterpretFormulaGroupOpenCL(sc::FormulaLogger::GroupScope& aScope,
157 bool& bDependencyComputed,
158 bool& bDependencyCheckFailed);
159 bool InterpretInvariantFormulaGroup();
161 public:
164 enum ScInterpretTailParameter
166 SCITP_NORMAL,
167 SCITP_FROM_ITERATION,
168 SCITP_CLOSE_ITERATION_CIRCLE
170 void InterpretTail( ScInterpreterContext&, ScInterpretTailParameter );
172 void HandleStuffAfterParallelCalculation(ScInterpreter* pInterpreter);
174 enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef };
176 ScAddress aPos;
178 virtual ~ScFormulaCell() override;
180 ScFormulaCell* Clone() const;
181 ScFormulaCell* Clone( const ScAddress& rPos ) const;
183 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos );
186 * Transfer the ownership of the passed token array instance to the
187 * formula cell being constructed. The caller <i>must not</i> pass a NULL
188 * token array pointer.
190 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, std::unique_ptr<ScTokenArray> pArray,
191 const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
192 ScMatrixMode cMatInd = ScMatrixMode::NONE );
194 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, const ScTokenArray& rArray,
195 const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
196 ScMatrixMode cMatInd = ScMatrixMode::NONE );
198 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup,
199 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
200 ScMatrixMode = ScMatrixMode::NONE );
202 /** With formula string and grammar to compile with.
203 formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
204 also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefore uses the address
205 convention associated with rPos::nTab by default. */
206 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos,
207 const OUString& rFormula,
208 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
209 ScMatrixMode cMatInd = ScMatrixMode::NONE );
211 ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, ScCloneFlags nCloneFlags = ScCloneFlags::Default);
213 size_t GetHash() const;
215 ScFormulaVectorState GetVectorState() const;
217 void GetFormula( OUString& rFormula,
218 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
219 const ScInterpreterContext* pContext = nullptr ) const;
220 void GetFormula( OUStringBuffer& rBuffer,
221 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
222 const ScInterpreterContext* pContext = nullptr ) const;
224 OUString GetFormula( sc::CompileFormulaContext& rCxt, const ScInterpreterContext* pContext = nullptr ) const;
226 void SetDirty( bool bDirtyFlag=true );
227 void SetDirtyVar();
228 // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
229 void SetDirtyAfterLoad();
230 void ResetTableOpDirtyVar();
231 void SetTableOpDirty();
233 bool IsDirtyOrInTableOpDirty() const
235 return bDirty || (bTableOpDirty && rDocument.IsInInterpreterTableOp());
238 bool GetDirty() const { return bDirty; }
239 void ResetDirty();
240 bool NeedsListening() const { return bNeedListening; }
241 void SetNeedsListening( bool bVar );
242 void SetNeedsDirty( bool bVar );
243 void SetNeedNumberFormat( bool bVal );
244 bool NeedsNumberFormat() const { return mbNeedsNumberFormat;}
245 SvNumFormatType GetFormatType() const { return nFormatType; }
246 void Compile(const OUString& rFormula,
247 bool bNoListening,
248 const formula::FormulaGrammar::Grammar );
249 void Compile(
250 sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening = false );
252 void CompileTokenArray( bool bNoListening = false );
253 void CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening = false );
254 void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); // compile temporary string tokens
255 void CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening );
256 bool MarkUsedExternalReferences();
257 bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
258 bool IsIterCell() const { return bIsIterCell; }
259 sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
261 bool HasOneReference( ScRange& r ) const;
262 /* Checks if the formula contains reference list that can be
263 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
264 reference list is not required to be sorted (i.e. A3;A1;A2 is
265 still recognized as A1:A3), but no overlapping is allowed.
266 If one reference is recognized, the rRange is filled.
268 It is similar to HasOneReference(), but more general.
270 bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
272 enum class RelNameRef
274 NONE, ///< no relative reference from named expression
275 SINGLE, ///< only single cell relative reference
276 DOUBLE ///< at least one range relative reference from named expression
278 RelNameRef HasRelNameReference() const;
280 bool UpdateReference(
281 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
284 * Shift the position of formula cell as part of reference update.
286 * @return true if the position has shifted, false otherwise.
288 bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
291 * Update reference in response to cell insertion or deletion.
293 bool UpdateReferenceOnShift(
294 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
297 * Update reference in response to cell move.
299 bool UpdateReferenceOnMove(
300 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
302 void TransposeReference();
303 void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
304 ScDocument* pUndoDoc );
306 void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
308 void UpdateInsertTab( const sc::RefUpdateInsertTabContext& rCxt );
309 void UpdateInsertTabAbs(SCTAB nTable);
310 void UpdateDeleteTab( const sc::RefUpdateDeleteTabContext& rCxt );
311 void UpdateMoveTab( const sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo );
312 bool TestTabRefAbs(SCTAB nTable);
313 void UpdateCompile( bool bForceIfNameInUse );
314 void FindRangeNamesInUse(sc::UpdatedRangeNames& rIndexes) const;
315 bool IsSubTotal() const { return bSubTotal;}
316 bool IsChanged() const { return bChanged;}
317 void SetChanged(bool b);
318 bool IsEmpty(); // formula::svEmptyCell result
319 // display as empty string if formula::svEmptyCell result
320 bool IsEmptyDisplayedAsString();
321 bool IsValue(); // also true if formula::svEmptyCell
322 bool IsValueNoError();
323 bool IsValueNoError() const;
324 double GetValue();
325 svl::SharedString GetString();
328 * Get a numeric value without potentially triggering re-calculation.
330 double GetRawValue() const;
333 * Get a string value without potentially triggering re-calculation.
335 svl::SharedString GetRawString() const;
336 const ScMatrix* GetMatrix();
337 bool GetMatrixOrigin( const ScDocument& rDoc, ScAddress& rPos ) const;
338 void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
339 sc::MatrixEdge GetMatrixEdge( const ScDocument& rDoc, ScAddress& rOrgPos ) const;
340 FormulaError GetErrCode(); // interpret first if necessary
341 FormulaError GetRawError() const; // don't interpret, just return code or result error
342 bool GetErrorOrValue( FormulaError& rErr, double& rVal );
343 sc::FormulaResultValue GetResult();
344 sc::FormulaResultValue GetResult() const;
345 ScMatrixMode GetMatrixFlag() const { return cMatrixFlag;}
346 ScTokenArray* GetCode() { return pCode;}
347 const ScTokenArray* GetCode() const { return pCode;}
349 void SetCode( std::unique_ptr<ScTokenArray> pNew );
351 bool IsRunning() const { return bRunning;}
352 void SetRunning( bool bVal );
353 void CompileDBFormula( sc::CompileFormulaContext& rCxt );
354 void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
355 ScFormulaCell* GetPrevious() const { return pPrevious; }
356 ScFormulaCell* GetNext() const { return pNext; }
357 void SetPrevious( ScFormulaCell* pF );
358 void SetNext( ScFormulaCell* pF );
359 ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
360 ScFormulaCell* GetNextTrack() const { return pNextTrack; }
361 void SetPreviousTrack( ScFormulaCell* pF );
362 void SetNextTrack( ScFormulaCell* pF );
364 virtual void Notify( const SfxHint& rHint ) override;
365 virtual void Query( SvtListener::QueryBase& rQuery ) const override;
367 void SetCompile( bool bVal );
368 ScDocument& GetDocument() const { return rDocument;}
369 void SetMatColsRows( SCCOL nCols, SCROW nRows );
370 void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
372 // cell belongs to ChangeTrack and not to the real document
373 void SetInChangeTrack( bool bVal );
374 bool IsInChangeTrack() const { return bInChangeTrack;}
376 // For import filters!
377 void AddRecalcMode( ScRecalcMode );
378 /** For import only: set a double result. */
379 void SetHybridDouble( double n );
380 /** For import only: set a string result.
381 If for whatever reason you have to use both, SetHybridDouble() and
382 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
383 for performance reasons.*/
384 void SetHybridString( const svl::SharedString& r );
385 /** For import only: set an empty cell result to be displayed as empty string.
386 If for whatever reason you have to use both, SetHybridDouble() and
387 SetHybridEmptyDisplayedAsString() or SetHybridFormula(), use
388 SetHybridDouble() first for performance reasons and use
389 SetHybridEmptyDisplayedAsString() last because SetHybridDouble() and
390 SetHybridString() will override it.*/
391 void SetHybridEmptyDisplayedAsString();
392 /** For import only: set a temporary formula string to be compiled later.
393 If for whatever reason you have to use both, SetHybridDouble() and
394 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
395 for performance reasons.*/
396 void SetHybridFormula(
397 const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
399 const OUString& GetHybridFormula() const;
401 void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL );
403 /** For import only: set a double result.
404 Use this instead of SetHybridDouble() if there is no (temporary)
405 formula string because the formula is present as a token array, as it
406 is the case for binary Excel import.
408 void SetResultDouble( double n );
410 void SetResultToken( const formula::FormulaToken* pToken );
412 svl::SharedString GetResultString() const;
414 bool HasHybridStringResult() const;
416 /* Sets the shared code array to error state in addition to the cell result */
417 void SetErrCode( FormulaError n );
419 /* Sets just the result to error */
420 void SetResultError( FormulaError n );
422 bool IsHyperLinkCell() const;
423 std::unique_ptr<EditTextObject> CreateURLObject();
424 void GetURLResult( OUString& rURL, OUString& rCellText );
426 /** Determines whether or not the result string contains more than one paragraph */
427 bool IsMultilineResult();
429 bool NeedsInterpret() const
431 if (bIsIterCell)
432 // Shortcut to force return of current value and not enter Interpret()
433 // as we're looping over all iteration cells.
434 return false;
436 if (!IsDirtyOrInTableOpDirty())
437 return false;
439 return (rDocument.GetAutoCalc() || (cMatrixFlag != ScMatrixMode::NONE));
442 void MaybeInterpret()
444 if (NeedsInterpret())
446 if (bRunning && !rDocument.GetDocOptions().IsIter() && rDocument.IsThreadedGroupCalcInProgress())
448 // This is actually copied from Interpret()'s if(bRunning)
449 // block that once caught this circular reference but now is
450 // prepended with various threaded group calc things which the
451 // assert() below is supposed to fail on when entering again.
452 // Nevertheless, we need some state here the caller can obtain.
453 aResult.SetResultError( FormulaError::CircularReference );
455 else
457 assert(!rDocument.IsThreadedGroupCalcInProgress());
458 Interpret();
464 * Turn a non-grouped cell into the top of a grouped cell.
466 ScFormulaCellGroupRef CreateCellGroup( SCROW nLen, bool bInvariant );
467 const ScFormulaCellGroupRef& GetCellGroup() const { return mxGroup;}
468 void SetCellGroup( const ScFormulaCellGroupRef &xRef );
470 CompareState CompareByTokenArray( const ScFormulaCell& rOther ) const;
472 bool InterpretFormulaGroup(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
474 // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
475 void StartListeningTo( ScDocument& rDoc );
476 void StartListeningTo( sc::StartListeningContext& rCxt );
477 void EndListeningTo(
478 ScDocument& rDoc, ScTokenArray* pArr = nullptr, ScAddress aPos = ScAddress() );
479 void EndListeningTo( sc::EndListeningContext& rCxt );
481 bool IsShared() const;
482 bool IsSharedTop() const;
483 SCROW GetSharedTopRow() const;
484 SCROW GetSharedLength() const;
486 // An estimate of the number of cells referenced by the formula
487 sal_Int32 GetWeight() const;
489 ScTokenArray* GetSharedCode();
490 const ScTokenArray* GetSharedCode() const;
492 void SyncSharedCode();
494 bool IsPostponedDirty() const { return mbPostponedDirty;}
496 void SetIsExtRef() { mbIsExtRef = true; }
497 bool GetSeenInPath() const { return mbSeenInPath; }
498 void SetSeenInPath(bool bSet) { mbSeenInPath = bSet; }
500 #if DUMP_COLUMN_STORAGE
501 void Dump() const;
502 #endif
505 #endif
507 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */