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
38namespace sc {
39
40class StartListeningContext;
41class EndListeningContext;
42struct RefUpdateContext;
43struct RefUpdateInsertTabContext;
44struct RefUpdateDeleteTabContext;
45struct RefUpdateMoveTabContext;
46class CompileFormulaContext;
47class FormulaGroupAreaListener;
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, std::unique_ptr<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 bool Interpret(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
265 bool IsIterCell() const { return bIsIterCell; }
266 sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
267
268 bool HasOneReference( ScRange& r ) const;
269 /* Checks if the formula contains reference list that can be
270 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
271 reference list is not required to be sorted (i.e. A3;A1;A2 is
272 still recognized as A1:A3), but no overlapping is allowed.
273 If one reference is recognized, the rRange is filled.
274
275 It is similar to HasOneReference(), but more general.
276 */
277 bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
278
279 enum class RelNameRef
280 {
281 NONE,
282 SINGLE,
283 DOUBLE
284 };
285 RelNameRef HasRelNameReference() const;
286
287 bool UpdateReference(
288 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
289
295 bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
296
300 bool UpdateReferenceOnShift(
301 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
302
306 bool UpdateReferenceOnMove(
307 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
308
309 void TransposeReference();
310 void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
311 ScDocument* pUndoDoc );
312
313 void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
314
315 void UpdateInsertTab( const sc::RefUpdateInsertTabContext& rCxt );
316 void UpdateInsertTabAbs(SCTAB nTable);
317 void UpdateDeleteTab( const sc::RefUpdateDeleteTabContext& rCxt );
318 void UpdateMoveTab( const sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo );
319 bool TestTabRefAbs(SCTAB nTable);
320 void UpdateCompile( bool bForceIfNameInUse );
321 void FindRangeNamesInUse(sc::UpdatedRangeNames& rIndexes) const;
322 bool IsSubTotal() const { return bSubTotal;}
323 bool IsChanged() const { return bChanged;}
324 void SetChanged(bool b);
325 bool IsEmpty(); // formula::svEmptyCell result
326 // display as empty string if formula::svEmptyCell result
327 bool IsEmptyDisplayedAsString();
328 bool IsValue(); // also true if formula::svEmptyCell
329 bool IsValueNoError();
330 bool IsValueNoError() const;
331 double GetValue();
333
337 double GetRawValue() const;
338
342 const svl::SharedString & GetRawString() const;
343 const ScMatrix* GetMatrix();
344 bool GetMatrixOrigin( const ScDocument& rDoc, ScAddress& rPos ) const;
345 void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
346 sc::MatrixEdge GetMatrixEdge( const ScDocument& rDoc, ScAddress& rOrgPos ) const;
347 FormulaError GetErrCode(); // interpret first if necessary
348 FormulaError GetRawError() const; // don't interpret, just return code or result error
349 bool GetErrorOrValue( FormulaError& rErr, double& rVal );
350 sc::FormulaResultValue GetResult();
351 sc::FormulaResultValue GetResult() const;
352 ScMatrixMode GetMatrixFlag() const { return cMatrixFlag;}
353 ScTokenArray* GetCode() { return pCode;}
354 const ScTokenArray* GetCode() const { return pCode;}
355
356 void SetCode( std::unique_ptr<ScTokenArray> pNew );
357
358 bool IsRunning() const { return bRunning;}
359 void SetRunning( bool bVal );
360 void CompileDBFormula( sc::CompileFormulaContext& rCxt );
361 void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
362 ScFormulaCell* GetPrevious() const { return pPrevious; }
363 ScFormulaCell* GetNext() const { return pNext; }
364 void SetPrevious( ScFormulaCell* pF );
365 void SetNext( ScFormulaCell* pF );
366 ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
367 ScFormulaCell* GetNextTrack() const { return pNextTrack; }
368 void SetPreviousTrack( ScFormulaCell* pF );
369 void SetNextTrack( ScFormulaCell* pF );
370
371 virtual void Notify( const SfxHint& rHint ) override;
372 virtual void Query( SvtListener::QueryBase& rQuery ) const override;
373
374 void SetCompile( bool bVal );
375 ScDocument& GetDocument() const { return rDocument;}
376 void SetMatColsRows( SCCOL nCols, SCROW nRows );
377 void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
378
379 // cell belongs to ChangeTrack and not to the real document
380 void SetInChangeTrack( bool bVal );
381 bool IsInChangeTrack() const { return bInChangeTrack;}
382
383 // For import filters!
384 void AddRecalcMode( ScRecalcMode );
386 void SetHybridDouble( double n );
391 void SetHybridString( const svl::SharedString& r );
398 void SetHybridEmptyDisplayedAsString();
403 void SetHybridFormula(
404 const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
405
406 OUString GetHybridFormula() const;
407
408 void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, const formula::FormulaToken* pUL );
409
415 void SetResultDouble( double n );
416
417 void SetResultToken( const formula::FormulaToken* pToken );
418
419 const svl::SharedString & GetResultString() const;
420
421 bool HasHybridStringResult() const;
422
423 /* Sets the shared code array to error state in addition to the cell result */
424 void SetErrCode( FormulaError n );
425
426 /* Sets just the result to error */
427 void SetResultError( FormulaError n );
428
429 bool IsHyperLinkCell() const;
430 std::unique_ptr<EditTextObject> CreateURLObject();
431 void GetURLResult( OUString& rURL, OUString& rCellText );
432
434 bool IsMultilineResult();
435
436 bool NeedsInterpret() const
437 {
438 if (bIsIterCell)
439 // Shortcut to force return of current value and not enter Interpret()
440 // as we're looping over all iteration cells.
441 return false;
442
443 if (!IsDirtyOrInTableOpDirty())
444 return false;
445
446 return (rDocument.GetAutoCalc() || (cMatrixFlag != ScMatrixMode::NONE));
447 }
448
450 {
451 if (NeedsInterpret())
452 {
453 if (bRunning && !rDocument.GetDocOptions().IsIter() && rDocument.IsThreadedGroupCalcInProgress())
454 {
455 // This is actually copied from Interpret()'s if(bRunning)
456 // block that once caught this circular reference but now is
457 // prepended with various threaded group calc things which the
458 // assert() below is supposed to fail on when entering again.
459 // Nevertheless, we need some state here the caller can obtain.
460 aResult.SetResultError( FormulaError::CircularReference );
461 }
462 else
463 {
464 assert(!rDocument.IsThreadedGroupCalcInProgress());
465 Interpret();
466 }
467 }
468 }
469
473 ScFormulaCellGroupRef CreateCellGroup( SCROW nLen, bool bInvariant );
474 const ScFormulaCellGroupRef& GetCellGroup() const { return mxGroup;}
475 void SetCellGroup( const ScFormulaCellGroupRef &xRef );
476
477 CompareState CompareByTokenArray( const ScFormulaCell& rOther ) const;
478
479 bool InterpretFormulaGroup(SCROW nStartOffset = -1, SCROW nEndOffset = -1);
480
481 // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
482 void StartListeningTo( ScDocument& rDoc );
483 void StartListeningTo( sc::StartListeningContext& rCxt );
484 void EndListeningTo(
485 ScDocument& rDoc, ScTokenArray* pArr = nullptr, ScAddress aPos = ScAddress() );
486 void EndListeningTo( sc::EndListeningContext& rCxt );
487
488 bool IsShared() const;
489 bool IsSharedTop() const;
490 SCROW GetSharedTopRow() const;
491 SCROW GetSharedLength() const;
492
493 // An estimate of the number of cells referenced by the formula
494 sal_Int32 GetWeight() const;
495
496 ScTokenArray* GetSharedCode();
497 const ScTokenArray* GetSharedCode() const;
498
499 void SyncSharedCode();
500
501 bool IsPostponedDirty() const { return mbPostponedDirty;}
502
503 void SetIsExtRef() { mbIsExtRef = true; }
504 bool GetSeenInPath() const { return mbSeenInPath; }
505 void SetSeenInPath(bool bSet) { mbSeenInPath = bSet; }
506
507#if DUMP_COLUMN_STORAGE
508 void Dump() const;
509#endif
510};
511
512inline bool ScDocument::IsInFormulaTree( const ScFormulaCell* pCell ) const { return pCell->GetPrevious() || pFormulaTree == pCell; }
513inline bool ScDocument::IsInFormulaTrack( const ScFormulaCell* pCell ) const { return pCell->GetPreviousTrack() || pFormulaTrack == pCell; }
514
515/* 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:385
bool IsInInterpreterTableOp() const
Definition: document.hxx:2430
SC_DLLPUBLIC bool GetAutoCalc() const
Definition: document.hxx:1409
bool IsThreadedGroupCalcInProgress() const
Definition: document.hxx:629
SC_DLLPUBLIC const ScDocOptions & GetDocOptions() const
Definition: documen3.cxx:1946
ScFormulaCell * pFormulaTrack
Definition: document.hxx:387
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
Keep track of all named expressions that have been updated during reference update.
FormulaError
std::map< AreaListenerKey, std::unique_ptr< sc::FormulaGroupAreaListener > > AreaListenersType
Definition: formulacell.hxx:68
ScMatrixMode
void intrusive_ptr_release(const ScFormulaCellGroup *p)
void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
ScCloneFlags
Definition: global.hxx:249
@ 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:483
OUString GetString(int nId)
NONE
Query
Reference
CAUTION! The following defines must be in the same namespace as the respective type.
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)
std::string 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