summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Mohrhard <markus.mohrhard@googlemail.com>2013-01-24 00:32:41 +0100
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-01-25 18:41:33 +0000
commita2ebd811d4049e2ed03c677cbc7d0e2c8515b797 (patch)
treed20c22e19fedf92f24b7115272a7f34b8d2282dc
parent36e31ab6551579bf69012d0ba803fcb5fb17a062 (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.hxx3
-rw-r--r--sc/inc/cell.hxx8
-rw-r--r--sc/inc/formularesult.hxx4
-rw-r--r--sc/inc/token.hxx45
-rw-r--r--sc/source/core/data/cell.cxx12
-rw-r--r--sc/source/core/data/cell2.cxx9
-rw-r--r--sc/source/core/tool/cellform.cxx2
-rw-r--r--sc/source/core/tool/formularesult.cxx26
-rw-r--r--sc/source/core/tool/token.cxx8
-rw-r--r--sc/source/filter/xml/xmlcelli.cxx48
-rw-r--r--sc/source/filter/xml/xmlcelli.hxx6
-rw-r--r--sc/source/ui/docshell/docsh.cxx4
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);