Hi,
I have submitted a patch for review:
https://gerrit.libreoffice.org/1870
To pull it, you can do:
git pull ssh://gerrit.libreoffice.org:29418/core refs/changes/70/1870/1
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>
---
M formula/inc/formula/token.hxx
M sc/inc/cell.hxx
M sc/inc/formularesult.hxx
M sc/inc/token.hxx
M sc/source/core/data/cell.cxx
M sc/source/core/data/cell2.cxx
M sc/source/core/tool/cellform.cxx
M sc/source/core/tool/formularesult.cxx
M sc/source/core/tool/token.cxx
M sc/source/filter/xml/xmlcelli.cxx
M sc/source/filter/xml/xmlcelli.hxx
M sc/source/ui/docshell/docsh.cxx
12 files changed, 123 insertions(+), 52 deletions(-)
diff --git a/formula/inc/formula/token.hxx b/formula/inc/formula/token.hxx
index b72234e..3a174d7 100644
--- a/formula/inc/formula/token.hxx
+++ b/formula/inc/formula/token.hxx
@@ -58,6 +58,9 @@
// 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 008b510..0322db6 100644
--- a/sc/inc/cell.hxx
+++ b/sc/inc/cell.hxx
@@ -429,6 +429,7 @@
// 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 @@
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 2128636..673bcdb 100644
--- a/sc/inc/formularesult.hxx
+++ b/sc/inc/formularesult.hxx
@@ -162,7 +162,7 @@
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 @@
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 e08db6c..a540555 100644
--- a/sc/inc/token.hxx
+++ b/sc/inc/token.hxx
@@ -414,26 +414,37 @@
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 bbf8976..e938ffe 100644
--- a/sc/source/core/data/cell.cxx
+++ b/sc/source/core/data/cell.cxx
@@ -978,7 +978,7 @@
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::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 @@
{
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 @@
// 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 @@
}
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 @@
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 bcf5283..c23377f 100644
--- a/sc/source/core/data/cell2.cxx
+++ b/sc/source/core/data/cell2.cxx
@@ -496,6 +496,11 @@
return aResult.IsValue();
}
+bool ScFormulaCell::IsHybridValueCell()
+{
+ return aResult.GetType() == formula::svHybridValueCell;
+}
+
double ScFormulaCell::GetValue()
{
MaybeInterpret();
@@ -1600,7 +1605,7 @@
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 @@
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 01dc61b..4a3ecc6 100644
--- a/sc/source/core/tool/cellform.cxx
+++ b/sc/source/core/tool/cellform.cxx
@@ -125,6 +125,8 @@
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 9e1032e..791dbad 100644
--- a/sc/source/core/tool/formularesult.cxx
+++ b/sc/source/core/tool/formularesult.cxx
@@ -268,7 +268,8 @@
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 @@
switch (mpToken->GetType())
{
case formula::svHybridCell:
+ case formula::svHybridValueCell:
return mpToken->GetDouble();
case formula::svMatrixCell:
{
@@ -359,6 +361,7 @@
{
case formula::svString:
case formula::svHybridCell:
+ case formula::svHybridValueCell:
return mpToken->GetString();
case formula::svMatrixCell:
{
@@ -382,7 +385,7 @@
return NULL;
}
-const String & ScFormulaResult::GetHybridFormula() const
+const OUString& ScFormulaResult::GetHybridFormula() const
{
if (GetType() == formula::svHybridCell)
{
@@ -390,7 +393,7 @@
if (p)
return p->GetFormula();
}
- return EMPTY_STRING;
+ return EMPTY_OUSTRING;
}
void ScFormulaResult::SetHybridDouble( double f )
@@ -443,6 +446,23 @@
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 4ea3d4e..8e8c329 100644
--- a/sc/source/core/tool/token.cxx
+++ b/sc/source/core/tool/token.cxx
@@ -1096,13 +1096,13 @@
}
-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 6e73782..42714a1 100644
--- a/sc/source/filter/xml/xmlcelli.cxx
+++ b/sc/source/filter/xml/xmlcelli.cxx
@@ -122,7 +122,9 @@
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 @@
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 @@
{
if( bFormulaTextResult && pOUTextValue )
{
- if (!GetScImport().IsFormulaErrorConstant(*pOUTextValue))
+ if( !IsPossibleErrorString() )
{
pFCell->SetHybridString( *pOUTextValue );
pFCell->ResetDirty();
@@ -733,11 +739,13 @@
}
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 @@
if(!aCellString.isEmpty())
{
- if (bDoIncrement && !GetScImport().IsFormulaErrorConstant(aCellString))
+ if (bDoIncrement && !IsPossibleErrorString())
{
pFCell->SetHybridString( aCellString );
pFCell->ResetDirty();
@@ -1113,7 +1121,7 @@
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 @@
// - 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 &&
- ( pOUTextContent->isEmpty() || (pOUTextContent->indexOf("#") > -1) ||
- (pOUTextContent->indexOf("Err:") > -1) )
- )
- return true;
- return false;
+ if( pOUTextContent )
+ {
+ if ( pOUTextContent->isEmpty() || (pOUTextContent->indexOf("Err:") > -1) )
+ mbPossibleErrorCell = true;
+ else if (pOUTextContent->indexOf("#") > -1)
+ mbCheckWithCompilerForError = true;
+ }
+}
+
+bool ScXMLTableRowCellContext::IsPossibleErrorString() const
+{
+ return mbPossibleErrorCell || ( mbCheckWithCompilerForError &&
GetScImport().IsFormulaErrorConstant(*pOUTextValue) );
}
@@ -1179,8 +1193,8 @@
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 32f0698..2bf8b8c 100644
--- a/sc/source/filter/xml/xmlcelli.hxx
+++ b/sc/source/filter/xml/xmlcelli.hxx
@@ -65,6 +65,8 @@
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 @@
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 43fd526..d7bcfcc 100644
--- a/sc/source/ui/docshell/docsh.cxx
+++ b/sc/source/ui/docshell/docsh.cxx
@@ -466,8 +466,10 @@
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);
--
To view, visit https://gerrit.libreoffice.org/1870
To unsubscribe, visit https://gerrit.libreoffice.org/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I698f60daf4e591b57d8d99c130d2e524dc10c306
Gerrit-PatchSet: 1
Gerrit-Project: core
Gerrit-Branch: libreoffice-4-0-0
Gerrit-Owner: Markus Mohrhard <markus.mohrhard@googlemail.com>
Gerrit-Reviewer: Kohei Yoshida <kohei.yoshida@gmail.com>
Context
- [PATCH] Change in core[libreoffice-4-0-0]: import inherited number formats with cached values, fdo#5972... · Markus Mohrhard (via Code Review)
Privacy Policy |
Impressum (Legal Info) |
Copyright information: Unless otherwise specified, all text and images
on this website are licensed under the
Creative Commons Attribution-Share Alike 3.0 License.
This does not include the source code of LibreOffice, which is
licensed under the Mozilla Public License (
MPLv2).
"LibreOffice" and "The Document Foundation" are
registered trademarks of their corresponding registered owners or are
in actual use as trademarks in one or more countries. Their respective
logos and icons are also subject to international copyright laws. Use
thereof is explained in our
trademark policy.