LibreOffice Module sc (master)  1
formulacell.hxx
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
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/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
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 .
18  */
19 
20 #ifndef INCLUDED_SC_INC_FORMULACELL_HXX
21 #define INCLUDED_SC_INC_FORMULACELL_HXX
22 
23 #include <memory>
24 
25 #include <formula/tokenarray.hxx>
26 #include <svl/listener.hxx>
27 
28 #include "types.hxx"
29 #include "interpretercontext.hxx"
30 #include "document.hxx"
31 #include "formulalogger.hxx"
32 #include "formularesult.hxx"
33 
34 namespace sc {
35 
36 class StartListeningContext;
37 class EndListeningContext;
38 struct RefUpdateContext;
39 struct RefUpdateInsertTabContext;
40 struct RefUpdateDeleteTabContext;
41 struct RefUpdateMoveTabContext;
42 class CompileFormulaContext;
43 class FormulaGroupAreaListener;
44 class UpdatedRangeNames;
45 
46 }
47 
48 class ScFormulaCell;
49 class ScProgress;
50 class ScTokenArray;
51 enum class SvNumFormatType : sal_Int16;
52 
54 {
55 private:
56  struct Impl;
57  std::unique_ptr<Impl> mpImpl;
58 
59 public:
60 
61  mutable size_t mnRefCount;
62 
63  std::unique_ptr<ScTokenArray> mpCode;
65  SCROW mnLength; // How many of these do we have ?
66  sal_Int32 mnWeight;
68  bool mbInvariant:1;
69  bool mbSubTotal:1;
70  bool mbPartOfCycle:1; // To flag FG's part of a cycle
71 
73 
75  ScFormulaCellGroup(const ScFormulaCellGroup&) = delete;
76  const ScFormulaCellGroup& operator=(const ScFormulaCellGroup&) = delete;
78 
79  void setCode( const ScTokenArray& rCode );
80  void setCode( std::unique_ptr<ScTokenArray> pCode );
81  void compileCode(
82  ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram );
83 
85  ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed );
86 
87  void endAllGroupListening( ScDocument& rDoc );
88 };
89 
91 {
92  p->mnRefCount++;
93 }
94 
96 {
97  if( --p->mnRefCount == 0 )
98  delete p;
99 }
100 
101 enum class ScMatrixMode : sal_uInt8 {
102  NONE = 0, // No matrix formula
103  Formula = 1, // Upper left matrix formula cell
104  Reference = 2 // Remaining cells, via ocMatRef reference token
105 };
106 
108 {
109 private:
110  ScFormulaCellGroupRef mxGroup; // Group of formulae we're part of
111  bool bDirty : 1; // Must be (re)calculated
112  bool bTableOpDirty : 1; // Dirty flag for TableOp
113  bool bChanged : 1; // Whether something changed regarding display/representation
114  bool bRunning : 1; // Already interpreting right now
115  bool bCompile : 1; // Must be (re)compiled
116  bool bSubTotal : 1; // Cell is part of or contains a SubTotal
117  bool bIsIterCell : 1; // Cell is part of a circular reference
118  bool bInChangeTrack : 1; // Cell is in ChangeTrack
119  bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference
120  bool mbNeedsNumberFormat : 1; // set the calculated number format as hard number format
121  bool mbAllowNumberFormatChange : 1; /* allow setting further calculated
122  number formats as hard number format */
123  bool mbPostponedDirty : 1; // if cell needs to be set dirty later
124  bool mbIsExtRef : 1; // has references in ScExternalRefManager; never cleared after set
125  bool mbSeenInPath : 1; // For detecting cycle involving formula groups and singleton formulacells
126  ScMatrixMode cMatrixFlag : 8;
127  sal_uInt16 nSeenInIteration : 16; // Iteration cycle in which the cell was last encountered
128  SvNumFormatType nFormatType : 16;
130  formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation
131  // If this cell is in a cell group (mxGroup!=nullptr), then this pCode is a not-owning pointer
132  // to the mxGroup's mpCode, which owns the array. If the cell is not in a group, this is an owning pointer.
133  ScTokenArray* pCode; // The token array
139 
143  bool UpdateReferenceOnCopy(
144  const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
145 
146  ScFormulaCell( const ScFormulaCell& ) = delete;
147 
148  bool CheckComputeDependencies(sc::FormulaLogger::GroupScope& rScope, bool fromFirstRow,
149  SCROW nStartOffset, SCROW nEndOffset, bool bCalcDependencyOnly = false);
150  bool InterpretFormulaGroupThreading(sc::FormulaLogger::GroupScope& aScope,
151  bool& bDependencyComputed,
152  bool& bDependencyCheckFailed,
153  SCROW nStartOffset, SCROW nEndOffset);
154  bool InterpretFormulaGroupOpenCL(sc::FormulaLogger::GroupScope& aScope,
155  bool& bDependencyComputed,
156  bool& bDependencyCheckFailed);
157  bool InterpretInvariantFormulaGroup();
158 
159 public:
160 
161 
163  {
166  SCITP_CLOSE_ITERATION_CIRCLE
167  };
168  void InterpretTail( ScInterpreterContext&, ScInterpretTailParameter );
169 
170  void HandleStuffAfterParallelCalculation(ScInterpreter* pInterpreter);
171 
172  enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef };
173 
175 
176  virtual ~ScFormulaCell() override;
177 
178  ScFormulaCell* Clone() const;
179  ScFormulaCell* Clone( const ScAddress& rPos ) const;
180 
181  ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos );
182 
188  ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, std::unique_ptr<ScTokenArray> pArray,
190  ScMatrixMode cMatInd = ScMatrixMode::NONE );
191 
192  ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
194  ScMatrixMode cMatInd = ScMatrixMode::NONE );
195 
196  ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup,
199 
204  ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
205  const OUString& rFormula,
207  ScMatrixMode cMatInd = ScMatrixMode::NONE );
208 
209  ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, ScCloneFlags nCloneFlags = ScCloneFlags::Default);
210 
211  size_t GetHash() const;
212 
213  ScFormulaVectorState GetVectorState() const;
214 
215  void GetFormula( OUString& rFormula,
217  const ScInterpreterContext* pContext = nullptr ) const;
218  void GetFormula( OUStringBuffer& rBuffer,
220  const ScInterpreterContext* pContext = nullptr ) const;
221 
222  OUString GetFormula( sc::CompileFormulaContext& rCxt, const ScInterpreterContext* pContext = nullptr ) const;
223 
224  void SetDirty( bool bDirtyFlag=true );
225  void SetDirtyVar();
226  // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
227  void SetDirtyAfterLoad();
228  void ResetTableOpDirtyVar();
229  void SetTableOpDirty();
230 
232  {
233  return bDirty || (bTableOpDirty && pDocument->IsInInterpreterTableOp());
234  }
235 
236  bool GetDirty() const { return bDirty; }
237  void ResetDirty();
238  bool NeedsListening() const { return bNeedListening; }
239  void SetNeedsListening( bool bVar );
240  void SetNeedsDirty( bool bVar );
241  void SetNeedNumberFormat( bool bVal );
242  bool NeedsNumberFormat() const { return mbNeedsNumberFormat;}
243  SvNumFormatType GetFormatType() const { return nFormatType; }
244  void Compile(const OUString& rFormula,
245  bool bNoListening,
247  void Compile(
248  sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening = false );
249 
250  void CompileTokenArray( bool bNoListening = false );
251  void CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening = false );
252  void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); // compile temporary string tokens
253  void CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening );
254  bool MarkUsedExternalReferences();
255  bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
256  bool IsIterCell() const { return bIsIterCell; }
257  sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
258 
259  bool HasOneReference( ScRange& r ) const;
260  /* Checks if the formula contains reference list that can be
261  expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
262  reference list is not required to be sorted (i.e. A3;A1;A2 is
263  still recognized as A1:A3), but no overlapping is allowed.
264  If one reference is recognized, the rRange is filled.
265 
266  It is similar to HasOneReference(), but more general.
267  */
268  bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
269 
270  enum class RelNameRef
271  {
272  NONE,
273  SINGLE,
274  DOUBLE
275  };
276  RelNameRef HasRelNameReference() const;
277 
278  bool UpdateReference(
279  const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
280 
286  bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
287 
291  bool UpdateReferenceOnShift(
292  const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
293 
297  bool UpdateReferenceOnMove(
298  const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
299 
300  void TransposeReference();
301  void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
302  ScDocument* pUndoDoc );
303 
304  void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
305 
306  void UpdateInsertTab( const sc::RefUpdateInsertTabContext& rCxt );
307  void UpdateInsertTabAbs(SCTAB nTable);
308  void UpdateDeleteTab( const sc::RefUpdateDeleteTabContext& rCxt );
309  void UpdateMoveTab( const sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo );
310  bool TestTabRefAbs(SCTAB nTable);
311  void UpdateCompile( bool bForceIfNameInUse );
312  void FindRangeNamesInUse(sc::UpdatedRangeNames& rIndexes) const;
313  bool IsSubTotal() const { return bSubTotal;}
314  bool IsChanged() const { return bChanged;}
315  void SetChanged(bool b);
316  bool IsEmpty(); // formula::svEmptyCell result
317  // display as empty string if formula::svEmptyCell result
318  bool IsEmptyDisplayedAsString();
319  bool IsValue(); // also true if formula::svEmptyCell
320  bool IsValueNoError();
321  bool IsValueNoError() const;
322  double GetValue();
324 
328  double GetRawValue() const;
329 
333  svl::SharedString GetRawString() const;
334  const ScMatrix* GetMatrix();
335  bool GetMatrixOrigin( const ScDocument* pDoc, ScAddress& rPos ) const;
336  void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
337  sc::MatrixEdge GetMatrixEdge( const ScDocument* pDoc, ScAddress& rOrgPos ) const;
338  FormulaError GetErrCode(); // interpret first if necessary
339  FormulaError GetRawError() const; // don't interpret, just return code or result error
340  bool GetErrorOrValue( FormulaError& rErr, double& rVal );
341  sc::FormulaResultValue GetResult();
342  sc::FormulaResultValue GetResult() const;
343  ScMatrixMode GetMatrixFlag() const { return cMatrixFlag;}
344  ScTokenArray* GetCode() { return pCode;}
345  const ScTokenArray* GetCode() const { return pCode;}
346 
347  void SetCode( std::unique_ptr<ScTokenArray> pNew );
348 
349  bool IsRunning() const { return bRunning;}
350  void SetRunning( bool bVal );
351  void CompileDBFormula( sc::CompileFormulaContext& rCxt );
352  void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
353  ScFormulaCell* GetPrevious() const { return pPrevious; }
354  ScFormulaCell* GetNext() const { return pNext; }
355  void SetPrevious( ScFormulaCell* pF );
356  void SetNext( ScFormulaCell* pF );
357  ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
358  ScFormulaCell* GetNextTrack() const { return pNextTrack; }
359  void SetPreviousTrack( ScFormulaCell* pF );
360  void SetNextTrack( ScFormulaCell* pF );
361 
362  virtual void Notify( const SfxHint& rHint ) override;
363  virtual void Query( SvtListener::QueryBase& rQuery ) const override;
364 
365  void SetCompile( bool bVal );
366  ScDocument* GetDocument() const { return pDocument;}
367  void SetMatColsRows( SCCOL nCols, SCROW nRows );
368  void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
369 
370  // cell belongs to ChangeTrack and not to the real document
371  void SetInChangeTrack( bool bVal );
372  bool IsInChangeTrack() const { return bInChangeTrack;}
373 
374  // For import filters!
375  void AddRecalcMode( ScRecalcMode );
377  void SetHybridDouble( double n );
382  void SetHybridString( const svl::SharedString& r );
389  void SetHybridEmptyDisplayedAsString();
394  void SetHybridFormula(
395  const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
396 
397  const OUString& GetHybridFormula() const;
398 
399  void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL );
400 
406  void SetResultDouble( double n );
407 
408  void SetResultToken( const formula::FormulaToken* pToken );
409 
410  svl::SharedString GetResultString() const;
411 
412  bool HasHybridStringResult() const;
413 
414  /* Sets the shared code array to error state in addition to the cell result */
415  void SetErrCode( FormulaError n );
416 
417  /* Sets just the result to error */
418  void SetResultError( FormulaError n );
419 
420  bool IsHyperLinkCell() const;
421  std::unique_ptr<EditTextObject> CreateURLObject();
422  void GetURLResult( OUString& rURL, OUString& rCellText );
423 
425  bool IsMultilineResult();
426 
427  bool NeedsInterpret() const
428  {
429  if (bIsIterCell)
430  // Shortcut to force return of current value and not enter Interpret()
431  // as we're looping over all iteration cells.
432  return false;
433 
434  if (!IsDirtyOrInTableOpDirty())
435  return false;
436 
437  return (pDocument->GetAutoCalc() || (cMatrixFlag != ScMatrixMode::NONE));
438  }
439 
441  {
442  if (NeedsInterpret())
443  {
444  assert(!pDocument->IsThreadedGroupCalcInProgress());
445  Interpret();
446  return true;
447  }
448  return false;
449  }
450 
454  ScFormulaCellGroupRef CreateCellGroup( SCROW nLen, bool bInvariant );
455  const ScFormulaCellGroupRef& GetCellGroup() const { return mxGroup;}
456  void SetCellGroup( const ScFormulaCellGroupRef &xRef );
457 
458  CompareState CompareByTokenArray( const ScFormulaCell& rOther ) const;
459 
460  bool InterpretFormulaGroup(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
461 
462  // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
463  void StartListeningTo( ScDocument* pDoc );
464  void StartListeningTo( sc::StartListeningContext& rCxt );
465  void EndListeningTo(
466  ScDocument* pDoc, ScTokenArray* pArr = nullptr, ScAddress aPos = ScAddress() );
467  void EndListeningTo( sc::EndListeningContext& rCxt );
468 
469  bool IsShared() const;
470  bool IsSharedTop() const;
471  SCROW GetSharedTopRow() const;
472  SCROW GetSharedLength() const;
473 
474  // An estimate of the number of cells referenced by the formula
475  sal_Int32 GetWeight() const;
476 
477  ScTokenArray* GetSharedCode();
478  const ScTokenArray* GetSharedCode() const;
479 
480  void SyncSharedCode();
481 
482  bool IsPostponedDirty() const { return mbPostponedDirty;}
483 
484  void SetIsExtRef() { mbIsExtRef = true; }
485  bool GetSeenInPath() const { return mbSeenInPath; }
486  void SetSeenInPath(bool bSet) { mbSeenInPath = bSet; }
487 
488 #if DUMP_COLUMN_STORAGE
489  void Dump() const;
490 #endif
491 };
492 
493 #endif
494 
495 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:113
Default cell clone flags: do not start listening, do not adjust 3D refs to old position, clone note captions of cell notes.
::boost::intrusive_ptr< ScFormulaCellGroup > ScFormulaCellGroupRef
Definition: types.hxx:44
bool GetSeenInPath() const
bool NeedsInterpret() const
ScCloneFlags
Definition: global.hxx:261
bool NeedsListening() const
std::string GetValue
ScDocument * GetDocument() const
ScRecalcMode
ScTokenArray * GetCode()
bool GetDirty() const
Context for reference update during shifting, moving or copying of cell ranges.
sc::FormulaGroupAreaListener * getAreaListener(ScFormulaCell **ppTopCell, const ScRange &rRange, bool bStartFixed, bool bEndFixed)
std::unique_ptr< ScTokenArray > mpCode
Definition: formulacell.hxx:63
ScFormulaCell * GetPreviousTrack() const
bool IsIterCell() const
sal_uInt16 GetSeenInIteration() const
void SetIsExtRef()
formula::FormulaGrammar::Grammar eTempGrammar
NONE
const ScFormulaCellGroupRef & GetCellGroup() const
bool IsPostponedDirty() const
size_t SCSIZE
size_t typedef to be able to find places where code was changed from USHORT to size_t and is used to ...
Definition: address.hxx:45
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
void setCode(const ScTokenArray &rCode)
Store a variable formula cell result, balancing between runtime performance and memory consumption...
virtual void Query(QueryBase &rQuery) const
ScAddress aPos
SvNumFormatType GetFormatType() const
bool IsChanged() const
Keep track of all named expressions that have been updated during reference update.
ScTokenArray * pCode
Reference< XAnimationNode > Clone(const Reference< XAnimationNode > &xSourceNode, const SdPage *pSource, const SdPage *pTarget)
bool NeedsNumberFormat() const
void SetSeenInPath(bool bSet)
bool MaybeInterpret()
sal_Int16 SCCOL
Definition: types.hxx:22
void intrusive_ptr_release(const ScFormulaCellGroup *p)
Definition: formulacell.hxx:95
ScFormulaCell * GetNextTrack() const
bool IsInInterpreterTableOp() const
Definition: document.hxx:2342
ScFormulaCell * pNext
SvNumFormatType
bool IsDirtyOrInTableOpDirty() const
bool IsRunning() const
ScFormulaCell * GetNext() const
#define DOUBLE
void endAllGroupListening(ScDocument &rDoc)
FormulaError
ScFormulaCellGroupRef mxGroup
ScFormulaCell * GetPrevious() const
const ScTokenArray * GetCode() const
sal_Int32 SCROW
Definition: types.hxx:18
bool IsThreadedGroupCalcInProgress() const
Definition: document.hxx:628
bool IsSubTotal() const
ScFormulaCell * pPreviousTrack
sal_uInt8 meCalcState
Definition: formulacell.hxx:72
std::unique_ptr< Impl > mpImpl
Definition: formulacell.hxx:56
unsigned char sal_uInt8
::boost::intrusive_ptr< const ScMatrix > ScConstMatrixRef
Definition: types.hxx:27
virtual void Notify(const SfxHint &rHint)
void compileCode(ScDocument &rDoc, const ScAddress &rPos, formula::FormulaGrammar::Grammar eGram)
ScMatrixMode
ScDocument * pDocument
ScFormulaResult aResult
bool IsInChangeTrack() const
ScFormulaVectorState
When vectorization is enabled, we could potentially mass-calculate a series of formula token arrays i...
Definition: types.hxx:52
ScFormulaCell * pPrevious
ScFormulaCell * mpTopCell
Definition: formulacell.hxx:64
void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
Definition: formulacell.hxx:90
MatrixEdge
Definition: types.hxx:66
SvNumFormatType mnFormatType
Definition: formulacell.hxx:67
ScMatrixMode GetMatrixFlag() const
#define SC_DLLPUBLIC
Definition: scdllapi.h:28
ScFormulaCell * pNextTrack
const ScFormulaCellGroup & operator=(const ScFormulaCellGroup &)=delete
sal_Int16 SCTAB
Definition: types.hxx:23
SC_DLLPUBLIC bool GetAutoCalc() const
Definition: document.hxx:1363
OUString GetString(double f, bool bLeadingSign, sal_uInt16 nMaxDig)