[PATCH] Change in core[libreoffice-4-0-0]: import inherited number formats with cached values, fdo#5972...

Markus Mohrhard (via Code Review) gerrit at gerrit.libreoffice.org
Fri Jan 25 10:55:04 PST 2013


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 at gmail.com>
Tested-by: Kohei Yoshida <kohei.yoshida at 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 at googlemail.com>
Gerrit-Reviewer: Kohei Yoshida <kohei.yoshida at gmail.com>



More information about the LibreOffice mailing list