[Libreoffice-commits] core.git: sc/source

Eike Rathke erack at redhat.com
Sat Oct 15 14:50:19 UTC 2016


 sc/source/filter/inc/workbookhelper.hxx |    2 ++
 sc/source/filter/oox/formulabuffer.cxx  |   32 ++++++++++++++++++++++----------
 sc/source/filter/oox/workbookhelper.cxx |   17 ++++++++++++++++-
 3 files changed, 40 insertions(+), 11 deletions(-)

New commits:
commit 2a45b26c619d1125419819d501a7653cf8d6e5ca
Author: Eike Rathke <erack at redhat.com>
Date:   Sat Oct 15 16:42:42 2016 +0200

    Resolves: tdf#98481 Google Sheets uses OOXML t="str" differently
    
    Set string results only for known good generators, otherwise
    recalculate. See source code comment.
    
    Change-Id: Ib89ba70fd7c3c515439498882fef90ca7c6e278d

diff --git a/sc/source/filter/inc/workbookhelper.hxx b/sc/source/filter/inc/workbookhelper.hxx
index c3af3dd..13f0b1c 100644
--- a/sc/source/filter/inc/workbookhelper.hxx
+++ b/sc/source/filter/inc/workbookhelper.hxx
@@ -122,6 +122,8 @@ public:
     SegmentProgressBar& getProgressBar() const;
     /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */
     sal_Int16           getCurrentSheetIndex() const;
+    /** Returns true when reading a file generated by a known good generator. */
+    bool                isGeneratorKnownGood() const;
 
     /** Sets the VBA project storage used to import VBA source code and forms. */
     void                setVbaProjectStorage( const StorageRef& rxVbaPrjStrg );
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 73d01e7..bed3f5f 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -255,7 +255,7 @@ void applyArrayFormulas(
 }
 
 void applyCellFormulaValues(
-    ScDocumentImport& rDoc, const std::vector<FormulaBuffer::FormulaValue>& rVector )
+    ScDocumentImport& rDoc, const std::vector<FormulaBuffer::FormulaValue>& rVector, bool bGeneratorKnownGood )
 {
     svl::SharedStringPool& rStrPool = rDoc.getDoc().GetSharedStringPool();
 
@@ -278,12 +278,23 @@ void applyCellFormulaValues(
             }
             break;
             case XML_str:
-            {
-                svl::SharedString aSS = rStrPool.intern(rValueStr);
-                pCell->SetResultToken(new formula::FormulaStringToken(aSS));
-                pCell->ResetDirty();
-                pCell->SetChanged(false);
-            }
+                // Excel uses t="str" for string results (per definition
+                // ECMA-376 18.18.11 ST_CellType (Cell Type) "Cell containing a
+                // formula string.", but that 't' Cell Data Type attribute, "an
+                // enumeration representing the cell's data type", is meant for
+                // the content of the <v> element). We follow that. Other
+                // applications might not and instead use t="str" for the cell
+                // content if formula. Setting an otherwise numeric result as
+                // string result fouls things up, set result strings only for
+                // documents claiming to be generated by a known good
+                // generator. See tdf#98481
+                if (bGeneratorKnownGood)
+                {
+                    svl::SharedString aSS = rStrPool.intern(rValueStr);
+                    pCell->SetResultToken(new formula::FormulaStringToken(aSS));
+                    pCell->ResetDirty();
+                    pCell->SetChanged(false);
+                }
             break;
             default:
                 ;
@@ -293,7 +304,7 @@ void applyCellFormulaValues(
 
 void processSheetFormulaCells(
     ScDocumentImport& rDoc, FormulaBuffer::SheetItem& rItem, SvNumberFormatter& rFormatter,
-    const uno::Sequence<sheet::ExternalLinkInfo>& rExternalLinks )
+    const uno::Sequence<sheet::ExternalLinkInfo>& rExternalLinks, bool bGeneratorKnownGood )
 {
     if (rItem.mpSharedFormulaEntries && rItem.mpSharedFormulaIDs)
         applySharedFormulas(rDoc, rFormatter, *rItem.mpSharedFormulaEntries, *rItem.mpSharedFormulaIDs);
@@ -308,7 +319,7 @@ void processSheetFormulaCells(
         applyArrayFormulas(rDoc, rFormatter, *rItem.mpArrayFormulas);
 
     if (rItem.mpCellFormulaValues)
-        applyCellFormulaValues(rDoc, *rItem.mpCellFormulaValues);
+        applyCellFormulaValues(rDoc, *rItem.mpCellFormulaValues, bGeneratorKnownGood);
 }
 
 }
@@ -362,7 +373,8 @@ void FormulaBuffer::finalizeImport()
     std::vector<SheetItem>::iterator it = aSheetItems.begin(), itEnd = aSheetItems.end();
 
     for (; it != itEnd; ++it)
-        processSheetFormulaCells(rDoc, *it, *rDoc.getDoc().GetFormatTable(), getExternalLinks().getLinkInfos());
+        processSheetFormulaCells(rDoc, *it, *rDoc.getDoc().GetFormatTable(), getExternalLinks().getLinkInfos(),
+                isGeneratorKnownGood());
 
     rDoc.getDoc().SetAutoNameCache(nullptr);
 
diff --git a/sc/source/filter/oox/workbookhelper.cxx b/sc/source/filter/oox/workbookhelper.cxx
index 44425e3..20bfade 100644
--- a/sc/source/filter/oox/workbookhelper.cxx
+++ b/sc/source/filter/oox/workbookhelper.cxx
@@ -132,6 +132,8 @@ public:
     const StorageRef&   getVbaProjectStorage() const { return mxVbaPrjStrg; }
     /** Returns the index of the current Calc sheet, if filter currently processes a sheet. */
     inline sal_Int16    getCurrentSheetIndex() const { return mnCurrSheet; }
+    /** Returns true when reading a file generated by a known good generator. */
+    inline bool         isGeneratorKnownGood() const { return mbGeneratorKnownGood; }
 
     /** Sets the VBA project storage used to import VBA source code and forms. */
     inline void         setVbaProjectStorage( const StorageRef& rxVbaPrjStrg ) { mxVbaPrjStrg = rxVbaPrjStrg; }
@@ -265,6 +267,7 @@ private:
     StorageRef          mxVbaPrjStrg;           /// Storage containing the VBA project.
     sal_Int16           mnCurrSheet;            /// Current sheet index in Calc document.
     bool                mbWorkbook;             /// True = multi-sheet file.
+    bool                mbGeneratorKnownGood;   /// Whether reading a file generated by Excel or Calc.
 
     // buffers
     FormulaBufferPtr    mxFormulaBuffer;
@@ -524,6 +527,7 @@ void WorkbookGlobals::initialize()
     maPageStyleServ = "com.sun.star.style.PageStyle";
     mnCurrSheet = -1;
     mbWorkbook = true;
+    mbGeneratorKnownGood = false;
     meTextEnc = osl_getThreadTextEncoding();
 
     // the spreadsheet document
@@ -544,13 +548,19 @@ void WorkbookGlobals::initialize()
 
     Reference< XDocumentPropertiesSupplier > xPropSupplier( mxDoc, UNO_QUERY);
     Reference< XDocumentProperties > xDocProps = xPropSupplier->getDocumentProperties();
+    const OUString aGenerator( xDocProps->getGenerator());
 
-    if (xDocProps->getGenerator().startsWithIgnoreAsciiCase("Microsoft"))
+    if (aGenerator.startsWithIgnoreAsciiCase("Microsoft"))
     {
+        mbGeneratorKnownGood = true;
         ScCalcConfig aCalcConfig = mpDoc->GetCalcConfig();
         aCalcConfig.SetStringRefSyntax( formula::FormulaGrammar::CONV_XL_A1 ) ;
         mpDoc->SetCalcConfig(aCalcConfig);
     }
+    else if (aGenerator.startsWithIgnoreAsciiCase("LibreOffice"))
+    {
+        mbGeneratorKnownGood = true;
+    }
 
     mxDocImport.reset(new ScDocumentImport(*mpDoc));
 
@@ -663,6 +673,11 @@ sal_Int16 WorkbookHelper::getCurrentSheetIndex() const
     return mrBookGlob.getCurrentSheetIndex();
 }
 
+bool WorkbookHelper::isGeneratorKnownGood() const
+{
+    return mrBookGlob.isGeneratorKnownGood();
+}
+
 void WorkbookHelper::setVbaProjectStorage( const StorageRef& rxVbaPrjStrg )
 {
     mrBookGlob.setVbaProjectStorage( rxVbaPrjStrg );


More information about the Libreoffice-commits mailing list