summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@collabora.com>2013-10-09 15:44:59 -0400
committerKohei Yoshida <kohei.yoshida@collabora.com>2013-10-11 12:14:24 -0400
commit0eabc71b59b97e51b8ee9630873dc8db3401f8f3 (patch)
tree7fef70b9262d91b306d91140081c9f6bf39a4a4f /sc
parent2f39c27be2bd66f149e0a4efdd7fa37daee43fb1 (diff)
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
Diffstat (limited to 'sc')
-rw-r--r--sc/inc/document.hxx2
-rw-r--r--sc/source/core/data/column2.cxx7
-rw-r--r--sc/source/core/data/column3.cxx1
-rw-r--r--sc/source/filter/ftools/sharedformulagroups.cxx17
-rw-r--r--sc/source/filter/inc/sharedformulagroups.hxx8
-rw-r--r--sc/source/filter/oox/formulabuffer.cxx30
6 files changed, 34 insertions, 31 deletions
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 076982c27e26..c378a26ce453 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 ec3d475149ad..f66bd9041baf 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 ae84c131cd77..c34fa1702e68 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 77da58782697..b80bdb50eb87 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 c6058fcfd884..0bd948427cef 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 21e383fe97b7..a4e3b7be9b6c 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())