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

New commits:
commit dac45f154a72e1bb35d7b0540ab5723390c11b30
Author: Eike Rathke <er...@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.
    
    (cherry picked from commit 2a45b26c619d1125419819d501a7653cf8d6e5ca)
    
    Backport.
    Also added to WorkerThread.
    
     Conflicts:
        sc/source/filter/oox/formulabuffer.cxx
    
    Change-Id: Ib89ba70fd7c3c515439498882fef90ca7c6e278d
    Reviewed-on: https://gerrit.libreoffice.org/29903
    Tested-by: Jenkins <c...@libreoffice.org>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    Tested-by: Caolán McNamara <caol...@redhat.com>

diff --git a/sc/source/filter/inc/workbookhelper.hxx 
b/sc/source/filter/inc/workbookhelper.hxx
index c314bf5..59c5c56 100644
--- a/sc/source/filter/inc/workbookhelper.hxx
+++ b/sc/source/filter/inc/workbookhelper.hxx
@@ -136,6 +136,8 @@ public:
     bool                isWorkbookFile() 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 d7a574e..41c99f8 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);
 }
 
 class WorkerThread: public salhelper::Thread
@@ -317,6 +328,7 @@ class WorkerThread: public salhelper::Thread
     FormulaBuffer::SheetItem& mrItem;
     std::unique_ptr<SvNumberFormatter> mpFormatter;
     const uno::Sequence<sheet::ExternalLinkInfo>& mrExternalLinks;
+    bool mbGeneratorKnownGood;
 
 public:
     WorkerThread(const WorkerThread&) = delete;
@@ -324,16 +336,17 @@ public:
 
     WorkerThread(
         ScDocumentImport& rDoc, FormulaBuffer::SheetItem& rItem, 
SvNumberFormatter* pFormatter,
-        const uno::Sequence<sheet::ExternalLinkInfo>& rExternalLinks ) :
+        const uno::Sequence<sheet::ExternalLinkInfo>& rExternalLinks, bool 
bGeneratorKnownGood ) :
         salhelper::Thread("xlsx-import-formula-buffer-worker-thread"),
-        mrDoc(rDoc), mrItem(rItem), mpFormatter(pFormatter), 
mrExternalLinks(rExternalLinks) {}
+        mrDoc(rDoc), mrItem(rItem), mpFormatter(pFormatter), 
mrExternalLinks(rExternalLinks),
+        mbGeneratorKnownGood(bGeneratorKnownGood) {}
 
     virtual ~WorkerThread() {}
 
 protected:
     virtual void execute() override
     {
-        processSheetFormulaCells(mrDoc, mrItem, *mpFormatter, mrExternalLinks);
+        processSheetFormulaCells(mrDoc, mrItem, *mpFormatter, mrExternalLinks, 
mbGeneratorKnownGood);
     }
 };
 
@@ -401,7 +414,8 @@ void FormulaBuffer::finalizeImport()
     if (nThreadCount == 1)
     {
         for (; it != itEnd; ++it)
-            processSheetFormulaCells(rDoc, *it, 
*rDoc.getDoc().GetFormatTable(), getExternalLinks().getLinkInfos());
+            processSheetFormulaCells(rDoc, *it, 
*rDoc.getDoc().GetFormatTable(), getExternalLinks().getLinkInfos(),
+                    isGeneratorKnownGood());
     }
     else
     {
@@ -419,7 +433,8 @@ void FormulaBuffer::finalizeImport()
                 if (it == itEnd)
                     break;
 
-                WorkerThreadRef xThread(new WorkerThread(rDoc, *it, 
rDoc.getDoc().CreateFormatTable(), getExternalLinks().getLinkInfos()));
+                WorkerThreadRef xThread(new WorkerThread(rDoc, *it, 
rDoc.getDoc().CreateFormatTable(),
+                            getExternalLinks().getLinkInfos(), 
isGeneratorKnownGood()));
                 ++it;
                 aThreads.push_back(xThread);
                 xThread->launch();
diff --git a/sc/source/filter/oox/workbookhelper.cxx 
b/sc/source/filter/oox/workbookhelper.cxx
index a12491f..736649d 100644
--- a/sc/source/filter/oox/workbookhelper.cxx
+++ b/sc/source/filter/oox/workbookhelper.cxx
@@ -138,6 +138,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; }
@@ -277,6 +279,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;
@@ -541,6 +544,7 @@ void WorkbookGlobals::initialize()
     maPageStyleServ = "com.sun.star.style.PageStyle";
     mnCurrSheet = -1;
     mbWorkbook = true;
+    mbGeneratorKnownGood = false;
     meTextEnc = osl_getThreadTextEncoding();
     mbHasCodePage = false;
 
@@ -562,13 +566,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));
 
@@ -704,6 +714,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 );
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to