diff options
author | Markus Mohrhard <markus.mohrhard@googlemail.com> | 2013-01-24 00:32:41 +0100 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-01-25 18:41:33 +0000 |
commit | a2ebd811d4049e2ed03c677cbc7d0e2c8515b797 (patch) | |
tree | d20c22e19fedf92f24b7115272a7f34b8d2282dc | |
parent | 36e31ab6551579bf69012d0ba803fcb5fb17a062 (diff) |
import inherited number formats with cached values, fdo#59724
Change-Id: I698f60daf4e591b57d8d99c130d2e524dc10c306
Reviewed-on: https://gerrit.libreoffice.org/1866
Reviewed-by: Kohei Yoshida <kohei.yoshida@gmail.com>
Tested-by: Kohei Yoshida <kohei.yoshida@gmail.com>
-rw-r--r-- | formula/inc/formula/token.hxx | 3 | ||||
-rw-r--r-- | sc/inc/cell.hxx | 8 | ||||
-rw-r--r-- | sc/inc/formularesult.hxx | 4 | ||||
-rw-r--r-- | sc/inc/token.hxx | 45 | ||||
-rw-r--r-- | sc/source/core/data/cell.cxx | 12 | ||||
-rw-r--r-- | sc/source/core/data/cell2.cxx | 9 | ||||
-rw-r--r-- | sc/source/core/tool/cellform.cxx | 2 | ||||
-rw-r--r-- | sc/source/core/tool/formularesult.cxx | 26 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 8 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlcelli.cxx | 48 | ||||
-rw-r--r-- | sc/source/filter/xml/xmlcelli.hxx | 6 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh.cxx | 4 |
12 files changed, 123 insertions, 52 deletions
diff --git a/formula/inc/formula/token.hxx b/formula/inc/formula/token.hxx index b72234e8fae5..3a174d7b9d4f 100644 --- a/formula/inc/formula/token.hxx +++ b/formula/inc/formula/token.hxx @@ -58,6 +58,9 @@ enum StackVarEnum // and/or string result and a formula // string to be compiled. + svHybridValueCell, // A temporary formula cell with an value + // and possibily a string representation + svExternalSingleRef, svExternalDoubleRef, svExternalName, diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx index 008b51026ba7..0322db6e5b9f 100644 --- a/sc/inc/cell.hxx +++ b/sc/inc/cell.hxx @@ -429,6 +429,7 @@ public: // display as empty string if formula::svEmptyCell result bool IsEmptyDisplayedAsString(); bool IsValue(); // also true if formula::svEmptyCell + bool IsHybridValueCell(); // for cells after import to deal with inherited number formats double GetValue(); double GetValueAlways(); // ignore errors rtl::OUString GetString(); @@ -492,6 +493,13 @@ public: const formula::FormulaGrammar::Grammar eGrammar ) { aResult.SetHybridFormula( r); eTempGrammar = eGrammar; } + /** + * For import only: use for formula cells that return a number + * formatted as some kind of string + */ + void SetHybridValueString( double nVal, const OUString& r ) + { aResult.SetHybridValueString( nVal, r ); } + void SetResultMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) { aResult.SetMatrix(nCols, nRows, pMat, pUL); diff --git a/sc/inc/formularesult.hxx b/sc/inc/formularesult.hxx index 2128636816b6..673bcdbf84bc 100644 --- a/sc/inc/formularesult.hxx +++ b/sc/inc/formularesult.hxx @@ -162,7 +162,7 @@ public: ScConstMatrixRef GetMatrix() const; /** Return formula string if type formula::svHybridCell, else empty string. */ - const String& GetHybridFormula() const; + const OUString& GetHybridFormula() const; /** Should only be used by import filters, best in the order SetHybridDouble(), SetHybridString(), or only SetHybridString() for @@ -179,6 +179,8 @@ public: SetHybridFormula() for formula string to be compiled later. */ SC_DLLPUBLIC void SetHybridFormula( const String & rFormula ); + void SetHybridValueString( double nVal, const OUString& rStr ); + SC_DLLPUBLIC void SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ); /** Get the const ScMatrixFormulaCellToken* if token is of that type, else diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx index e08db6cb440c..a54055561bae 100644 --- a/sc/inc/token.hxx +++ b/sc/inc/token.hxx @@ -414,26 +414,37 @@ public: class SC_DLLPUBLIC ScHybridCellToken : public ScToken { private: - double fDouble; - String aString; - String aFormula; + double mfDouble; + String maString; + OUString maFormula; public: - ScHybridCellToken( double f, - const String & rStr, - const String & rFormula ) : - ScToken( formula::svHybridCell ), - fDouble( f ), aString( rStr ), - aFormula( rFormula ) {} - ScHybridCellToken( const ScHybridCellToken& r ) : - ScToken( r ), fDouble( r.fDouble), - aString( r.aString), aFormula( r.aFormula) {} - const String & GetFormula() const { return aFormula; } - virtual double GetDouble() const; - virtual const String & GetString() const; - virtual bool operator==( const formula::FormulaToken& rToken ) const; - virtual FormulaToken* Clone() const { return new ScHybridCellToken(*this); } + ScHybridCellToken( double f, + const OUString & rStr, + const OUString & rFormula ) : + ScToken( formula::svHybridCell ), + mfDouble( f ), maString( rStr ), + maFormula( rFormula ) {} + + const OUString& GetFormula() const { return maFormula; } + virtual double GetDouble() const; + virtual const String& GetString() const; + virtual bool operator==( const formula::FormulaToken& rToken ) const; + virtual FormulaToken* Clone() const { return new ScHybridCellToken(*this); } }; +class SC_DLLPUBLIC ScHybridValueCellToken : public ScToken +{ +private: + double mfValue; + String maString; +public: + ScHybridValueCellToken (double f, const OUString& rStr ): + ScToken( formula::svHybridValueCell ), + mfValue( f ), maString( rStr ) {} + + virtual double GetDouble() const { return mfValue; } + virtual const String & GetString() const { return maString; } +}; // Simplify argument passing to RefUpdate methods with ScSingleRefToken or // ScDoubleRefToken diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index bbf89760597f..e938ffe4e78c 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -978,7 +978,7 @@ void ScFormulaCell::Compile( const rtl::OUString& rFormula, bool bNoListening, delete pCodeOld; if( !pCode->GetCodeError() ) { - if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() && rFormula == rtl::OUString(aResult.GetHybridFormula()) ) + if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() && rFormula == aResult.GetHybridFormula() ) { // not recursive CompileTokenArray/Compile/CompileTokenArray if ( rFormula[0] == '=' ) pCode->AddBad( rFormula.copy(1) ); @@ -1002,7 +1002,7 @@ void ScFormulaCell::Compile( const rtl::OUString& rFormula, bool bNoListening, void ScFormulaCell::CompileTokenArray( bool bNoListening ) { // Not already compiled? - if( !pCode->GetLen() && aResult.GetHybridFormula().Len() ) + if( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) Compile( aResult.GetHybridFormula(), bNoListening, eTempGrammar); else if( bCompile && !pDocument->IsClipOrUndo() && !pCode->GetCodeError() ) { @@ -1110,7 +1110,7 @@ void ScFormulaCell::CalcAfterLoad() { bool bNewCompiled = false; // If a Calc 1.0-doc is read, we have a result, but no token array - if( !pCode->GetLen() && aResult.GetHybridFormula().Len() ) + if( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { Compile( aResult.GetHybridFormula(), true, eTempGrammar); aResult.SetToken( NULL); @@ -1459,7 +1459,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) // This should only be a temporary condition and, since we set an // error, if ran into it again we'd bump into the dirty-clearing // condition further down. - if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() ) + if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { pCode->SetCodeError( errNoCode ); // This is worth an assertion; if encountered in daily work @@ -1595,7 +1595,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) } else { - if ( eOld == svHybridCell ) // string result from SetFormulaResultString? + if ( eOld == svHybridCell || eOld == svHybridValueCell ) // string result from SetFormulaResultString? eOld = svString; // ScHybridCellToken has a valid GetString method // #i106045# use approxEqual to compare with stored value @@ -1620,7 +1620,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) if ( bChanged && !bContentChanged && pDocument->IsStreamValid(aPos.Tab()) ) { if ( ( eOld == svUnknown && ( eNew == svError || ( eNew == svDouble && aNewResult.GetDouble() == 0.0 ) ) ) || - ( eOld == svHybridCell && eNew == svString && aResult.GetString() == aNewResult.GetString() ) || + ( (eOld == svHybridCell || eOld == svHybridValueCell) && eNew == svString && aResult.GetString() == aNewResult.GetString() ) || ( eOld == svDouble && eNew == svDouble && rtl::math::approxEqual( aResult.GetDouble(), aNewResult.GetDouble() ) ) ) { // no change, see above diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx index bcf52836183e..c23377fd4341 100644 --- a/sc/source/core/data/cell2.cxx +++ b/sc/source/core/data/cell2.cxx @@ -496,6 +496,11 @@ bool ScFormulaCell::IsValue() return aResult.IsValue(); } +bool ScFormulaCell::IsHybridValueCell() +{ + return aResult.GetType() == formula::svHybridValueCell; +} + double ScFormulaCell::GetValue() { MaybeInterpret(); @@ -1600,7 +1605,7 @@ void ScFormulaCell::CompileDBFormula( bool bCreateFormulaString ) SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE); } } - else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() ) + else if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { Compile( aResult.GetHybridFormula(), false, eTempGrammar ); aResult.SetToken( NULL); @@ -1647,7 +1652,7 @@ void ScFormulaCell::CompileNameFormula( bool bCreateFormulaString ) SetHybridFormula( aFormula, formula::FormulaGrammar::GRAM_NATIVE); } } - else if ( !pCode->GetLen() && aResult.GetHybridFormula().Len() ) + else if ( !pCode->GetLen() && !aResult.GetHybridFormula().isEmpty() ) { Compile( aResult.GetHybridFormula(), false, eTempGrammar ); aResult.SetToken( NULL); diff --git a/sc/source/core/tool/cellform.cxx b/sc/source/core/tool/cellform.cxx index 01dc61be7470..4a3ecc668d50 100644 --- a/sc/source/core/tool/cellform.cxx +++ b/sc/source/core/tool/cellform.cxx @@ -125,6 +125,8 @@ void ScCellFormat::GetString( ScBaseCell* pCell, sal_uLong nFormat, rtl::OUStrin double fValue = pFCell->GetValue(); if ( !bNullVals && fValue == 0.0 ) rString = rtl::OUString(); + else if ( pFCell->IsHybridValueCell() ) + rString = pFCell->GetString(); else rFormatter.GetOutputString( fValue, nFormat, rString, ppColor, bUseStarFormat ); } diff --git a/sc/source/core/tool/formularesult.cxx b/sc/source/core/tool/formularesult.cxx index 9e1032ec9d44..791dbadcea86 100644 --- a/sc/source/core/tool/formularesult.cxx +++ b/sc/source/core/tool/formularesult.cxx @@ -268,7 +268,8 @@ bool ScFormulaResult::IsEmptyDisplayedAsString() const bool ScFormulaResult::IsValue() const { formula::StackVar sv = GetCellResultType(); - return sv == formula::svDouble || sv == formula::svError || sv == formula::svEmptyCell; + return sv == formula::svDouble || sv == formula::svError + || sv == formula::svEmptyCell || sv == formula::svHybridValueCell; } bool ScFormulaResult::IsMultiline() const @@ -331,6 +332,7 @@ double ScFormulaResult::GetDouble() const switch (mpToken->GetType()) { case formula::svHybridCell: + case formula::svHybridValueCell: return mpToken->GetDouble(); case formula::svMatrixCell: { @@ -359,6 +361,7 @@ const String & ScFormulaResult::GetString() const { case formula::svString: case formula::svHybridCell: + case formula::svHybridValueCell: return mpToken->GetString(); case formula::svMatrixCell: { @@ -382,7 +385,7 @@ ScConstMatrixRef ScFormulaResult::GetMatrix() const return NULL; } -const String & ScFormulaResult::GetHybridFormula() const +const OUString& ScFormulaResult::GetHybridFormula() const { if (GetType() == formula::svHybridCell) { @@ -390,7 +393,7 @@ const String & ScFormulaResult::GetHybridFormula() const if (p) return p->GetFormula(); } - return EMPTY_STRING; + return EMPTY_OUSTRING; } void ScFormulaResult::SetHybridDouble( double f ) @@ -443,6 +446,23 @@ void ScFormulaResult::SetHybridFormula( const String & rFormula ) mbToken = true; } +void ScFormulaResult::SetHybridValueString( double nVal, const OUString& rStr ) +{ + if(GetType() == formula::svMatrixCell) + { + SetDouble(nVal); + return; + } + + ResetToDefaults(); + if (mbToken && mpToken) + mpToken->DecRef(); + + mpToken = new ScHybridValueCellToken( nVal, rStr ); + mpToken->IncRef(); + mbToken = true; +} + void ScFormulaResult::SetMatrix( SCCOL nCols, SCROW nRows, const ScConstMatrixRef& pMat, formula::FormulaToken* pUL ) { ResetToDefaults(); diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index 4ea3d4e056b6..8e8c329727ab 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1096,13 +1096,13 @@ void ScMatrixFormulaCellToken::SetUpperLeftDouble( double f ) } -double ScHybridCellToken::GetDouble() const { return fDouble; } -const String & ScHybridCellToken::GetString() const { return aString; } +double ScHybridCellToken::GetDouble() const { return mfDouble; } +const String& ScHybridCellToken::GetString() const { return maString; } bool ScHybridCellToken::operator==( const FormulaToken& r ) const { return FormulaToken::operator==( r ) && - fDouble == r.GetDouble() && aString == r.GetString() && - aFormula == static_cast<const ScHybridCellToken &>(r).GetFormula(); + mfDouble == r.GetDouble() && maString == r.GetString() && + maFormula == static_cast<const ScHybridCellToken &>(r).GetFormula(); } diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index 6e73782a5b4b..42714a1bf648 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -122,7 +122,9 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport, bHasTextImport(false), bIsFirstTextImport(false), bSolarMutexLocked(false), - bFormulaTextResult(false) + bFormulaTextResult(false), + mbPossibleErrorCell(false), + mbCheckWithCompilerForError(false) { rtl::math::setNan(&fValue); // NaN by default @@ -352,9 +354,13 @@ SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( sal_uInt16 nPr ScAddress aCellPos = rXMLImport.GetTables().GetCurrentCellPos(); - if( ((nCellType == util::NumberFormat::TEXT) || bFormulaTextResult) ) + if( ((nCellType == util::NumberFormat::TEXT) || pOUFormula || bFormulaTextResult) ) { - if (!bHasTextImport) + if ( pOUFormula ) + { + pContext = new ScXMLTextPContext(rXMLImport, nPrefix, rLName, xAttrList, this); + } + else if (!bHasTextImport) { bIsFirstTextImport = true; bHasTextImport = true; @@ -725,7 +731,7 @@ void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const { if( bFormulaTextResult && pOUTextValue ) { - if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue)) + if( !IsPossibleErrorString() ) { pFCell->SetHybridString( *pOUTextValue ); pFCell->ResetDirty(); @@ -733,11 +739,13 @@ void ScXMLTableRowCellContext::SetFormulaCell(ScFormulaCell* pFCell) const } else if (!rtl::math::isNan(fValue)) { - pFCell->SetHybridDouble(fValue); + if( pOUTextContent ) + pFCell->SetHybridValueString( fValue, *pOUTextContent ); + else + pFCell->SetHybridDouble(fValue); pFCell->ResetDirty(); } pFCell->StartListeningTo(rXMLImport.GetDocument()); - // Leave the cell dirty when the cached result is not given. } } @@ -766,7 +774,7 @@ void ScXMLTableRowCellContext::PutTextCell( const ScAddress& rCurrentPos, if(!aCellString.isEmpty()) { - if (bDoIncrement && !GetScImport().IsFormulaErrorConstant(aCellString)) + if (bDoIncrement && !IsPossibleErrorString()) { pFCell->SetHybridString( aCellString ); pFCell->ResetDirty(); @@ -1113,7 +1121,7 @@ void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos ) ScMatrixRef pMat(new ScMatrix(nMatrixCols, nMatrixRows)); if (bFormulaTextResult && pOUTextValue) { - if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue)) + if (!IsPossibleErrorString()) { pFCell->SetResultMatrix( nMatrixCols, nMatrixRows, pMat, new formula::FormulaStringToken(*pOUTextValue)); @@ -1153,14 +1161,20 @@ void ScXMLTableRowCellContext::AddFormulaCell( const ScAddress& rCellPos ) // - is blank // - has a constant error value beginning with "#" (such as "#VALUE!" or "#N/A") // - has an "Err:[###]" (where "[###]" is an error number) -bool ScXMLTableRowCellContext::HasSpecialCaseFormulaText() const +void ScXMLTableRowCellContext::HasSpecialCaseFormulaText() +{ + if( pOUTextContent ) + { + if ( pOUTextContent->isEmpty() || (pOUTextContent->indexOf("Err:") > -1) ) + mbPossibleErrorCell = true; + else if (pOUTextContent->indexOf("#") > -1) + mbCheckWithCompilerForError = true; + } +} + +bool ScXMLTableRowCellContext::IsPossibleErrorString() const { - if( pOUTextContent && - ( pOUTextContent->isEmpty() || (pOUTextContent->indexOf("#") > -1) || - (pOUTextContent->indexOf("Err:") > -1) ) - ) - return true; - return false; + return mbPossibleErrorCell || ( mbCheckWithCompilerForError && GetScImport().IsFormulaErrorConstant(*pOUTextValue) ); } @@ -1179,8 +1193,8 @@ void ScXMLTableRowCellContext::EndElement() aTextImport->ResetCursor(); } } - - if( bFormulaTextResult && HasSpecialCaseFormulaText() ) + HasSpecialCaseFormulaText(); + if( bFormulaTextResult && (mbPossibleErrorCell || mbCheckWithCompilerForError) ) { pOUTextValue.reset(*pOUTextContent); nCellType = util::NumberFormat::TEXT; diff --git a/sc/source/filter/xml/xmlcelli.hxx b/sc/source/filter/xml/xmlcelli.hxx index 32f0698e9ad4..2bf8b8c6a3e1 100644 --- a/sc/source/filter/xml/xmlcelli.hxx +++ b/sc/source/filter/xml/xmlcelli.hxx @@ -65,6 +65,8 @@ class ScXMLTableRowCellContext : public SvXMLImportContext bool bIsFirstTextImport; bool bSolarMutexLocked; bool bFormulaTextResult; + bool mbPossibleErrorCell; + bool mbCheckWithCompilerForError; const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } @@ -92,7 +94,9 @@ class ScXMLTableRowCellContext : public SvXMLImportContext void PutFormulaCell ( const ScAddress& rScCurrentPos ); void AddFormulaCell ( const ScAddress& rScCellPos ); - bool HasSpecialCaseFormulaText() const; + void HasSpecialCaseFormulaText(); + + bool IsPossibleErrorString() const; public: diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 43fd526a25af..d7bcfcc4cae0 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -466,8 +466,10 @@ sal_Bool ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::un if (bHardRecalc) DoHardRecalc(false); else + { // still need to recalc volatile formula cells. - aDocument.CalcFormulaTree(false, true, false); + aDocument.Broadcast( SC_HINT_DATACHANGED, BCA_BRDCST_ALWAYS, NULL ); + } bool bAdjustHeightOld = aDocument.IsAdjustHeightEnabled(); aDocument.EnableAdjustHeight(false); |