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