build fix
[LibreOffice.git] / sc / inc / formulacell.hxx
blobad21cc21d7f4543f424dcc0cc58f7cfad38705ee
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 <set>
24 #include <memory>
26 #include <formula/tokenarray.hxx>
27 #include <osl/conditn.hxx>
28 #include <osl/mutex.hxx>
29 #include <rtl/ref.hxx>
30 #include <svl/listener.hxx>
32 #include "types.hxx"
34 #include "formularesult.hxx"
36 namespace sc {
38 class CompiledFormula;
39 class StartListeningContext;
40 class EndListeningContext;
41 struct RefUpdateContext;
42 struct RefUpdateInsertTabContext;
43 struct RefUpdateDeleteTabContext;
44 struct RefUpdateMoveTabContext;
45 class CompileFormulaContext;
46 class FormulaGroupAreaListener;
47 class UpdatedRangeNames;
51 class ScFormulaCell;
52 class ScProgress;
53 class ScTokenArray;
55 struct SC_DLLPUBLIC ScFormulaCellGroup
57 private:
58 struct Impl;
59 std::unique_ptr<Impl> mpImpl;
61 public:
63 mutable size_t mnRefCount;
65 ScTokenArray* mpCode;
66 ScFormulaCell *mpTopCell;
67 SCROW mnLength; // How many of these do we have ?
68 short mnFormatType;
69 bool mbInvariant:1;
70 bool mbSubTotal:1;
72 sal_uInt8 meCalcState;
74 ScFormulaCellGroup();
75 ScFormulaCellGroup(const ScFormulaCellGroup&) = delete;
76 const ScFormulaCellGroup& operator=(const ScFormulaCellGroup&) = delete;
77 ~ScFormulaCellGroup();
79 void setCode( const ScTokenArray& rCode );
80 void setCode( ScTokenArray* pCode );
81 void compileCode(
82 ScDocument& rDoc, const ScAddress& rPos, formula::FormulaGrammar::Grammar eGram );
84 sc::FormulaGroupAreaListener* getAreaListener(
85 ScFormulaCell** ppTopCell, const ScRange& rRange, bool bStartFixed, bool bEndFixed );
87 void endAllGroupListening( ScDocument& rDoc );
90 inline void intrusive_ptr_add_ref(const ScFormulaCellGroup *p)
92 p->mnRefCount++;
95 inline void intrusive_ptr_release(const ScFormulaCellGroup *p)
97 if( --p->mnRefCount == 0 )
98 delete p;
101 enum ScMatrixMode {
102 MM_NONE = 0, // No matrix formula
103 MM_FORMULA = 1, // Upper left matrix formula cell
104 MM_REFERENCE = 2 // Remaining cells, via ocMatRef reference token
107 class SC_DLLPUBLIC ScFormulaCell : public SvtListener
109 private:
110 ScFormulaCellGroupRef mxGroup; // re-factoring hack - group of formulae we're part of.
111 ScFormulaResult aResult;
112 formula::FormulaGrammar::Grammar eTempGrammar; // used between string (creation) and (re)compilation
113 ScTokenArray* pCode; // The (new) token array
114 ScDocument* pDocument;
115 ScFormulaCell* pPrevious;
116 ScFormulaCell* pNext;
117 ScFormulaCell* pPreviousTrack;
118 ScFormulaCell* pNextTrack;
119 sal_uInt16 nSeenInIteration; // Iteration cycle in which the cell was last encountered
120 short nFormatType;
121 sal_uInt8 cMatrixFlag : 2; // One of ScMatrixMode
122 bool bDirty : 1; // Must be (re)calculated
123 bool bChanged : 1; // Whether something changed regarding display/representation
124 bool bRunning : 1; // Already interpreting right now
125 bool bCompile : 1; // Must be (re)compiled
126 bool bSubTotal : 1; // Cell is part of or contains a SubTotal
127 bool bIsIterCell : 1; // Cell is part of a circular reference
128 bool bInChangeTrack : 1; // Cell is in ChangeTrack
129 bool bTableOpDirty : 1; // Dirty flag for TableOp
130 bool bNeedListening : 1; // Listeners need to be re-established after UpdateReference
131 bool mbNeedsNumberFormat : 1; // set the calculated number format as hard number format
132 bool mbAllowNumberFormatChange : 1; /* allow setting further calculated
133 number formats as hard number format */
134 bool mbPostponedDirty : 1; // if cell needs to be set dirty later
135 bool mbIsExtRef : 1; // has references in ScExternalRefManager; never cleared after set
137 enum ScInterpretTailParameter
139 SCITP_NORMAL,
140 SCITP_FROM_ITERATION,
141 SCITP_CLOSE_ITERATION_CIRCLE
143 void InterpretTail( ScInterpretTailParameter );
146 * Update reference in response to cell copy-n-paste.
148 bool UpdateReferenceOnCopy(
149 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
151 ScFormulaCell( const ScFormulaCell& ) = delete;
152 public:
154 enum CompareState { NotEqual = 0, EqualInvariant, EqualRelativeRef };
156 DECL_FIXEDMEMPOOL_NEWDEL( ScFormulaCell )
158 ScAddress aPos;
160 virtual ~ScFormulaCell() override;
162 ScFormulaCell* Clone() const;
163 ScFormulaCell* Clone( const ScAddress& rPos ) const;
165 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos );
168 * Transfer the ownership of the passed token array instance to the
169 * formula cell being constructed. The caller <i>must not</i> pass a NULL
170 * token array pointer.
172 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, ScTokenArray* pArray,
173 const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
174 sal_uInt8 cMatInd = MM_NONE );
176 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScTokenArray& rArray,
177 const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT,
178 sal_uInt8 cMatInd = MM_NONE );
180 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos, const ScFormulaCellGroupRef& xGroup,
181 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
182 sal_uInt8 = MM_NONE );
184 /** With formula string and grammar to compile with.
185 formula::FormulaGrammar::GRAM_DEFAULT effectively isformula::FormulaGrammar::GRAM_NATIVE_UI that
186 also includes formula::FormulaGrammar::CONV_UNSPECIFIED, therefore uses the address
187 convention associated with rPos::nTab by default. */
188 ScFormulaCell( ScDocument* pDoc, const ScAddress& rPos,
189 const OUString& rFormula,
190 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT,
191 sal_uInt8 cMatInd = MM_NONE );
193 ScFormulaCell(const ScFormulaCell& rCell, ScDocument& rDoc, const ScAddress& rPos, ScCloneFlags nCloneFlags = ScCloneFlags::Default);
195 size_t GetHash() const;
197 ScFormulaVectorState GetVectorState() const;
199 void GetFormula( OUString& rFormula,
200 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
201 void GetFormula( OUStringBuffer& rBuffer,
202 const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const;
204 OUString GetFormula( sc::CompileFormulaContext& rCxt ) const;
206 void SetDirty( bool bDirtyFlag=true );
207 void SetDirtyVar();
208 // If setting entire document dirty after load, no broadcasts but still append to FormulaTree.
209 void SetDirtyAfterLoad();
210 void ResetTableOpDirtyVar();
211 void SetTableOpDirty();
212 bool IsDirtyOrInTableOpDirty() const;
213 bool GetDirty() const { return bDirty; }
214 void ResetDirty();
215 bool NeedsListening() const { return bNeedListening; }
216 void SetNeedsListening( bool bVar );
217 void SetNeedsDirty( bool bVar );
218 void SetNeedNumberFormat( bool bVal );
219 bool NeedsNumberFormat() const { return mbNeedsNumberFormat;}
220 short GetFormatType() const { return nFormatType; }
221 void Compile(const OUString& rFormula,
222 bool bNoListening,
223 const formula::FormulaGrammar::Grammar );
224 void Compile(
225 sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening = false );
227 void CompileTokenArray( bool bNoListening = false );
228 void CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening = false );
229 void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); // compile temporary string tokens
230 void CalcAfterLoad( sc::CompileFormulaContext& rCxt, bool bStartListening );
231 bool MarkUsedExternalReferences();
232 void Interpret();
233 bool IsIterCell() const { return bIsIterCell; }
234 sal_uInt16 GetSeenInIteration() const { return nSeenInIteration; }
236 bool HasOneReference( ScRange& r ) const;
237 /* Checks if the formula contains reference list that can be
238 expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The
239 reference list is not required to be sorted (i.e. A3;A1;A2 is
240 still recognized as A1:A3), but no overlapping is allowed.
241 If one reference is recognized, the rRange is filled.
243 It is similar to HasOneReference(), but more general.
245 bool HasRefListExpressibleAsOneReference(ScRange& rRange) const;
247 enum class RelNameRef
249 NONE, ///< no relative reference from named expression
250 SINGLE, ///< only single cell relative reference
251 DOUBLE ///< at least one range relative reference from named expression
253 RelNameRef HasRelNameReference() const;
255 bool UpdateReference(
256 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = nullptr, const ScAddress* pUndoCellPos = nullptr );
259 * Shift the position of formula cell as part of reference update.
261 * @return true if the position has shifted, false otherwise.
263 bool UpdatePosOnShift( const sc::RefUpdateContext& rCxt );
266 * Update reference in response to cell insertion or deletion.
268 bool UpdateReferenceOnShift(
269 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
272 * Update reference in response to cell move.
274 bool UpdateReferenceOnMove(
275 const sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc, const ScAddress* pUndoCellPos );
277 void TransposeReference();
278 void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest,
279 ScDocument* pUndoDoc );
281 void UpdateGrow( const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY );
283 void UpdateInsertTab( sc::RefUpdateInsertTabContext& rCxt );
284 void UpdateInsertTabAbs(SCTAB nTable);
285 void UpdateDeleteTab( sc::RefUpdateDeleteTabContext& rCxt );
286 void UpdateMoveTab( sc::RefUpdateMoveTabContext& rCxt, SCTAB nTabNo );
287 bool TestTabRefAbs(SCTAB nTable);
288 void UpdateCompile( bool bForceIfNameInUse );
289 void FindRangeNamesInUse(sc::UpdatedRangeNames& rIndexes) const;
290 bool IsSubTotal() const { return bSubTotal;}
291 bool IsChanged() const { return bChanged;}
292 void SetChanged(bool b);
293 bool IsEmpty(); // formula::svEmptyCell result
294 // display as empty string if formula::svEmptyCell result
295 bool IsEmptyDisplayedAsString();
296 bool IsValue(); // also true if formula::svEmptyCell
297 bool IsValueNoError();
298 bool IsValueNoError() const;
299 double GetValue();
300 svl::SharedString GetString();
303 * Get a numeric value without potentially triggering re-calculation.
305 double GetRawValue() const;
308 * Get a string value without potentially triggering re-calculation.
310 svl::SharedString GetRawString() const;
311 const ScMatrix* GetMatrix();
312 bool GetMatrixOrigin( ScAddress& rPos ) const;
313 void GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
314 sc::MatrixEdge GetMatrixEdge( ScAddress& rOrgPos ) const;
315 FormulaError GetErrCode(); // interpret first if necessary
316 FormulaError GetRawError(); // don't interpret, just return code or result error
317 bool GetErrorOrValue( FormulaError& rErr, double& rVal );
318 sc::FormulaResultValue GetResult();
319 sc::FormulaResultValue GetResult() const;
320 sal_uInt8 GetMatrixFlag() const { return cMatrixFlag;}
321 ScTokenArray* GetCode() { return pCode;}
322 const ScTokenArray* GetCode() const { return pCode;}
324 void SetCode( ScTokenArray* pNew );
326 bool IsRunning() const { return bRunning;}
327 void SetRunning( bool bVal );
328 void CompileDBFormula( sc::CompileFormulaContext& rCxt );
329 void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt );
330 ScFormulaCell* GetPrevious() const { return pPrevious; }
331 ScFormulaCell* GetNext() const { return pNext; }
332 void SetPrevious( ScFormulaCell* pF );
333 void SetNext( ScFormulaCell* pF );
334 ScFormulaCell* GetPreviousTrack() const { return pPreviousTrack; }
335 ScFormulaCell* GetNextTrack() const { return pNextTrack; }
336 void SetPreviousTrack( ScFormulaCell* pF );
337 void SetNextTrack( ScFormulaCell* pF );
339 virtual void Notify( const SfxHint& rHint ) override;
340 virtual void Query( SvtListener::QueryBase& rQuery ) const override;
342 void SetCompile( bool bVal );
343 ScDocument* GetDocument() const { return pDocument;}
344 void SetMatColsRows( SCCOL nCols, SCROW nRows );
345 void GetMatColsRows( SCCOL& nCols, SCROW& nRows ) const;
347 // cell belongs to ChangeTrack and not to the real document
348 void SetInChangeTrack( bool bVal );
349 bool IsInChangeTrack() const { return bInChangeTrack;}
351 // For import filters!
352 void AddRecalcMode( ScRecalcMode );
353 /** For import only: set a double result. */
354 void SetHybridDouble( double n );
355 /** For import only: set a string result.
356 If for whatever reason you have to use both, SetHybridDouble() and
357 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
358 for performance reasons.*/
359 void SetHybridString( const svl::SharedString& r );
360 /** For import only: set an empty cell result to be displayed as empty string.
361 If for whatever reason you have to use both, SetHybridDouble() and
362 SetHybridEmptyDisplayedAsString() or SetHybridFormula(), use
363 SetHybridDouble() first for performance reasons and use
364 SetHybridEmptyDisplayedAsString() last because SetHybridDouble() and
365 SetHybridString() will override it.*/
366 void SetHybridEmptyDisplayedAsString();
367 /** For import only: set a temporary formula string to be compiled later.
368 If for whatever reason you have to use both, SetHybridDouble() and
369 SetHybridString() or SetHybridFormula(), use SetHybridDouble() first
370 for performance reasons.*/
371 void SetHybridFormula(
372 const OUString& r, const formula::FormulaGrammar::Grammar eGrammar );
374 OUString GetHybridFormula() const;
376 void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL );
378 /** For import only: set a double result.
379 Use this instead of SetHybridDouble() if there is no (temporary)
380 formula string because the formula is present as a token array, as it
381 is the case for binary Excel import.
383 void SetResultDouble( double n );
385 void SetResultToken( const formula::FormulaToken* pToken );
387 svl::SharedString GetResultString() const;
389 /* Sets the shared code array to error state in addition to the cell result */
390 void SetErrCode( FormulaError n );
392 /* Sets just the result to error */
393 void SetResultError( FormulaError n );
395 bool IsHyperLinkCell() const;
396 EditTextObject* CreateURLObject();
397 void GetURLResult( OUString& rURL, OUString& rCellText );
399 /** Determines whether or not the result string contains more than one paragraph */
400 bool IsMultilineResult();
402 bool NeedsInterpret() const;
404 void MaybeInterpret();
407 * Turn a non-grouped cell into the top of a grouped cell.
409 ScFormulaCellGroupRef CreateCellGroup( SCROW nLen, bool bInvariant );
410 const ScFormulaCellGroupRef& GetCellGroup() const { return mxGroup;}
411 void SetCellGroup( const ScFormulaCellGroupRef &xRef );
413 CompareState CompareByTokenArray( ScFormulaCell& rOther ) const;
415 bool InterpretFormulaGroup();
416 bool InterpretInvariantFormulaGroup();
418 // nOnlyNames may be one or more of SC_LISTENING_NAMES_*
419 void StartListeningTo( ScDocument* pDoc );
420 void StartListeningTo( sc::StartListeningContext& rCxt );
421 void EndListeningTo(
422 ScDocument* pDoc, ScTokenArray* pArr = nullptr, ScAddress aPos = ScAddress() );
423 void EndListeningTo( sc::EndListeningContext& rCxt );
425 bool IsShared() const;
426 bool IsSharedTop() const;
427 SCROW GetSharedTopRow() const;
428 SCROW GetSharedLength() const;
430 // An estimate of the number of cells referenced by the formula
431 sal_Int32 GetWeight() const;
433 ScTokenArray* GetSharedCode();
434 const ScTokenArray* GetSharedCode() const;
436 void SyncSharedCode();
438 bool IsPostponedDirty() const { return mbPostponedDirty;}
440 void SetIsExtRef() { mbIsExtRef = true; }
443 #endif
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */