From 99a835ca644d69241cba9d7e4c4a315a4a3ea652 Mon Sep 17 00:00:00 2001 From: Kohei Yoshida Date: Tue, 4 Feb 2014 10:19:47 -0500 Subject: fdo#74516: Avoid excessive building of escaped sheet names. The old code would build an array of escaped sheet names for all sheets on evevery invokation of ScCompiler, which unfortunately slowed down these "compile all formula cells" type methods, such as CompileAll(), CompileXML() etc. Let's avoid that and build or re-build the list only when necessary. Conflicts: sc/inc/column.hxx sc/inc/table.hxx sc/source/core/data/document.cxx sc/source/core/tool/compiler.cxx Change-Id: Iabf7c2374b728b6701da3aae7835cca2157f6c96 Reviewed-on: https://gerrit.libreoffice.org/7861 Reviewed-by: Fridrich Strba Tested-by: Fridrich Strba --- sc/inc/column.hxx | 17 +-- sc/inc/compiler.hxx | 10 ++ sc/inc/formulacell.hxx | 21 ++-- sc/inc/rangenam.hxx | 15 ++- sc/inc/table.hxx | 17 +-- sc/inc/tokenstringcontext.hxx | 19 ++++ sc/source/core/data/column.cxx | 48 ++++---- sc/source/core/data/column2.cxx | 46 +++++--- sc/source/core/data/documen2.cxx | 4 +- sc/source/core/data/documen4.cxx | 13 ++- sc/source/core/data/document.cxx | 16 ++- sc/source/core/data/formulacell.cxx | 172 +++++++++++++++++++++++++---- sc/source/core/data/table2.cxx | 20 ++-- sc/source/core/data/table4.cxx | 20 ++-- sc/source/core/tool/compiler.cxx | 36 ++++++ sc/source/core/tool/rangenam.cxx | 11 +- sc/source/core/tool/tokenstringcontext.cxx | 43 ++++++++ 17 files changed, 410 insertions(+), 118 deletions(-) (limited to 'sc') diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 414f40d90e5c..9eef0853c05e 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -56,6 +56,7 @@ struct RefUpdateMoveTabContext; class EditTextIterator; struct NoteEntry; class DocumentStreamAccess; +class CompileFormulaContext; } @@ -321,11 +322,11 @@ public: void SetDirtyAfterLoad(); void SetTableOpDirty( const ScRange& ); void CalcAll(); - void CalcAfterLoad(); - void CompileAll(); - void CompileXML( ScProgress& rProgress ); + void CalcAfterLoad( sc::CompileFormulaContext& rCxt ); + void CompileAll( sc::CompileFormulaContext& rCxt ); + void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); - bool CompileErrorCells(sal_uInt16 nErrCode); + bool CompileErrorCells( sc::CompileFormulaContext& rCxt, sal_uInt16 nErrCode ); void ResetChanged( SCROW nStartRow, SCROW nEndRow ); @@ -449,10 +450,10 @@ public: void SetDirtyIfPostponed(); void BroadcastRecalcOnRefMove(); - void CompileDBFormula(); - void CompileDBFormula( bool bCreateFormulaString ); - void CompileNameFormula( bool bCreateFormulaString ); - void CompileColRowNameFormula(); + void CompileDBFormula( sc::CompileFormulaContext& rCxt ); + void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ); + void CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ); + void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt ); sal_Int32 GetMaxStringLen( SCROW nRowStart, SCROW nRowEnd, rtl_TextEncoding eCharSet ) const; xub_StrLen GetMaxNumberStringLen( sal_uInt16& nPrecision, diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index a8757e7f8cda..78f896e4badb 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -78,6 +78,12 @@ class ScRangeData; class ScExternalRefManager; class ScTokenArray; +namespace sc { + +class CompileFormulaContext; + +} + // constants and data types internal to compiler /* @@ -362,8 +368,12 @@ private: static void InitCharClassEnglish(); public: + ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos ); + ScCompiler( ScDocument* pDocument, const ScAddress&); + ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, ScTokenArray& rArr ); + ScCompiler( ScDocument* pDocument, const ScAddress&,ScTokenArray& rArr); virtual ~ScCompiler(); diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 68c620cd67c8..e901c6e2b10e 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -44,6 +44,7 @@ struct RefUpdateContext; struct RefUpdateInsertTabContext; struct RefUpdateDeleteTabContext; struct RefUpdateMoveTabContext; +class CompileFormulaContext; } @@ -205,6 +206,8 @@ public: void GetFormula( OUStringBuffer& rBuffer, const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ) const; + OUString GetFormula( sc::CompileFormulaContext& rCxt ) const; + void SetDirty( bool bDirtyFlag=true ); void SetDirtyVar(); // If setting entire document dirty after load, no broadcasts but still append to FormulaTree. @@ -221,9 +224,13 @@ public: void Compile(const OUString& rFormula, bool bNoListening = false, const formula::FormulaGrammar::Grammar = formula::FormulaGrammar::GRAM_DEFAULT ); - void CompileTokenArray( bool bNoListening = false ); - void CompileXML( ScProgress& rProgress ); // compile temporary string tokens - void CalcAfterLoad(); + void Compile( + sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening = false ); + + void CompileTokenArray( bool bNoListening = false ); + void CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening = false ); + void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); // compile temporary string tokens + void CalcAfterLoad( sc::CompileFormulaContext& rCxt ); bool MarkUsedExternalReferences(); void Interpret(); bool IsIterCell() const; @@ -285,10 +292,10 @@ public: bool IsRunning() const; void SetRunning( bool bVal ); - void CompileDBFormula(); - void CompileDBFormula( bool bCreateFormulaString ); - void CompileNameFormula( bool bCreateFormulaString ); - void CompileColRowNameFormula(); + void CompileDBFormula( sc::CompileFormulaContext& rCxt ); + void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ); + void CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ); + void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt ); ScFormulaCell* GetPrevious() const; ScFormulaCell* GetNext() const; void SetPrevious( ScFormulaCell* pF ); diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index 6113709b118b..5d4aebea1b4f 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -35,10 +35,13 @@ class ScDocument; class ScTokenArray; namespace sc { - struct RefUpdateContext; - struct RefUpdateInsertTabContext; - struct RefUpdateDeleteTabContext; - struct RefUpdateMoveTabContext; + +struct RefUpdateContext; +struct RefUpdateInsertTabContext; +struct RefUpdateDeleteTabContext; +struct RefUpdateMoveTabContext; +class CompileFormulaContext; + } typedef sal_uInt16 RangeType; @@ -151,7 +154,7 @@ public: SCROW GetMaxRow() const; SCCOL GetMaxCol() const; - void CompileUnresolvedXML(); + void CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ); #if DEBUG_FORMULA_COMPILER void Dump() const; @@ -201,7 +204,7 @@ public: /** Compile those names that couldn't be resolved during loading and inserting because they may have referred a name that was inserted later. */ - void CompileUnresolvedXML(); + void CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ); SC_DLLPUBLIC const_iterator begin() const; SC_DLLPUBLIC const_iterator end() const; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index f067658e1b0a..3049698492c9 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -68,6 +68,7 @@ struct RefUpdateDeleteTabContext; struct RefUpdateMoveTabContext; struct NoteEntry; class DocumentStreamAccess; +class CompileFormulaContext; } @@ -509,11 +510,11 @@ public: void SetDirtyVar(); void SetTableOpDirty( const ScRange& ); void CalcAll(); - void CalcAfterLoad(); - void CompileAll(); - void CompileXML( ScProgress& rProgress ); + void CalcAfterLoad( sc::CompileFormulaContext& rCxt ); + void CompileAll( sc::CompileFormulaContext& rCxt ); + void CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ); - bool CompileErrorCells(sal_uInt16 nErrCode); + bool CompileErrorCells( sc::CompileFormulaContext& rCxt, sal_uInt16 nErrCode ); void UpdateReference( sc::RefUpdateContext& rCxt, ScDocument* pUndoDoc = NULL, @@ -986,10 +987,10 @@ private: const ScMarkData& rMark) const; bool GetNextMarkedCell( SCCOL& rCol, SCROW& rRow, const ScMarkData& rMark ) const; bool TestTabRefAbs(SCTAB nTable) const; - void CompileDBFormula(); - void CompileDBFormula( bool bCreateFormulaString ); - void CompileNameFormula( bool bCreateFormulaString ); - void CompileColRowNameFormula(); + void CompileDBFormula( sc::CompileFormulaContext& rCxt ); + void CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ); + void CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ); + void CompileColRowNameFormula( sc::CompileFormulaContext& rCxt ); void RebuildFormulaGroups(); void StartListening( const ScAddress& rAddress, SvtListener* pListener ); diff --git a/sc/inc/tokenstringcontext.hxx b/sc/inc/tokenstringcontext.hxx index 85b61f77b13d..3740f60146bf 100644 --- a/sc/inc/tokenstringcontext.hxx +++ b/sc/inc/tokenstringcontext.hxx @@ -46,6 +46,25 @@ struct SC_DLLPUBLIC TokenStringContext TokenStringContext( const ScDocument* pDoc, formula::FormulaGrammar::Grammar eGram ); }; +class CompileFormulaContext +{ + ScDocument* mpDoc; + formula::FormulaGrammar::Grammar meGram; + std::vector maTabNames; + + void updateTabNames(); + +public: + CompileFormulaContext( ScDocument* pDoc ); + + formula::FormulaGrammar::Grammar getGrammar() const; + void setGrammar( formula::FormulaGrammar::Grammar eGram ); + + const std::vector& getTabNames() const; + + ScDocument* getDoc(); +}; + } #endif diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 7771f0e065f8..0b1032873786 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -2836,24 +2836,30 @@ struct CalcAllHandler } }; -struct CompileAllHandler +class CompileAllHandler { + sc::CompileFormulaContext& mrCxt; +public: + CompileAllHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {} + void operator() (size_t /*nRow*/, ScFormulaCell* pCell) { // for unconditional compilation // bCompile=true and pCode->nError=0 pCell->GetCode()->SetCodeError(0); pCell->SetCompile(true); - pCell->CompileTokenArray(); + pCell->CompileTokenArray(mrCxt); } }; class CompileXMLHandler { + sc::CompileFormulaContext& mrCxt; ScProgress& mrProgress; const ScColumn& mrCol; public: - CompileXMLHandler(ScProgress& rProgress, const ScColumn& rCol) : + CompileXMLHandler( sc::CompileFormulaContext& rCxt, ScProgress& rProgress, const ScColumn& rCol) : + mrCxt(rCxt), mrProgress(rProgress), mrCol(rCol) {} @@ -2865,23 +2871,24 @@ public: else pCell->SetDirtyVar(); - pCell->CompileXML(mrProgress); + pCell->CompileXML(mrCxt, mrProgress); } }; class CompileErrorCellsHandler { + sc::CompileFormulaContext& mrCxt; ScColumn& mrColumn; sc::CellStoreType::iterator miPos; sal_uInt16 mnErrCode; FormulaGrammar::Grammar meGram; bool mbCompiled; public: - CompileErrorCellsHandler(ScColumn& rColumn, sal_uInt16 nErrCode, FormulaGrammar::Grammar eGram) : + CompileErrorCellsHandler( sc::CompileFormulaContext& rCxt, ScColumn& rColumn, sal_uInt16 nErrCode ) : + mrCxt(rCxt), mrColumn(rColumn), miPos(mrColumn.GetCellStore().begin()), mnErrCode(nErrCode), - meGram(eGram), mbCompiled(false) { } @@ -2901,9 +2908,8 @@ public: miPos = aPos.first; sc::SharedFormulaUtil::unshareFormulaCell(aPos, *pCell); pCell->GetCode()->SetCodeError(0); - OUStringBuffer aBuf; - pCell->GetFormula(aBuf, meGram); - pCell->Compile(aBuf.makeStringAndClear(), false, meGram); + OUString aFormula = pCell->GetFormula(mrCxt); + pCell->Compile(mrCxt, aFormula, false); mrColumn.JoinNewFormulaCell(aPos, *pCell); mbCompiled = true; @@ -2912,11 +2918,15 @@ public: bool isCompiled() const { return mbCompiled; } }; -struct CalcAfterLoadHandler +class CalcAfterLoadHandler { + sc::CompileFormulaContext& mrCxt; +public: + CalcAfterLoadHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {} + void operator() (size_t /*nRow*/, ScFormulaCell* pCell) { - pCell->CalcAfterLoad(); + pCell->CalcAfterLoad(mrCxt); } }; @@ -3165,29 +3175,29 @@ void ScColumn::CalcAll() sc::ProcessFormula(maCells, aFunc); } -void ScColumn::CompileAll() +void ScColumn::CompileAll( sc::CompileFormulaContext& rCxt ) { - CompileAllHandler aFunc; + CompileAllHandler aFunc(rCxt); sc::ProcessFormula(maCells, aFunc); } -void ScColumn::CompileXML( ScProgress& rProgress ) +void ScColumn::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ) { - CompileXMLHandler aFunc(rProgress, *this); + CompileXMLHandler aFunc(rCxt, rProgress, *this); sc::ProcessFormula(maCells, aFunc); RegroupFormulaCells(); } -bool ScColumn::CompileErrorCells(sal_uInt16 nErrCode) +bool ScColumn::CompileErrorCells( sc::CompileFormulaContext& rCxt, sal_uInt16 nErrCode ) { - CompileErrorCellsHandler aHdl(*this, nErrCode, pDocument->GetGrammar()); + CompileErrorCellsHandler aHdl(rCxt, *this, nErrCode); sc::ProcessFormula(maCells, aHdl); return aHdl.isCompiled(); } -void ScColumn::CalcAfterLoad() +void ScColumn::CalcAfterLoad( sc::CompileFormulaContext& rCxt ) { - CalcAfterLoadHandler aFunc; + CalcAfterLoadHandler aFunc(rCxt); sc::ProcessFormula(maCells, aFunc); } diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index 6aef111d9b6a..04f127fba81e 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -3181,75 +3181,87 @@ void ScColumn::EndListening( sc::EndListeningContext& rCxt, SCROW nRow, SvtListe namespace { -struct CompileDBFormulaHandler +class CompileDBFormulaHandler { + sc::CompileFormulaContext& mrCxt; + +public: + CompileDBFormulaHandler( sc::CompileFormulaContext& rCxt ) : + mrCxt(rCxt) {} + void operator() (size_t, ScFormulaCell* p) { - p->CompileDBFormula(); + p->CompileDBFormula(mrCxt); } }; class CompileDBFormula2Handler { + sc::CompileFormulaContext& mrCxt; bool mbCreateFormulaString; public: - CompileDBFormula2Handler(bool bCreateFormulaString) : - mbCreateFormulaString(bCreateFormulaString) {} + CompileDBFormula2Handler( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) : + mrCxt(rCxt), mbCreateFormulaString(bCreateFormulaString) {} void operator() (size_t, ScFormulaCell* p) { - p->CompileDBFormula(mbCreateFormulaString); + p->CompileDBFormula(mrCxt, mbCreateFormulaString); } }; class CompileNameFormulaHandler { + sc::CompileFormulaContext& mrCxt; bool mbCreateFormulaString; public: - CompileNameFormulaHandler(bool bCreateFormulaString) : - mbCreateFormulaString(bCreateFormulaString) {} + CompileNameFormulaHandler( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString) : + mrCxt(rCxt), mbCreateFormulaString(bCreateFormulaString) {} void operator() (size_t, ScFormulaCell* p) { - p->CompileNameFormula(mbCreateFormulaString); + p->CompileNameFormula(mrCxt, mbCreateFormulaString); } }; struct CompileColRowNameFormulaHandler { + sc::CompileFormulaContext& mrCxt; +public: + CompileColRowNameFormulaHandler( sc::CompileFormulaContext& rCxt ) : mrCxt(rCxt) {} + void operator() (size_t, ScFormulaCell* p) { - p->CompileColRowNameFormula(); + p->CompileColRowNameFormula(mrCxt); } }; } -void ScColumn::CompileDBFormula() +void ScColumn::CompileDBFormula( sc::CompileFormulaContext& rCxt ) { - CompileDBFormulaHandler aFunc; + CompileDBFormulaHandler aFunc(rCxt); sc::ProcessFormula(maCells, aFunc); RegroupFormulaCells(); } -void ScColumn::CompileDBFormula( bool bCreateFormulaString ) +void ScColumn::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) { - CompileDBFormula2Handler aFunc(bCreateFormulaString); + CompileDBFormula2Handler aFunc(rCxt, bCreateFormulaString); sc::ProcessFormula(maCells, aFunc); RegroupFormulaCells(); } -void ScColumn::CompileNameFormula( bool bCreateFormulaString ) +void ScColumn::CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) { - CompileNameFormulaHandler aFunc(bCreateFormulaString); + CompileNameFormulaHandler aFunc(rCxt, bCreateFormulaString); sc::ProcessFormula(maCells, aFunc); } -void ScColumn::CompileColRowNameFormula() +void ScColumn::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt ) { - CompileColRowNameFormulaHandler aFunc; + CompileColRowNameFormulaHandler aFunc(rCxt); sc::ProcessFormula(maCells, aFunc); RegroupFormulaCells(); } diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index ae9cbd9dbcc6..d027bb49f9d2 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -93,6 +93,7 @@ #include "scopetools.hxx" #include "formulagroup.hxx" #include "documentlinkmgr.hxx" +#include using namespace com::sun::star; @@ -1018,7 +1019,8 @@ sal_uLong ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos, // Readjust self-contained absolute references to this sheet maTabs[nDestPos]->TestTabRefAbs(nSrcPos); - maTabs[nDestPos]->CompileAll(); + sc::CompileFormulaContext aFormulaCxt(this); + maTabs[nDestPos]->CompileAll(aFormulaCxt); } SetNoListening( false ); diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index ed496961c38b..fb4538581c73 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -44,6 +44,7 @@ #include "formulacell.hxx" #include "tokenarray.hxx" #include "scmatrix.hxx" +#include using namespace formula; @@ -538,41 +539,45 @@ bool ScDocument::ReplaceStyle(const SvxSearchItem& rSearchItem, void ScDocument::CompileDBFormula() { + sc::CompileFormulaContext aCxt(this); TableContainer::iterator it = maTabs.begin(); for (;it != maTabs.end(); ++it) { if (*it) - (*it)->CompileDBFormula(); + (*it)->CompileDBFormula(aCxt); } } void ScDocument::CompileDBFormula( bool bCreateFormulaString ) { + sc::CompileFormulaContext aCxt(this); TableContainer::iterator it = maTabs.begin(); for (;it != maTabs.end(); ++it) { if (*it) - (*it)->CompileDBFormula( bCreateFormulaString ); + (*it)->CompileDBFormula(aCxt, bCreateFormulaString); } } void ScDocument::CompileNameFormula( bool bCreateFormulaString ) { + sc::CompileFormulaContext aCxt(this); TableContainer::iterator it = maTabs.begin(); for (;it != maTabs.end(); ++it) { if (*it) - (*it)->CompileNameFormula( bCreateFormulaString ); + (*it)->CompileNameFormula(aCxt, bCreateFormulaString); } } void ScDocument::CompileColRowNameFormula() { + sc::CompileFormulaContext aCxt(this); TableContainer::iterator it = maTabs.begin(); for (;it != maTabs.end(); ++it) { if (*it) - (*it)->CompileColRowNameFormula(); + (*it)->CompileColRowNameFormula(aCxt); } } diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index 6bbe8358b4bc..99192e485181 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -95,6 +95,7 @@ #include "scopetools.hxx" #include "refupdatecontext.hxx" #include "formulagroup.hxx" +#include #include "formula/vectortoken.hxx" @@ -3644,10 +3645,11 @@ void ScDocument::CalcAll() void ScDocument::CompileAll() { + sc::CompileFormulaContext aCxt(this); TableContainer::iterator it = maTabs.begin(); for (; it != maTabs.end(); ++it) if (*it) - (*it)->CompileAll(); + (*it)->CompileAll(aCxt); SetDirty(); } @@ -3659,17 +3661,19 @@ void ScDocument::CompileXML() ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString( STR_PROGRESS_CALCULATING ), GetXMLImportedFormulaCount() ); + sc::CompileFormulaContext aCxt(this); + // set AutoNameCache to speed up automatic name lookup OSL_ENSURE( !pAutoNameCache, "AutoNameCache already set" ); pAutoNameCache = new ScAutoNameCache( this ); if (pRangeName) - pRangeName->CompileUnresolvedXML(); + pRangeName->CompileUnresolvedXML(aCxt); TableContainer::iterator it = maTabs.begin(); for (; it != maTabs.end(); ++it) if (*it) - (*it)->CompileXML( aProgress ); + (*it)->CompileXML(aCxt, aProgress); DELETEZ( pAutoNameCache ); // valid only during CompileXML, where cell contents don't change @@ -3682,6 +3686,7 @@ void ScDocument::CompileXML() bool ScDocument::CompileErrorCells(sal_uInt16 nErrCode) { bool bCompiled = false; + sc::CompileFormulaContext aCxt(this); TableContainer::iterator it = maTabs.begin(), itEnd = maTabs.end(); for (; it != itEnd; ++it) { @@ -3689,7 +3694,7 @@ bool ScDocument::CompileErrorCells(sal_uInt16 nErrCode) if (!pTab) continue; - if (pTab->CompileErrorCells(nErrCode)) + if (pTab->CompileErrorCells(aCxt, nErrCode)) bCompiled = true; } @@ -3702,11 +3707,12 @@ void ScDocument::CalcAfterLoad() return; // dann wird erst beim Einfuegen in das richtige Doc berechnet bCalcingAfterLoad = true; + sc::CompileFormulaContext aCxt(this); { TableContainer::iterator it = maTabs.begin(); for (; it != maTabs.end(); ++it) if (*it) - (*it)->CalcAfterLoad(); + (*it)->CalcAfterLoad(aCxt); for (it = maTabs.begin(); it != maTabs.end(); ++it) if (*it) (*it)->SetDirtyAfterLoad(); diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index cad21446ad05..7d1dff1d58ec 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -50,6 +50,7 @@ #include "types.hxx" #include "scopetools.hxx" #include "refupdatecontext.hxx" +#include #include @@ -882,6 +883,62 @@ void ScFormulaCell::GetFormula( OUString& rFormula, const FormulaGrammar::Gramma rFormula = rBuffer.makeStringAndClear(); } +OUString ScFormulaCell::GetFormula( sc::CompileFormulaContext& rCxt ) const +{ + OUStringBuffer aBuf; + if (pCode->GetCodeError() && !pCode->GetLen()) + { + aBuf = OUStringBuffer( ScGlobal::GetErrorString( pCode->GetCodeError())); + return aBuf.makeStringAndClear(); + } + else if( cMatrixFlag == MM_REFERENCE ) + { + // Reference to another cell that contains a matrix formula. + pCode->Reset(); + ScToken* p = static_cast(pCode->GetNextReferenceRPN()); + if( p ) + { + /* FIXME: original GetFormula() code obtained + * pCell only if (!this->IsInChangeTrack()), + * GetEnglishFormula() omitted that test. + * Can we live without in all cases? */ + ScFormulaCell* pCell = NULL; + ScSingleRefData& rRef = p->GetSingleRef(); + ScAddress aAbs = rRef.toAbs(aPos); + if (ValidAddress(aAbs)) + pCell = pDocument->GetFormulaCell(aAbs); + + if (pCell) + { + return pCell->GetFormula(rCxt); + } + else + { + ScCompiler aComp(rCxt, aPos, *pCode); + aComp.CreateStringFromTokenArray(aBuf); + } + } + else + { + OSL_FAIL("ScFormulaCell::GetFormula: not a matrix"); + } + } + else + { + ScCompiler aComp(rCxt, aPos, *pCode); + aComp.CreateStringFromTokenArray(aBuf); + } + + aBuf.insert( 0, '='); + if( cMatrixFlag ) + { + aBuf.insert( 0, '{'); + aBuf.append( '}'); + } + + return aBuf.makeStringAndClear(); +} + void ScFormulaCell::GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows ) { MaybeInterpret(); @@ -940,6 +997,40 @@ void ScFormulaCell::Compile( const OUString& rFormula, bool bNoListening, pDocument->PutInFormulaTree( this ); } +void ScFormulaCell::Compile( + sc::CompileFormulaContext& rCxt, const OUString& rFormula, bool bNoListening ) +{ + if ( pDocument->IsClipOrUndo() ) + return; + bool bWasInFormulaTree = pDocument->IsInFormulaTree( this ); + if ( bWasInFormulaTree ) + pDocument->RemoveFromFormulaTree( this ); + // pCode may not deleted for queries, but must be empty + if ( pCode ) + pCode->Clear(); + ScTokenArray* pCodeOld = pCode; + ScCompiler aComp(rCxt, aPos); + pCode = aComp.CompileString( rFormula ); + if ( pCodeOld ) + delete pCodeOld; + if( !pCode->GetCodeError() ) + { + if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() && rFormula == aResult.GetHybridFormula() ) + { // not recursive CompileTokenArray/Compile/CompileTokenArray + if ( rFormula[0] == '=' ) + pCode->AddBad( rFormula.copy(1) ); + else + pCode->AddBad( rFormula ); + } + bCompile = true; + CompileTokenArray(rCxt, bNoListening); + } + else + bChanged = true; + + if ( bWasInFormulaTree ) + pDocument->PutInFormulaTree( this ); +} void ScFormulaCell::CompileTokenArray( bool bNoListening ) { @@ -981,8 +1072,47 @@ void ScFormulaCell::CompileTokenArray( bool bNoListening ) } } +void ScFormulaCell::CompileTokenArray( sc::CompileFormulaContext& rCxt, bool bNoListening ) +{ + // Not already compiled? + if( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) + { + rCxt.setGrammar(eTempGrammar); + Compile(rCxt, aResult.GetHybridFormula(), bNoListening); + } + else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetCodeError() ) + { + // RPN length may get changed + bool bWasInFormulaTree = pDocument->IsInFormulaTree( this ); + if ( bWasInFormulaTree ) + pDocument->RemoveFromFormulaTree( this ); + + // Loading from within filter? No listening yet! + if( pDocument->IsInsertingFromOtherDoc() ) + bNoListening = true; -void ScFormulaCell::CompileXML( ScProgress& rProgress ) + if( !bNoListening && pCode->GetCodeLen() ) + EndListeningTo( pDocument ); + ScCompiler aComp(rCxt, aPos, *pCode); + bSubTotal = aComp.CompileTokenArray(); + if( !pCode->GetCodeError() ) + { + nFormatType = aComp.GetNumFormatType(); + bChanged = true; + aResult.SetToken( NULL); + bCompile = false; + if ( !bNoListening ) + StartListeningTo( pDocument ); + } + if ( bWasInFormulaTree ) + pDocument->PutInFormulaTree( this ); + + if (bSubTotal) + pDocument->AddSubTotalCell(this); + } +} + +void ScFormulaCell::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ) { if ( cMatrixFlag == MM_REFERENCE ) { // is already token code via ScDocFunc::EnterMatrix, ScDocument::InsertMatrixFormula @@ -996,8 +1126,8 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress ) bool bWasInFormulaTree = pDocument->IsInFormulaTree( this); if (bWasInFormulaTree) pDocument->RemoveFromFormulaTree( this); - ScCompiler aComp( pDocument, aPos, *pCode); - aComp.SetGrammar(eTempGrammar); + rCxt.setGrammar(eTempGrammar); + ScCompiler aComp(rCxt, aPos, *pCode); OUString aFormula, aFormulaNmsp; aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp ); pDocument->DecXMLImportedFormulaCount( aFormula.getLength() ); @@ -1051,13 +1181,14 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress ) } -void ScFormulaCell::CalcAfterLoad() +void ScFormulaCell::CalcAfterLoad( sc::CompileFormulaContext& rCxt ) { bool bNewCompiled = false; // If a Calc 1.0-doc is read, we have a result, but no token array if( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { - Compile( aResult.GetHybridFormula(), true, eTempGrammar); + rCxt.setGrammar(eTempGrammar); + Compile(rCxt, aResult.GetHybridFormula(), true); aResult.SetToken( NULL); bDirty = true; bNewCompiled = true; @@ -1065,8 +1196,7 @@ void ScFormulaCell::CalcAfterLoad() // The RPN array is not created when a Calc 3.0-Doc has been read as the Range Names exist until now. if( pCode->GetLen() && !pCode->GetCodeLen() && !pCode->GetCodeError() ) { - ScCompiler aComp(pDocument, aPos, *pCode); - aComp.SetGrammar(pDocument->GetGrammar()); + ScCompiler aComp(rCxt, aPos, *pCode); bSubTotal = aComp.CompileTokenArray(); nFormatType = aComp.GetNumFormatType(); bDirty = true; @@ -3213,7 +3343,7 @@ void ScFormulaCell::SetRunning( bool bVal ) bRunning = bVal; } -void ScFormulaCell::CompileDBFormula() +void ScFormulaCell::CompileDBFormula( sc::CompileFormulaContext& rCxt ) { for( FormulaToken* p = pCode->First(); p; p = pCode->Next() ) { @@ -3221,14 +3351,14 @@ void ScFormulaCell::CompileDBFormula() || (p->GetOpCode() == ocName && p->GetIndex() >= SC_START_INDEX_DB_COLL) ) { bCompile = true; - CompileTokenArray(); + CompileTokenArray(rCxt); SetDirty(); break; } } } -void ScFormulaCell::CompileDBFormula( bool bCreateFormulaString ) +void ScFormulaCell::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) { // Two phases must be called after each other // 1. Formula String with old generated names @@ -3256,8 +3386,7 @@ void ScFormulaCell::CompileDBFormula( bool bCreateFormulaString ) } if ( bRecompile ) { - OUString aFormula; - GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE); + OUString aFormula = GetFormula(rCxt); if ( GetMatrixFlag() != MM_NONE && !aFormula.isEmpty() ) { if ( aFormula[ aFormula.getLength()-1 ] == '}' ) @@ -3268,18 +3397,19 @@ void ScFormulaCell::CompileDBFormula( bool bCreateFormulaString ) EndListeningTo( pDocument ); pDocument->RemoveFromFormulaTree( this ); pCode->Clear(); - SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE); + SetHybridFormula(aFormula, rCxt.getGrammar()); } } else if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { - Compile( aResult.GetHybridFormula(), false, eTempGrammar ); + rCxt.setGrammar(eTempGrammar); + Compile(rCxt, aResult.GetHybridFormula(), false); aResult.SetToken( NULL); SetDirty(); } } -void ScFormulaCell::CompileNameFormula( bool bCreateFormulaString ) +void ScFormulaCell::CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) { // Two phases must be called after each other // 1. Formula String with old generated names @@ -3303,8 +3433,7 @@ void ScFormulaCell::CompileNameFormula( bool bCreateFormulaString ) } if ( bRecompile ) { - OUString aFormula; - GetFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE); + OUString aFormula = GetFormula(rCxt); if ( GetMatrixFlag() != MM_NONE && !aFormula.isEmpty() ) { if ( aFormula[ aFormula.getLength()-1 ] == '}' ) @@ -3315,18 +3444,19 @@ void ScFormulaCell::CompileNameFormula( bool bCreateFormulaString ) EndListeningTo( pDocument ); pDocument->RemoveFromFormulaTree( this ); pCode->Clear(); - SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE); + SetHybridFormula(aFormula, rCxt.getGrammar()); } } else if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { - Compile( aResult.GetHybridFormula(), false, eTempGrammar ); + rCxt.setGrammar(eTempGrammar); + Compile(rCxt, aResult.GetHybridFormula(), false); aResult.SetToken( NULL); SetDirty(); } } -void ScFormulaCell::CompileColRowNameFormula() +void ScFormulaCell::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt ) { pCode->Reset(); for ( FormulaToken* p = pCode->First(); p; p = pCode->Next() ) @@ -3334,7 +3464,7 @@ void ScFormulaCell::CompileColRowNameFormula() if ( p->GetOpCode() == ocColRowName ) { bCompile = true; - CompileTokenArray(); + CompileTokenArray(rCxt); SetDirty(); break; } diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index e81a5e218811..ce0909d0aeb2 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -1704,44 +1704,46 @@ void ScTable::CalcAll() } -void ScTable::CompileAll() +void ScTable::CompileAll( sc::CompileFormulaContext& rCxt ) { - for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CompileAll(); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].CompileAll(rCxt); if(mpCondFormatList) mpCondFormatList->CompileAll(); } -void ScTable::CompileXML( ScProgress& rProgress ) +void ScTable::CompileXML( sc::CompileFormulaContext& rCxt, ScProgress& rProgress ) { if (mpRangeName) - mpRangeName->CompileUnresolvedXML(); + mpRangeName->CompileUnresolvedXML(rCxt); for (SCCOL i=0; i <= MAXCOL; i++) { - aCol[i].CompileXML( rProgress ); + aCol[i].CompileXML(rCxt, rProgress); } if(mpCondFormatList) mpCondFormatList->CompileXML(); } -bool ScTable::CompileErrorCells(sal_uInt16 nErrCode) +bool ScTable::CompileErrorCells( sc::CompileFormulaContext& rCxt, sal_uInt16 nErrCode ) { bool bCompiled = false; for (SCCOL i = 0; i <= MAXCOL; ++i) { - if (aCol[i].CompileErrorCells(nErrCode)) + if (aCol[i].CompileErrorCells(rCxt, nErrCode)) bCompiled = true; } return bCompiled; } -void ScTable::CalcAfterLoad() +void ScTable::CalcAfterLoad( sc::CompileFormulaContext& rCxt ) { - for (SCCOL i=0; i <= MAXCOL; i++) aCol[i].CalcAfterLoad(); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].CalcAfterLoad(rCxt); } bool ScTable::IsEmptyData( SCCOL nCol ) const diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index b7112bbc661b..9a50176a890d 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -2056,24 +2056,28 @@ bool ScTable::TestTabRefAbs(SCTAB nTable) const return false; } -void ScTable::CompileDBFormula() +void ScTable::CompileDBFormula( sc::CompileFormulaContext& rCxt ) { - for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula(); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].CompileDBFormula(rCxt); } -void ScTable::CompileDBFormula( bool bCreateFormulaString ) +void ScTable::CompileDBFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) { - for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileDBFormula( bCreateFormulaString ); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].CompileDBFormula(rCxt, bCreateFormulaString); } -void ScTable::CompileNameFormula( bool bCreateFormulaString ) +void ScTable::CompileNameFormula( sc::CompileFormulaContext& rCxt, bool bCreateFormulaString ) { - for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileNameFormula( bCreateFormulaString ); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].CompileNameFormula(rCxt, bCreateFormulaString); } -void ScTable::CompileColRowNameFormula() +void ScTable::CompileColRowNameFormula( sc::CompileFormulaContext& rCxt ) { - for (SCCOL i=0; i<=MAXCOL; i++) aCol[i].CompileColRowNameFormula(); + for (SCCOL i = 0; i <= MAXCOL; ++i) + aCol[i].CompileColRowNameFormula(rCxt); } diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index dcb676e4a001..4a1bbd723570 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -68,6 +68,7 @@ #include "formulaparserpool.hxx" #include "tokenarray.hxx" #include "scmatrix.hxx" +#include using namespace formula; using namespace ::com::sun::star; @@ -1529,6 +1530,24 @@ struct ConventionXL_R1C1 : public ScCompiler::Convention, public ConventionXL static const ConventionXL_R1C1 ConvXL_R1C1; const ScCompiler::Convention * const ScCompiler::pConvXL_R1C1 = &ConvXL_R1C1; +ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos, ScTokenArray& rArr ) : + FormulaCompiler(rArr), + pDoc(rCxt.getDoc()), + aPos(rPos), + mpFormatter(pDoc->GetFormatTable()), + pCharClass(ScGlobal::pCharClass), + mnPredetectedReference(0), + mnRangeOpPosInSymbol(-1), + pConv(GetRefConvention(FormulaGrammar::CONV_OOO)), + meExtendedErrorDetection(EXTENDED_ERROR_DETECTION_NONE), + mbCloseBrackets(true), + mbRewind(false), + maTabNames(rCxt.getTabNames()) +{ + nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0; + SetGrammar(rCxt.getGrammar()); +} + ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArray& rArr) : FormulaCompiler(rArr), pDoc( pDocument ), @@ -1555,6 +1574,23 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra } } +ScCompiler::ScCompiler( sc::CompileFormulaContext& rCxt, const ScAddress& rPos ) : + pDoc(rCxt.getDoc()), + aPos(rPos), + mpFormatter(pDoc ? pDoc->GetFormatTable() : NULL), + pCharClass(ScGlobal::pCharClass), + mnPredetectedReference(0), + mnRangeOpPosInSymbol(-1), + pConv(GetRefConvention(FormulaGrammar::CONV_OOO)), + meExtendedErrorDetection(EXTENDED_ERROR_DETECTION_NONE), + mbCloseBrackets(true), + mbRewind(false), + maTabNames(rCxt.getTabNames()) +{ + nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0; + SetGrammar(rCxt.getGrammar()); +} + ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos) : pDoc( pDocument ), diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 6130c614a138..5d88ee8c6959 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -34,6 +34,7 @@ #include "refupdat.hxx" #include "document.hxx" #include "refupdatecontext.hxx" +#include #include "formula/errorcodes.hxx" @@ -181,14 +182,14 @@ void ScRangeData::CompileRangeData( const OUString& rSymbol, bool bSetError ) } } -void ScRangeData::CompileUnresolvedXML() +void ScRangeData::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ) { if (pCode->GetCodeError() == errNoName) { // Reconstruct the symbol/formula and then recompile. OUString aSymbol; - ScCompiler aComp( pDoc, aPos, *pCode); - aComp.SetGrammar( eTempGrammar); + rCxt.setGrammar(eTempGrammar); + ScCompiler aComp(rCxt, aPos, *pCode); aComp.CreateStringFromTokenArray( aSymbol); // Don't let the compiler set an error for unknown names on final // compile, errors are handled by the interpreter thereafter. @@ -764,11 +765,11 @@ void ScRangeName::UpdateGrow(const ScRange& rArea, SCCOL nGrowX, SCROW nGrowY) itr->second->UpdateGrow(rArea, nGrowX, nGrowY); } -void ScRangeName::CompileUnresolvedXML() +void ScRangeName::CompileUnresolvedXML( sc::CompileFormulaContext& rCxt ) { DataType::iterator itr = maData.begin(), itrEnd = maData.end(); for (; itr != itrEnd; ++itr) - itr->second->CompileUnresolvedXML(); + itr->second->CompileUnresolvedXML(rCxt); } ScRangeName::const_iterator ScRangeName::begin() const diff --git a/sc/source/core/tool/tokenstringcontext.cxx b/sc/source/core/tool/tokenstringcontext.cxx index a68ae759299a..203d36aaf3e8 100644 --- a/sc/source/core/tool/tokenstringcontext.cxx +++ b/sc/source/core/tool/tokenstringcontext.cxx @@ -105,6 +105,49 @@ TokenStringContext::TokenStringContext( const ScDocument* pDoc, formula::Formula } } +CompileFormulaContext::CompileFormulaContext( ScDocument* pDoc ) : + mpDoc(pDoc), meGram(pDoc->GetGrammar()) +{ + if (!pDoc) + return; + + updateTabNames(); +} + +void CompileFormulaContext::updateTabNames() +{ + // Fetch all sheet names. + maTabNames = mpDoc->GetAllTableNames(); + { + std::vector::iterator it = maTabNames.begin(), itEnd = maTabNames.end(); + for (; it != itEnd; ++it) + ScCompiler::CheckTabQuotes(*it, formula::FormulaGrammar::extractRefConvention(meGram)); + } +} + +formula::FormulaGrammar::Grammar CompileFormulaContext::getGrammar() const +{ + return meGram; +} + +void CompileFormulaContext::setGrammar( formula::FormulaGrammar::Grammar eGram ) +{ + bool bUpdate = (meGram != eGram); + meGram = eGram; + if (bUpdate) + updateTabNames(); +} + +const std::vector& CompileFormulaContext::getTabNames() const +{ + return maTabNames; +} + +ScDocument* CompileFormulaContext::getDoc() +{ + return mpDoc; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ -- cgit v1.2.3