sc/qa/unit/data/xlsx/shared-formula/text-results.xlsx |binary sc/qa/unit/subsequent_export-test.cxx | 75 +++++++++++++++++- sc/source/filter/excel/xestream.cxx | 40 ++------- sc/source/filter/inc/formulabuffer.hxx | 15 ++- sc/source/filter/inc/worksheethelper.hxx | 5 - sc/source/filter/oox/formulabuffer.cxx | 44 ++++++++-- sc/source/filter/oox/sheetdatacontext.cxx | 4 sc/source/filter/oox/worksheethelper.cxx | 6 - 8 files changed, 139 insertions(+), 50 deletions(-)
New commits: commit c1dc7576c18cc534e1934459f5fb210091a5b484 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Mar 10 17:25:34 2014 -0400 fdo#74747: Correctly inspect formula result value for xlsx export. Change-Id: I757a8eb371b432970885e2fbd6aea9dd965ab5c0 diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index 290bd6d..6c3aa3b 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -679,45 +679,27 @@ static const char* lcl_GetErrorString( sal_uInt16 nScErrCode ) void XclXmlUtils::GetFormulaTypeAndValue( ScFormulaCell& rCell, const char*& rsType, OUString& rsValue ) { - sal_uInt16 nScErrCode = rCell.GetErrCode(); - if( nScErrCode ) - { - rsType = "e"; - rsValue = ToOUString( lcl_GetErrorString( nScErrCode ) ); + sc::FormulaResultValue aResValue = rCell.GetResult(); - return; - } - - switch( rCell.GetFormatType() ) + switch (aResValue.meType) { - case NUMBERFORMAT_NUMBER: - { - // either value or error code + case sc::FormulaResultValue::Error: + rsType = "e"; + rsValue = ToOUString(lcl_GetErrorString(aResValue.mnError)); + break; + case sc::FormulaResultValue::Value: rsType = "n"; - rsValue = OUString::number( rCell.GetValue() ); - } + rsValue = OUString::number(aResValue.mfValue); break; - - case NUMBERFORMAT_TEXT: - { + case sc::FormulaResultValue::String: rsType = "str"; rsValue = rCell.GetString().getString(); - } - break; - - case NUMBERFORMAT_LOGICAL: - { - rsType = "b"; - rsValue = ToOUString( rCell.GetValue() == 0.0 ? "0" : "1" ); - } break; - + case sc::FormulaResultValue::Invalid: default: - { + // TODO : double-check this to see if this is correct. rsType = "inlineStr"; rsValue = rCell.GetString().getString(); - } - break; } } commit aa5ad7b8096cd15a55c467b1a23d03849aeb870d Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Mar 10 17:03:52 2014 -0400 fdo#74747: Make use of cached string formula results. Just like we do with cached numeric formula results. Change-Id: Ib8b311b540caeb47d8c2162a456f7490c5882ad5 diff --git a/sc/source/filter/inc/formulabuffer.hxx b/sc/source/filter/inc/formulabuffer.hxx index 6be0a25..5fdc248 100644 --- a/sc/source/filter/inc/formulabuffer.hxx +++ b/sc/source/filter/inc/formulabuffer.hxx @@ -77,13 +77,19 @@ public: TokenRangeAddressItem( const TokenAddressItem& rTokenAndAddress, const ::com::sun::star::table::CellRangeAddress& rCellRangeAddress ) : maTokenAndAddress( rTokenAndAddress ), maCellRangeAddress( rCellRangeAddress ) {} }; + struct FormulaValue + { + com::sun::star::table::CellAddress maCellAddress; + OUString maValueStr; + sal_Int32 mnCellType; + }; typedef std::pair<com::sun::star::table::CellAddress, double> ValueAddressPair; struct SheetItem { std::vector<TokenAddressItem>* mpCellFormulas; std::vector<TokenRangeAddressItem>* mpArrayFormulas; - std::vector<ValueAddressPair>* mpCellFormulaValues; + std::vector<FormulaValue>* mpCellFormulaValues; std::vector<SharedFormulaEntry>* mpSharedFormulaEntries; std::vector<SharedFormulaDesc>* mpSharedFormulaIDs; @@ -98,7 +104,7 @@ private: typedef ::std::vector< std::vector<SharedFormulaDesc> > SheetToSharedFormulaid; // sheet -> stuff needed to create shared formulae typedef ::std::vector< std::vector<SharedFormulaEntry> > SheetToFormulaEntryArray; - typedef ::std::vector< std::vector<ValueAddressPair> > FormulaValueArray; + typedef ::std::vector< std::vector<FormulaValue> > FormulaValueArray; osl::Mutex maMtxData; FormulaDataArray maCellFormulas; @@ -118,8 +124,9 @@ public: const ::com::sun::star::table::CellAddress& rAddress, sal_Int32 nSharedId, const OUString& rCellValue, sal_Int32 nValueType ); - void setCellFormulaValue( const ::css::table::CellAddress& rAddress, - double fValue ); + void setCellFormulaValue( + const css::table::CellAddress& rAddress, const OUString& rValueStr, sal_Int32 nCellType ); + void setCellArrayFormula( const ::css::table::CellRangeAddress& rRangeAddress, const ::css::table::CellAddress& rTokenAddress, const OUString& ); diff --git a/sc/source/filter/inc/worksheethelper.hxx b/sc/source/filter/inc/worksheethelper.hxx index 07f3b73..aa0f239 100644 --- a/sc/source/filter/inc/worksheethelper.hxx +++ b/sc/source/filter/inc/worksheethelper.hxx @@ -325,8 +325,9 @@ public: const com::sun::star::table::CellRangeAddress& rRange, sal_Int32 nSharedId, const OUString& rTokens ); - void setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress, - double fValue ); + void setCellFormulaValue( + const css::table::CellAddress& rAddress, const OUString& rValueStr, sal_Int32 nCellType ); + private: WorksheetGlobals& mrSheetGlob; }; diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index ca241a6..e5a2874 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -28,6 +28,7 @@ #include "externalrefmgr.hxx" #include "tokenstringcontext.hxx" #include "oox/token/tokens.hxx" +#include <svl/sharedstringpool.hxx> using namespace com::sun::star; using namespace ::com::sun::star::uno; @@ -256,19 +257,39 @@ void applyArrayFormulas( } void applyCellFormulaValues( - ScDocumentImport& rDoc, const std::vector<FormulaBuffer::ValueAddressPair>& rVector ) + ScDocumentImport& rDoc, const std::vector<FormulaBuffer::FormulaValue>& rVector ) { - std::vector<FormulaBuffer::ValueAddressPair>::const_iterator it = rVector.begin(), itEnd = rVector.end(); + svl::SharedStringPool& rStrPool = rDoc.getDoc().GetSharedStringPool(); + + std::vector<FormulaBuffer::FormulaValue>::const_iterator it = rVector.begin(), itEnd = rVector.end(); for (; it != itEnd; ++it) { ScAddress aCellPos; - ScUnoConversion::FillScAddress(aCellPos, it->first); + ScUnoConversion::FillScAddress(aCellPos, it->maCellAddress); ScFormulaCell* pCell = rDoc.getDoc().GetFormulaCell(aCellPos); - if (pCell) + const OUString& rValueStr = it->maValueStr; + if (!pCell) + continue; + + switch (it->mnCellType) { - pCell->SetHybridDouble(it->second); - pCell->ResetDirty(); - pCell->SetChanged(false); + case XML_n: + { + pCell->SetResultDouble(rValueStr.toDouble()); + pCell->ResetDirty(); + pCell->SetChanged(false); + } + break; + case XML_str: + { + svl::SharedString aSS = rStrPool.intern(rValueStr); + pCell->SetResultToken(new formula::FormulaStringToken(aSS)); + pCell->ResetDirty(); + pCell->SetChanged(false); + } + break; + default: + ; } } } @@ -470,10 +491,15 @@ void FormulaBuffer::setCellArrayFormula( const ::com::sun::star::table::CellRang maCellArrayFormulas[ rRangeAddress.Sheet ].push_back( TokenRangeAddressItem( tokenPair, rRangeAddress ) ); } -void FormulaBuffer::setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress, double fValue ) +void FormulaBuffer::setCellFormulaValue( + const css::table::CellAddress& rAddress, const OUString& rValueStr, sal_Int32 nCellType ) { assert( rAddress.Sheet >= 0 && (size_t)rAddress.Sheet < maCellFormulaValues.size() ); - maCellFormulaValues[ rAddress.Sheet ].push_back( ValueAddressPair( rAddress, fValue ) ); + FormulaValue aVal; + aVal.maCellAddress = rAddress; + aVal.maValueStr = rValueStr; + aVal.mnCellType = nCellType; + maCellFormulaValues[rAddress.Sheet].push_back(aVal); } }} diff --git a/sc/source/filter/oox/sheetdatacontext.cxx b/sc/source/filter/oox/sheetdatacontext.cxx index 43c15bb..9628e78 100644 --- a/sc/source/filter/oox/sheetdatacontext.cxx +++ b/sc/source/filter/oox/sheetdatacontext.cxx @@ -161,8 +161,8 @@ void SheetDataContext::onEndElement() // If a number cell has some preloaded value, stick it into the buffer // but do this only for real cell formulas (not array, shared etc.) - if( !( maCellValue.isEmpty() ) && ( maCellData.mnCellType == XML_n ) ) - setCellFormulaValue( maCellData.maCellAddr, maCellValue.toDouble() ); + if (!maCellValue.isEmpty()) + setCellFormulaValue(maCellData.maCellAddr, maCellValue, maCellData.mnCellType); break; case XML_shared: diff --git a/sc/source/filter/oox/worksheethelper.cxx b/sc/source/filter/oox/worksheethelper.cxx index 32cff08..2dceb6c 100644 --- a/sc/source/filter/oox/worksheethelper.cxx +++ b/sc/source/filter/oox/worksheethelper.cxx @@ -1567,10 +1567,10 @@ void WorksheetHelper::putValue( const CellAddress& rAddress, double fValue ) getDocImport().setNumericCell(aAddress, fValue); } -void WorksheetHelper::setCellFormulaValue( const ::com::sun::star::table::CellAddress& rAddress, - double fValue ) +void WorksheetHelper::setCellFormulaValue( + const css::table::CellAddress& rAddress, const OUString& rValueStr, sal_Int32 nCellType ) { - getFormulaBuffer().setCellFormulaValue( rAddress, fValue ); + getFormulaBuffer().setCellFormulaValue(rAddress, rValueStr, nCellType); } void WorksheetHelper::putString( const CellAddress& rAddress, const OUString& rText ) commit 304e6144c66affd7adcea66f72fb5757eddfb12f Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Mar 10 15:37:46 2014 -0400 fdo#74747: Test cached numeric results too just to be safe. Change-Id: I00c68694859fdb9a2f31f50cb3c63984ed146146 diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index b0011b3..90da87c 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -1232,11 +1232,14 @@ void ScExportTest::testSharedFormulaExportXLSX() ScDocShellRef xDocSh = loadDoc("shared-formula/3d-reference.", XLSX); CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is()); ScDocument* pDoc = xDocSh->GetDocument(); - pDoc->CalcAll(); // Recalculate to flush all cached results. bool bRes = aTest.checkContent(pDoc); CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes); + pDoc->CalcAll(); // Recalculate to flush all cached results. + bRes = aTest.checkContent(pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes); + // Save and reload, and check the content again. ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX); xDocSh->DoClose(); commit c59b3d6c5c8096486730007d9b9b053793b90b1e Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Mon Mar 10 15:32:33 2014 -0400 fdo#74747: Write test for this first. Change-Id: Ia528904405cbb698b9cf08d4a8531c60780e0d9e diff --git a/sc/qa/unit/data/xlsx/shared-formula/text-results.xlsx b/sc/qa/unit/data/xlsx/shared-formula/text-results.xlsx new file mode 100644 index 0000000..3f59bc3 Binary files /dev/null and b/sc/qa/unit/data/xlsx/shared-formula/text-results.xlsx differ diff --git a/sc/qa/unit/subsequent_export-test.cxx b/sc/qa/unit/subsequent_export-test.cxx index 5eb4eca..b0011b3 100644 --- a/sc/qa/unit/subsequent_export-test.cxx +++ b/sc/qa/unit/subsequent_export-test.cxx @@ -89,6 +89,7 @@ public: void testSharedFormulaExportXLS(); void testSharedFormulaExportXLSX(); + void testSharedFormulaStringResultExportXLSX(); CPPUNIT_TEST_SUITE(ScExportTest); CPPUNIT_TEST(test); @@ -115,6 +116,7 @@ public: CPPUNIT_TEST(testCellBordersXLSX); CPPUNIT_TEST(testSharedFormulaExportXLS); CPPUNIT_TEST(testSharedFormulaExportXLSX); + CPPUNIT_TEST(testSharedFormulaStringResultExportXLSX); CPPUNIT_TEST_SUITE_END(); @@ -1249,6 +1251,74 @@ void ScExportTest::testSharedFormulaExportXLSX() xDocSh2->DoClose(); } +void ScExportTest::testSharedFormulaStringResultExportXLSX() +{ + struct + { + bool checkContent( ScDocument* pDoc ) + { + { + // B2:B7 should show A,B,....,F. + const char* expected[] = { "A", "B", "C", "D", "E", "F" }; + for (SCROW i = 0; i <= 5; ++i) + { + ScAddress aPos(1,i+1,0); + OUString aStr = pDoc->GetString(aPos); + OUString aExpected = OUString::createFromAscii(expected[i]); + if (aStr != aExpected) + { + cerr << "Wrong value in B" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl; + return false; + } + } + } + + { + // C2:C7 should show AA,BB,....,FF. + const char* expected[] = { "AA", "BB", "CC", "DD", "EE", "FF" }; + for (SCROW i = 0; i <= 5; ++i) + { + ScAddress aPos(2,i+1,0); + OUString aStr = pDoc->GetString(aPos); + OUString aExpected = OUString::createFromAscii(expected[i]); + if (aStr != aExpected) + { + cerr << "Wrong value in C" << (i+2) << ": expected='" << aExpected << "', actual='" << aStr << "'" << endl; + return false; + } + } + } + + return true; + } + + } aTest; + + ScDocShellRef xDocSh = loadDoc("shared-formula/text-results.", XLSX); + CPPUNIT_ASSERT_MESSAGE("Failed to load file.", xDocSh.Is()); + ScDocument* pDoc = xDocSh->GetDocument(); + + // Check content without re-calculation, to test cached formula results. + bool bRes = aTest.checkContent(pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial document failed.", bRes); + + // Now, re-calculate and check the results. + pDoc->CalcAll(); + bRes = aTest.checkContent(pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the initial recalculated document failed.", bRes); + + // Reload and check again. + ScDocShellRef xDocSh2 = saveAndReload(xDocSh, XLSX); + xDocSh->DoClose(); + CPPUNIT_ASSERT_MESSAGE("Failed to re-load file.", xDocSh2.Is()); + pDoc = xDocSh2->GetDocument(); + + bRes = aTest.checkContent(pDoc); + CPPUNIT_ASSERT_MESSAGE("Content check on the reloaded document failed.", bRes); + + xDocSh2->DoClose(); +} + ScExportTest::ScExportTest() : ScBootstrapFixture("/sc/qa/unit/data") { _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits