summaryrefslogtreecommitdiff
path: root/sc/source/core/data/formulacell.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/core/data/formulacell.cxx')
-rw-r--r--sc/source/core/data/formulacell.cxx172
1 files changed, 151 insertions, 21 deletions
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 <tokenstringcontext.hxx>
#include <boost/scoped_ptr.hpp>
@@ -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<ScToken*>(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;
}