diff options
author | Eike Rathke <erack@redhat.com> | 2016-10-15 16:42:42 +0200 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2016-10-27 16:04:24 +0000 |
commit | dac45f154a72e1bb35d7b0540ab5723390c11b30 (patch) | |
tree | eb672fa2a3ec3dd6dfbad7cdeed907e90df38b8b | |
parent | 873929d14aa4013eb3dac216db9b828ff01e8d8f (diff) |
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 <ci@libreoffice.org>
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r-- | sc/source/filter/inc/workbookhelper.hxx | 2 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabuffer.cxx | 43 | ||||
-rw-r--r-- | sc/source/filter/oox/workbookhelper.cxx | 17 |
3 files changed, 47 insertions, 15 deletions
diff --git a/sc/source/filter/inc/workbookhelper.hxx b/sc/source/filter/inc/workbookhelper.hxx index c314bf592939..59c5c56ba50b 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 d7a574e39271..41c99f80062e 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 a12491f299c1..736649d75d25 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 ); |