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#pragma once
21
22#include <map>
23#include <memory>
24#include <optional>
25
28#include <svl/listener.hxx>
29
30#include "types.hxx"
32#include "document.hxx"
33#include "docoptio.hxx"
34#include "formulalogger.hxx"
35#include "formularesult.hxx"
36#include "tokenarray.hxx"
37#include "grouparealistener.hxx"
38
39namespace sc {
40
41class StartListeningContext;
42class EndListeningContext;
43struct RefUpdateContext;
44struct RefUpdateInsertTabContext;
45struct RefUpdateDeleteTabContext;
46struct RefUpdateMoveTabContext;
47class CompileFormulaContext;
48class UpdatedRangeNames;
49
50}
51
52class ScFormulaCell;
53class ScProgress;
54enum class SvNumFormatType : sal_Int16;
55
57{
61
62 AreaListenerKey( const ScRange& rRange, bool bStartFixed, bool bEndFixed ) :
63 maRange(rRange), mbStartFixed(bStartFixed), mbEndFixed(bEndFixed) {}
64
65 bool operator < ( const AreaListenerKey& r ) const;
66};
67
68typedef std::map<AreaListenerKey, sc::FormulaGroupAreaListener> AreaListenersType;
69
71{
73public:
74
75 mutable size_t mnRefCount;
76
77 std::optional<ScTokenArray> mpCode;
79 SCROW mnLength; // How many of these do we have ?
80 sal_Int32 mnWeight;
83 bool mbSubTotal:1;
84 bool mbPartOfCycle:1; // To flag FG's part of a cycle
85
87
92
93 void setCode( const ScTokenArray& rCode );
94 void compileCode(
95 ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram );
96
97 sc::FormulaGroupAreaListener* getAreaListener(
98 ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed );
99
100 void endAllGroupListening( ScDocument& rDoc );
101};
102
104{
105 p->mnRefCount++;
106}
107
109{
110 if( --p->mnRefCount == 0 )
111 delete p;
112}
113
115 NONE = 0, // No matrix formula
116 Formula = 1, // Upper left matrix formula cell
117 Reference = 2 // Remaining cells, via ocMatRef reference token
118};
119
121{
122private:
123 ScFormulaCellGroupRef mxGroup; // Group of formulae we're part of
124 bool bDirty : 1; // Must be (re)calculated
125 bool bTableOpDirty : 1; // Dirty flag for TableOp
126 bool bChanged : 1; // Whether something changed regarding display/representation
127 bool bRunning : 1; // Already interpreting right now
128 bool bCompile : 1; // Must be (re)compiled
129 bool bSubTotal : 1; // Cell is part of or contains a SubTotal
130 bool bIsIterCell : 1; // Cell is part of a circular reference
131 bool bInChangeTrack : 1; // Cell is in ChangeTrack
132 bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference
133 bool mbNeedsNumberFormat : 1; // set the calculated number format as hard number format
134 bool mbAllowNumberFormatChange : 1; /* allow setting further calculated
135 number formats as hard number format */
136 bool mbPostponedDirty : 1; // if cell needs to be set dirty later
137 bool mbIsExtRef : 1; // has references in ScExternalRefManager; never cleared after set
138 bool mbSeenInPath : 1; // For detecting cycle involving formula groups and singleton formulacells
139 bool mbFreeFlying : 1; // Cell is out of sheets interpreted, like in conditional format
141 sal_uInt16 nSeenInIteration : 16; // Iteration cycle in which the cell was last encountered
144 formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation
145 // If this cell is in a cell group (mxGroup!=nullptr), then this pCode is a not-owning pointer
146 // to the mxGroup's mpCode, which owns the array. If the cell is not in a group, this is an owning pointer.
147 ScTokenArray* pCode; // The token array
153
157 bool UpdateReferenceOnCopy(
158 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
159
160 ScFormulaCell( const ScFormulaCell& ) = delete;
161
162 bool CheckComputeDependencies(sc::FormulaLogger::GroupScope& rScope, bool fromFirstRow,
163 SCROW nStartOffset, SCROW nEndOffset, bool bCalcDependencyOnly = false);
164 bool InterpretFormulaGroupThreading(sc::FormulaLogger::GroupScope& aScope,
165 bool& bDependencyComputed,
166 bool& bDependencyCheckFailed,
167 SCROW nStartOffset, SCROW nEndOffset);
168 bool InterpretFormulaGroupOpenCL(sc::FormulaLogger::GroupScope& aScope,
169 bool& bDependencyComputed,
170 bool& bDependencyCheckFailed);
171 bool InterpretInvariantFormulaGroup();
172
173public:
174
175
177 {
180 SCITP_CLOSE_ITERATION_CIRCLE
181 };
182 void InterpretTail( ScInterpreterContext&, ScInterpretTailParameter );
183
184 void HandleStuffAfterParallelCalculation(ScInterpreter* pInterpreter);
185
186 enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef };
187
189
190 virtual ~ScFormulaCell() override;
191
192 ScFormulaCell* Clone() const;
193 ScFormulaCell* Clone( const ScAddress& rPos ) const;
194
195 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos );
196
202 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, std::unique_ptr<ScTokenArray> pArray,
205
206 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, const ScTokenArray& rArray,
209
210 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup,
213
218 ScFormulaCell( ScDocument& rDoc, const ScAddress& rPos,
219 const OUString& rFormula,
222
223 ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, ScCloneFlags nCloneFlags = ScCloneFlags::Default);
224
225 void SetFreeFlying( bool b ) { mbFreeFlying = b; }
226
227 size_t GetHash() const;
228
230 const ScInterpreterContext* pContext = nullptr ) const;
231 OUString GetFormula( sc::CompileFormulaContext& rCxt, const ScInterpreterContext* pContext = nullptr ) const;
232
233 void SetDirty( bool bDirtyFlag=true );
234 void SetDirtyVar();
235 // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
236 void SetDirtyAfterLoad();
237 void ResetTableOpDirtyVar();
238 void SetTableOpDirty();
239
241 {
242 return bDirty || (bTableOpDirty && rDocument.IsInInterpreterTableOp());
243 }
244
245 bool GetDirty() const { return bDirty; }
246 void ResetDirty();
247 bool NeedsListening() const { return bNeedListening; }
248 void SetNeedsListening( bool bVar );
249 void SetNeedsDirty( bool bVar );
250 void SetNeedNumberFormat( bool bVal );
251 bool NeedsNumberFormat() const { return mbNeedsNumberFormat;}
252 SvNumFormatType GetFormatType() const { return nFormatType; }
253 void Compile(const OUString& rFormula,
254 bool bNoListening,
256 void Compile(
257 sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening = false );
258
259 void CompileTokenArray( bool bNoListening = false );
260 void CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening = false );
261 void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); // compile temporary string tokens
262 void CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening );
263 bool MarkUsedExternalReferences();
264 // Returns true if the cell was interpreted as part of the formula group.
265 // The parameters may limit which subset of the formula group should be interpreted, if possible.
266 bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
267 bool IsIterCell() const { return bIsIterCell; }
268 sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
269
270 bool HasOneReference( ScRange& r ) const;
271 /* Checks if the formula contains reference list that can be
272 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
273 reference list is not required to be sorted (i.e. A3;A1;A2 is
274 still recognized as A1:A3), but no overlapping is allowed.
275 If one reference is recognized, the rRange is filled.
276
277 It is similar to HasOneReference(), but more general.
278 */
279 bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
280
281 enum class RelNameRef
282 {
283 NONE,
284 SINGLE,
285 DOUBLE
286 };
287 RelNameRef HasRelNameReference() const;
288
289 bool UpdateReference(
290 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
291
297 bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
298
302 bool UpdateReferenceOnShift(
303 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
304
308 bool UpdateReferenceOnMove(
309 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
310
311 void TransposeReference();
312 void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
313 ScDocument* pUndoDoc );
314
315 void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
316
317 void UpdateInsertTab( const sc::RefUpdateInsertTabContext& rCxt );
318 void UpdateInsertTabAbs(SCTAB nTable);
319 void UpdateDeleteTab( const sc::RefUpdateDeleteTabContext& rCxt );
320 void UpdateMoveTab( const sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo );
321 bool TestTabRefAbs(SCTAB nTable);
322 void UpdateCompile( bool bForceIfNameInUse );
323 void FindRangeNamesInUse(sc::UpdatedRangeNames& rIndexes) const;
324 bool IsSubTotal() const { return bSubTotal;}
325 bool IsChanged() const { return bChanged;}
326 void SetChanged(bool b);
327 bool IsEmpty(); // formula::svEmptyCell result
328 // display as empty string if formula::svEmptyCell result
329 bool IsEmptyDisplayedAsString();
330 bool IsValue(); // also true if formula::svEmptyCell
331 bool IsValueNoError();
332 bool IsValueNoError() const;
333 double GetValue();
335
339 double GetRawValue() const;
340
344 const svl::SharedString & GetRawString() const;
345 const ScMatrix* GetMatrix();
346 bool GetMatrixOrigin( const ScDocument& rDoc, ScAddress& rPos ) const;
347 void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
348 sc::MatrixEdge GetMatrixEdge( const ScDocument& rDoc, ScAddress& rOrgPos ) const;
349 FormulaError GetErrCode(); // interpret first if necessary
350 FormulaError GetRawError() const; // don't interpret, just return code or result error
351 bool GetErrorOrValue( FormulaError& rErr, double& rVal );
352 sc::FormulaResultValue GetResult();
353 sc::FormulaResultValue GetResult() const;
354 ScMatrixMode GetMatrixFlag() const { return cMatrixFlag;}
355 ScTokenArray* GetCode() { return pCode;}
356 const ScTokenArray* GetCode() const { return pCode;}
357
358 void SetCode( std::unique_ptr<ScTokenArray> pNew );
359
360 bool IsRunning() const { return bRunning;}
361 void SetRunning( bool bVal );
362 void CompileDBFormula( sc::CompileFormulaContext& rCxt );
363 void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
364 ScFormulaCell* GetPrevious() const { return pPrevious; }
365 ScFormulaCell* GetNext() const { return pNext; }
366 void SetPrevious( ScFormulaCell* pF );
367 void SetNext( ScFormulaCell* pF );
368 ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
369 ScFormulaCell* GetNextTrack() const { return pNextTrack; }
370 void SetPreviousTrack( ScFormulaCell* pF );
371 void SetNextTrack( ScFormulaCell* pF );
372
373 virtual void Notify( const SfxHint& rHint ) override;
374 virtual void Query( SvtListener::QueryBase& rQuery ) const override;
375
376 void SetCompile( bool bVal );
377 ScDocument& GetDocument() const { return rDocument;}
378 void SetMatColsRows( SCCOL nCols, SCROW nRows );
379 void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
380
381 // cell belongs to ChangeTrack and not to the real document
382 void SetInChangeTrack( bool bVal );
383 bool IsInChangeTrack() const { return bInChangeTrack;}
384
385 // For import filters!
386 void AddRecalcMode( ScRecalcMode );
388 void SetHybridDouble( double n );
393 void SetHybridString( const svl::SharedString& r );
400 void SetHybridEmptyDisplayedAsString();
405 void SetHybridFormula(
406 const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
407
408 OUString GetHybridFormula() const;
409
410 void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL );
411
417 void SetResultDouble( double n );
418
419 void SetResultToken( const formula::FormulaToken* pToken );
420
421 const svl::SharedString & GetResultString() const;
422
423 bool HasHybridStringResult() const;
424
425 /* Sets the shared code array to error state in addition to the cell result */
426 void SetErrCode( FormulaError n );
427
428 /* Sets just the result to error */
429 void SetResultError( FormulaError n );
430
431 bool IsHyperLinkCell() const;
432 std::unique_ptr<EditTextObject> CreateURLObject();
433 void GetURLResult( OUString& rURL, OUString& rCellText );
434
436 bool IsMultilineResult();
437
438 bool NeedsInterpret() const
439 {
440 if (bIsIterCell)
441 // Shortcut to force return of current value and not enter Interpret()
442 // as we're looping over all iteration cells.
443 return false;
444
445 if (!IsDirtyOrInTableOpDirty())
446 return false;
447
448 return rDocument.GetAutoCalc() || (cMatrixFlag != ScMatrixMode::NONE)
449 || (pCode->IsRecalcModeMustAfterImport() && !pCode->IsRecalcModeAlways());
450 }
451
453 {
454 if (NeedsInterpret())
455 {
456 if (bRunning && !rDocument.GetDocOptions().IsIter() && rDocument.IsThreadedGroupCalcInProgress())
457 {
458 // This is actually copied from Interpret()'s if(bRunning)
459 // block that once caught this circular reference but now is
460 // prepended with various threaded group calc things which the
461 // assert() below is supposed to fail on when entering again.
462 // Nevertheless, we need some state here the caller can obtain.
463 aResult.SetResultError( FormulaError::CircularReference );
464 }
465 else
466 {
467 assert(!rDocument.IsThreadedGroupCalcInProgress());
468 Interpret();
469 }
470 }
471 }
472
476 ScFormulaCellGroupRef CreateCellGroup( SCROW nLen, bool bInvariant );
477 const ScFormulaCellGroupRef& GetCellGroup() const { return mxGroup;}
478 void SetCellGroup( const ScFormulaCellGroupRef &xRef );
479
480 CompareState CompareByTokenArray( const ScFormulaCell& rOther ) const;
481
482 bool InterpretFormulaGroup(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
483
484 // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
485 void StartListeningTo( ScDocument& rDoc );
486 void StartListeningTo( sc::StartListeningContext& rCxt );
487 void EndListeningTo(
488 ScDocument& rDoc, ScTokenArray* pArr = nullptr, ScAddress aPos = ScAddress() );
489 void EndListeningTo( sc::EndListeningContext& rCxt );
490
491 bool IsShared() const;
492 bool IsSharedTop() const;
493 SCROW GetSharedTopRow() const;
494 SCROW GetSharedLength() const;
495
496 // An estimate of the number of cells referenced by the formula
497 sal_Int32 GetWeight() const;
498
499 ScTokenArray* GetSharedCode();
500 const ScTokenArray* GetSharedCode() const;
501
502 void SyncSharedCode();
503
504 bool IsPostponedDirty() const { return mbPostponedDirty;}
505
506 void SetIsExtRef() { mbIsExtRef = true; }
507 bool GetSeenInPath() const { return mbSeenInPath; }
508 void SetSeenInPath(bool bSet) { mbSeenInPath = bSet; }
509
510#if DUMP_COLUMN_STORAGE
511 void Dump() const;
512#endif
513};
514
515inline bool ScDocument::IsInFormulaTree( const ScFormulaCell* pCell ) const { return pCell->GetPrevious() || pFormulaTree == pCell; }
516inline bool ScDocument::IsInFormulaTrack( const ScFormulaCell* pCell ) const { return pCell->GetPreviousTrack() || pFormulaTrack == pCell; }
517
518/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
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:44
#define DOUBLE
bool IsIter() const
Definition: docoptio.hxx:59
bool IsInFormulaTree(const ScFormulaCell *pCell) const
bool IsInFormulaTrack(const ScFormulaCell *pCell) const
ScFormulaCell * pFormulaTree
Definition: document.hxx:386
bool IsInInterpreterTableOp() const
Definition: document.hxx:2439
SC_DLLPUBLIC bool GetAutoCalc() const
Definition: document.hxx:1413
bool IsThreadedGroupCalcInProgress() const
Definition: document.hxx:630
SC_DLLPUBLIC const ScDocOptions & GetDocOptions() const
Definition: documen3.cxx:1936
ScFormulaCell * pFormulaTrack
Definition: document.hxx:388
bool NeedsInterpret() const
bool IsInChangeTrack() const
ScTokenArray * pCode
ScMatrixMode GetMatrixFlag() const
ScFormulaCellGroupRef mxGroup
void Dump() const
ScFormulaCell * GetNext() const
bool mbAllowNumberFormatChange
const ScFormulaCellGroupRef & GetCellGroup() const
ScFormulaCell(const ScFormulaCell &)=delete
bool IsSubTotal() const
bool IsPostponedDirty() const
ScDocument & rDocument
ScFormulaResult aResult
bool IsRunning() const
ScMatrixMode cMatrixFlag
void SetSeenInPath(bool bSet)
ScFormulaCell * GetPrevious() const
bool GetSeenInPath() const
void SetFreeFlying(bool b)
SvNumFormatType nFormatType
bool mbNeedsNumberFormat
bool GetDirty() const
bool IsChanged() const
SvNumFormatType GetFormatType() const
bool IsIterCell() const
ScFormulaCell * pNext
bool IsDirtyOrInTableOpDirty() const
bool NeedsNumberFormat() const
ScFormulaCell * GetNextTrack() const
formula::FormulaGrammar::Grammar eTempGrammar
sal_uInt16 nSeenInIteration
bool NeedsListening() const
void MaybeInterpret()
void SetIsExtRef()
ScDocument & GetDocument() const
ScFormulaCell * pNextTrack
ScFormulaCell * pPrevious
ScTokenArray * GetCode()
sal_uInt16 GetSeenInIteration() const
const ScTokenArray * GetCode() const
ScFormulaCell * pPreviousTrack
ScAddress aPos
ScFormulaCell * GetPreviousTrack() const
Store a variable formula cell result, balancing between runtime performance and memory consumption.
void SetResultError(FormulaError nErr)
Set error code, don't touch token or double.
Matrix data type that can store values of mixed types.
Definition: scmatrix.hxx:101
bool IsRecalcModeAlways() const
bool IsRecalcModeMustAfterImport() const
Keep track of all named expressions that have been updated during reference update.
FormulaError
ScMatrixMode
void intrusive_ptr_release(const ScFormulaCellGroup *p)
std::map< AreaListenerKey, sc::FormulaGroupAreaListener > AreaListenersType
Definition: formulacell.hxx:68
void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
ScCloneFlags
Definition: global.hxx:251
@ Default
Default cell clone flags: do not start listening, do not adjust 3D refs to old position,...
void * p
void Notify(ScModelObj &rModelObj, const ScRangeList &rChangeRanges, const OUString &rType=OUString("cell-change"), const css::uno::Sequence< css::beans::PropertyValue > &rProperties=css::uno::Sequence< css::beans::PropertyValue >())
Definition: docsh.hxx:498
OUString GetString(int nId)
NONE
Query
Reference
CAUTION! The following defines must be in the same namespace as the respective type.
Definition: broadcast.cxx:15
MatrixEdge
Definition: types.hxx:65
css::uno::Reference< css::animations::XAnimationNode > Clone(const css::uno::Reference< css::animations::XAnimationNode > &xSourceNode, const SdPage *pSource=nullptr, const SdPage *pTarget=nullptr)
const char GetValue[]
#define SC_DLLPUBLIC
Definition: scdllapi.h:27
AreaListenerKey(const ScRange &rRange, bool bStartFixed, bool bEndFixed)
Definition: formulacell.hxx:62
bool operator<(const AreaListenerKey &r) const
std::optional< ScTokenArray > mpCode
Definition: formulacell.hxx:77
SvNumFormatType mnFormatType
Definition: formulacell.hxx:81
ScFormulaCellGroup(const ScFormulaCellGroup &)=delete
sal_uInt8 meCalcState
Definition: formulacell.hxx:86
const ScFormulaCellGroup & operator=(const ScFormulaCellGroup &)=delete
ScFormulaCell * mpTopCell
Definition: formulacell.hxx:78
AreaListenersType m_AreaListeners
Definition: formulacell.hxx:72
Context for reference update during shifting, moving or copying of cell ranges.
ScRecalcMode
unsigned char sal_uInt8
sal_Int16 SCTAB
Definition: types.hxx:22
::boost::intrusive_ptr< ScFormulaCellGroup > ScFormulaCellGroupRef
Definition: types.hxx:43
::boost::intrusive_ptr< const ScMatrix > ScConstMatrixRef
Definition: types.hxx:26
sal_Int16 SCCOL
Definition: types.hxx:21
sal_Int32 SCROW
Definition: types.hxx:17
SvNumFormatType