Rebased ref, commits from common ancestor: commit 8ce57d475d8863c338245760c178de1d54d1c736 Author: Kohei Yoshida <kohei.yosh...@collabora.com> Date: Wed Oct 9 15:44:59 2013 -0400
Import shared formulas from xlsx without crashing. The key here is to only use the shared formula ID's and ignore the ref range. The ref ranges are not correct half the time. Change-Id: If65f9b1b44ab6239db37977b6dfe3f822a9cf67e diff --git a/include/svl/sharedstring.hxx b/include/svl/sharedstring.hxx index 183dc43..a3650a5 100644 --- a/include/svl/sharedstring.hxx +++ b/include/svl/sharedstring.hxx @@ -41,6 +41,8 @@ public: bool isValid() const; bool isEmpty() const; + + sal_Int32 getLength() const; }; } diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 076982c..c378a26 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -2014,7 +2014,7 @@ public: bool HasBroadcaster( SCTAB nTab, SCCOL nCol ) const; #if DEBUG_COLUMN_STORAGE - void DumpFormulaGroups( SCTAB nTab, SCCOL nCol ) const; + SC_DLLPUBLIC void DumpFormulaGroups( SCTAB nTab, SCCOL nCol ) const; #endif private: // CLOOK-Impl-methods diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index ec3d475..f66bd90 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -1527,6 +1527,7 @@ struct FormulaGroupDumper : std::unary_function<sc::CellStoreType::value_type, v if (rNode.type != sc::element_type_formula) return; + cout << " -- formula block" << endl; sc::formula_block::const_iterator it = sc::formula_block::begin(*rNode.data); sc::formula_block::const_iterator itEnd = sc::formula_block::end(*rNode.data); @@ -1534,10 +1535,16 @@ struct FormulaGroupDumper : std::unary_function<sc::CellStoreType::value_type, v { const ScFormulaCell& rCell = **it; if (!rCell.IsShared()) + { + cout << " + row " << rCell.aPos.Row() << " not shared" << endl; continue; + } if (rCell.GetSharedTopRow() != rCell.aPos.Row()) + { + cout << " + row " << rCell.aPos.Row() << " shared with top row " << rCell.GetSharedTopRow() << " with length " << rCell.GetSharedLength() << endl; continue; + } SCROW nLen = rCell.GetSharedLength(); cout << " * group: start=" << rCell.aPos.Row() << ", length=" << nLen << endl; diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index ae84c13..c34fa17 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -2702,7 +2702,6 @@ public: if (eCompState == ScFormulaCell::NotEqual) { // different formula tokens. - pCur->SetCellGroup(mxNone); if (xCurGrp) { // Move to the cell after the last cell of the current group. diff --git a/sc/source/filter/ftools/sharedformulagroups.cxx b/sc/source/filter/ftools/sharedformulagroups.cxx index 77da587..b80bdb5 100644 --- a/sc/source/filter/ftools/sharedformulagroups.cxx +++ b/sc/source/filter/ftools/sharedformulagroups.cxx @@ -31,17 +31,28 @@ size_t SharedFormulaGroups::KeyHash::operator ()( const Key& rKey ) const return static_cast<size_t>(nVal); } +void SharedFormulaGroups::set( size_t nSharedId, ScTokenArray* pArray ) +{ + maStore.insert(nSharedId, pArray); +} + void SharedFormulaGroups::set( size_t nSharedId, SCCOL nCol, const ScFormulaCellGroupRef& xGroup ) { Key aKey(nSharedId, nCol); - maStore.insert(StoreType::value_type(aKey, xGroup)); + maColStore.insert(ColStoreType::value_type(aKey, xGroup)); +} + +const ScTokenArray* SharedFormulaGroups::get( size_t nSharedId ) const +{ + StoreType::const_iterator it = maStore.find(nSharedId); + return it == maStore.end() ? NULL : it->second; } ScFormulaCellGroupRef SharedFormulaGroups::get( size_t nSharedId, SCCOL nCol ) const { Key aKey(nSharedId, nCol); - StoreType::const_iterator it = maStore.find(aKey); - return it == maStore.end() ? ScFormulaCellGroupRef() : it->second; + ColStoreType::const_iterator it = maColStore.find(aKey); + return it == maColStore.end() ? ScFormulaCellGroupRef() : it->second; } } diff --git a/sc/source/filter/inc/sharedformulagroups.hxx b/sc/source/filter/inc/sharedformulagroups.hxx index c6058fc..0bd9484 100644 --- a/sc/source/filter/inc/sharedformulagroups.hxx +++ b/sc/source/filter/inc/sharedformulagroups.hxx @@ -12,7 +12,9 @@ #include "address.hxx" #include "formulacell.hxx" +#include "tokenarray.hxx" +#include <boost/ptr_container/ptr_map.hpp> #include <boost/unordered_map.hpp> namespace sc { @@ -35,11 +37,15 @@ class SharedFormulaGroups size_t operator() ( const Key& rKey ) const; }; - typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType; + typedef boost::ptr_map<size_t, ScTokenArray> StoreType; + typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> ColStoreType; + ColStoreType maColStore; StoreType maStore; public: + void set( size_t nSharedId, ScTokenArray* pArray ); void set( size_t nSharedId, SCCOL nCol, const ScFormulaCellGroupRef& xGroup ); + const ScTokenArray* get( size_t nSharedId ) const; ScFormulaCellGroupRef get( size_t nSharedId, SCCOL nCol ) const; }; diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx index 21e383f..a4e3b7b 100644 --- a/sc/source/filter/oox/formulabuffer.cxx +++ b/sc/source/filter/oox/formulabuffer.cxx @@ -94,7 +94,7 @@ void FormulaBuffer::applyCellFormula( ScDocument& rDoc, const ApiTokenSequence& ScFormulaCell* pNewCell = new ScFormulaCell( &rDoc, aCellPos, &aTokenArray ); pNewCell->StartListeningTo( &rDoc ); rDoc.EnsureTable(aCellPos.Tab()); - rDoc.SetFormulaCell(aCellPos, pNewCell); + rDoc.SetGroupFormulaCell(aCellPos, pNewCell); } void FormulaBuffer::applyCellFormulas( const std::vector< TokenAddressItem >& rVector ) @@ -149,7 +149,6 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab ) for (; it != itEnd; ++it) { const table::CellAddress& rAddr = it->maAddress; - const table::CellRangeAddress& rRange = it->maRange; sal_Int32 nId = it->mnSharedId; const OUString& rTokenStr = it->maTokenStr; @@ -159,18 +158,7 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab ) aComp.SetGrammar(formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX); ScTokenArray* pArray = aComp.CompileString(rTokenStr); if (pArray) - { - for (sal_Int32 nCol = rRange.StartColumn; nCol <= rRange.EndColumn; ++nCol) - { - // Create one group per column, since Calc doesn't support - // shared formulas across multiple columns. - ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup); - xNewGroup->mnStart = rRange.StartRow; - xNewGroup->mnLength = 1; // Length gets updated as we go. - xNewGroup->setCode(*pArray); - aGroups.set(nId, nCol, xNewGroup); - } - } + aGroups.set(nId, pArray); } } @@ -180,18 +168,13 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab ) for (; it != itEnd; ++it) { const table::CellAddress& rAddr = it->maAddress; - - ScFormulaCellGroupRef xGroup = aGroups.get(it->mnSharedId, rAddr.Column); - if (!xGroup) + const ScTokenArray* pArray = aGroups.get(it->mnSharedId); + if (!pArray) continue; ScAddress aPos; ScUnoConversion::FillScAddress(aPos, rAddr); - if (xGroup->mnStart == aPos.Row()) - // Generate code for the top cell only. - xGroup->compileCode(rDoc, aPos, formula::FormulaGrammar::GRAM_DEFAULT); - ScFormulaCell* pCell = new ScFormulaCell(&rDoc, aPos, xGroup); - + ScFormulaCell* pCell = new ScFormulaCell(&rDoc, aPos, pArray); bool bInserted = rDoc.SetGroupFormulaCell(aPos, pCell); if (!bInserted) { @@ -200,9 +183,6 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab ) continue; } - // Update the length of shared formula span as we go. The length - // that Excel gives is not always correct. - xGroup->mnLength = aPos.Row() - xGroup->mnStart + 1; pCell->StartListeningTo(&rDoc); if (it->maCellValue.isEmpty()) diff --git a/svl/source/misc/sharedstring.cxx b/svl/source/misc/sharedstring.cxx index 9c0cad2f..0438421 100644 --- a/svl/source/misc/sharedstring.cxx +++ b/svl/source/misc/sharedstring.cxx @@ -118,6 +118,11 @@ bool SharedString::isEmpty() const return mpData == NULL || mpData->length == 0; } +sal_Int32 SharedString::getLength() const +{ + return mpData ? mpData->length : 0; +} + } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits