summaryrefslogtreecommitdiff
path: root/sc/source
diff options
context:
space:
mode:
authorKohei Yoshida <kohei.yoshida@gmail.com>2013-08-07 18:46:57 -0400
committerKohei Yoshida <kohei.yoshida@gmail.com>2013-08-12 19:46:26 -0400
commitc3f631ea5c09072a2e6bbb1f3a71b3a331b62713 (patch)
tree201ad4ec4476eab50cdf17a707e160ea66cdc6e5 /sc/source
parent3c4fb3d0741a762fd21cc4e0dad631a81f1057f3 (diff)
Rework shared formula import in orcus handler.
Change-Id: I3a6ed347565fff7cc984960929c66997e3a18f1e
Diffstat (limited to 'sc/source')
-rw-r--r--sc/source/filter/ftools/sharedformulagroups.cxx49
-rw-r--r--sc/source/filter/inc/orcusinterface.hxx4
-rw-r--r--sc/source/filter/inc/sharedformulagroups.hxx50
-rw-r--r--sc/source/filter/oox/formulabuffer.cxx58
-rw-r--r--sc/source/filter/orcus/interface.cxx143
5 files changed, 212 insertions, 92 deletions
diff --git a/sc/source/filter/ftools/sharedformulagroups.cxx b/sc/source/filter/ftools/sharedformulagroups.cxx
new file mode 100644
index 000000000000..77da58782697
--- /dev/null
+++ b/sc/source/filter/ftools/sharedformulagroups.cxx
@@ -0,0 +1,49 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include "sharedformulagroups.hxx"
+
+namespace sc {
+
+SharedFormulaGroups::Key::Key(size_t nId, SCCOL nCol) : mnId(nId), mnCol(nCol) {}
+
+bool SharedFormulaGroups::Key::operator== ( const Key& rOther ) const
+{
+ return mnId == rOther.mnId && mnCol == rOther.mnCol;
+}
+
+bool SharedFormulaGroups::Key::operator!= ( const Key& rOther ) const
+{
+ return !operator==(rOther);
+}
+
+size_t SharedFormulaGroups::KeyHash::operator ()( const Key& rKey ) const
+{
+ double nVal = rKey.mnId;
+ nVal *= 256.0;
+ nVal += rKey.mnCol;
+ return static_cast<size_t>(nVal);
+}
+
+void SharedFormulaGroups::set( size_t nSharedId, SCCOL nCol, const ScFormulaCellGroupRef& xGroup )
+{
+ Key aKey(nSharedId, nCol);
+ maStore.insert(StoreType::value_type(aKey, xGroup));
+}
+
+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;
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx
index 6e6f2db94726..75b49f44fbfa 100644
--- a/sc/source/filter/inc/orcusinterface.hxx
+++ b/sc/source/filter/inc/orcusinterface.hxx
@@ -12,6 +12,9 @@
#include "address.hxx"
#include "documentimport.hxx"
+
+#include "sharedformulagroups.hxx"
+
#include "rtl/strbuf.hxx"
#define __ORCUS_STATIC_LIB
@@ -68,6 +71,7 @@ class ScOrcusSheet : public orcus::spreadsheet::iface::import_sheet
ScDocumentImport& mrDoc;
SCTAB mnTab;
ScOrcusFactory& mrFactory;
+ sc::SharedFormulaGroups maFormulaGroups;
typedef std::map<size_t, ScRangeData*> SharedFormulaContainer;
SharedFormulaContainer maSharedFormulas;
diff --git a/sc/source/filter/inc/sharedformulagroups.hxx b/sc/source/filter/inc/sharedformulagroups.hxx
new file mode 100644
index 000000000000..c6058fcfd884
--- /dev/null
+++ b/sc/source/filter/inc/sharedformulagroups.hxx
@@ -0,0 +1,50 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef SC_FILTER_SHAREDFORMULAGROUPS_HXX
+#define SC_FILTER_SHAREDFORMULAGROUPS_HXX
+
+#include "address.hxx"
+#include "formulacell.hxx"
+
+#include <boost/unordered_map.hpp>
+
+namespace sc {
+
+class SharedFormulaGroups
+{
+ struct Key
+ {
+ size_t mnId;
+ SCCOL mnCol;
+
+ Key(size_t nId, SCCOL nCol);
+
+ bool operator== ( const Key& rOther ) const;
+ bool operator!= ( const Key& rOther ) const;
+ };
+
+ struct KeyHash
+ {
+ size_t operator() ( const Key& rKey ) const;
+ };
+
+ typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
+ StoreType maStore;
+public:
+
+ void set( size_t nSharedId, SCCOL nCol, const ScFormulaCellGroupRef& xGroup );
+ ScFormulaCellGroupRef get( size_t nSharedId, SCCOL nCol ) const;
+};
+
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/formulabuffer.cxx b/sc/source/filter/oox/formulabuffer.cxx
index 66d15ea81bd6..59518bc6be36 100644
--- a/sc/source/filter/oox/formulabuffer.cxx
+++ b/sc/source/filter/oox/formulabuffer.cxx
@@ -22,6 +22,7 @@
#include "autonamecache.hxx"
#include "tokenuno.hxx"
#include "tokenarray.hxx"
+#include "sharedformulagroups.hxx"
#include "oox/token/tokens.hxx"
using namespace com::sun::star;
@@ -137,59 +138,6 @@ void FormulaBuffer::applyCellFormulaValues( const std::vector< ValueAddressPair
}
}
-namespace {
-
-class SharedFormulaGroups
-{
- struct Key
- {
- sal_Int32 mnId;
- sal_Int32 mnCol;
-
- Key(sal_Int32 nId, sal_Int32 nCol) : mnId(nId), mnCol(nCol) {}
-
- bool operator== ( const Key& rOther ) const
- {
- return mnId == rOther.mnId && mnCol == rOther.mnCol;
- }
-
- bool operator!= ( const Key& rOther ) const
- {
- return !operator==(rOther);
- }
- };
-
- struct KeyHash
- {
- size_t operator() ( const Key& rKey ) const
- {
- double nVal = rKey.mnId;
- nVal *= 256.0;
- nVal += rKey.mnCol;
- return static_cast<size_t>(nVal);
- }
- };
-
- typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
- StoreType maStore;
-public:
-
- void set( sal_Int32 nSharedId, sal_Int32 nCol, const ScFormulaCellGroupRef& xGroup )
- {
- Key aKey(nSharedId, nCol);
- maStore.insert(StoreType::value_type(aKey, xGroup));
- }
-
- ScFormulaCellGroupRef get( sal_Int32 nSharedId, sal_Int32 nCol ) const
- {
- Key aKey(nSharedId, nCol);
- StoreType::const_iterator it = maStore.find(aKey);
- return it == maStore.end() ? ScFormulaCellGroupRef() : it->second;
- }
-};
-
-}
-
void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
{
SheetToFormulaEntryMap::const_iterator itShared = sharedFormulas.find(nTab);
@@ -207,7 +155,7 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
ScDocument& rDoc = getScDocument();
- SharedFormulaGroups aGroups;
+ sc::SharedFormulaGroups aGroups;
{
// Process shared formulas first.
std::vector<SharedFormulaEntry>::const_iterator it = rSharedFormulas.begin(), itEnd = rSharedFormulas.end();
@@ -231,7 +179,7 @@ void FormulaBuffer::applySharedFormulas( sal_Int32 nTab )
// shared formulas across multiple columns.
ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup);
xNewGroup->mnStart = rRange.StartRow;
- xNewGroup->mnLength = rRange.EndRow - rRange.StartRow;
+ xNewGroup->mnLength = rRange.EndRow - rRange.StartRow + 1;
xNewGroup->setCode(*pArray);
aGroups.set(nId, nCol, xNewGroup);
}
diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx
index a3c1e6d1430b..495715f9644e 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -16,6 +16,7 @@
#include "globalnames.hxx"
#include "docoptio.hxx"
#include "globstr.hrc"
+#include "compiler.hxx"
#include "formula/token.hxx"
#include "tools/datetime.hxx"
@@ -256,7 +257,7 @@ formula::FormulaGrammar::Grammar getCalcGrammarFromOrcus( os::formula_grammar_t
break;
case orcus::spreadsheet::xlsx_2007:
case orcus::spreadsheet::xlsx_2010:
- eGrammar = formula::FormulaGrammar::GRAM_ENGLISH_XL_A1;
+ eGrammar = formula::FormulaGrammar::GRAM_ENGLISH_XL_OOX;
break;
case orcus::spreadsheet::gnumeric:
eGrammar = formula::FormulaGrammar::GRAM_ENGLISH_XL_A1;
@@ -266,6 +267,55 @@ formula::FormulaGrammar::Grammar getCalcGrammarFromOrcus( os::formula_grammar_t
return eGrammar;
}
+class SharedFormulaGroups
+{
+ struct Key
+ {
+ sal_Int32 mnId;
+ sal_Int32 mnCol;
+
+ Key(sal_Int32 nId, sal_Int32 nCol) : mnId(nId), mnCol(nCol) {}
+
+ bool operator== ( const Key& rOther ) const
+ {
+ return mnId == rOther.mnId && mnCol == rOther.mnCol;
+ }
+
+ bool operator!= ( const Key& rOther ) const
+ {
+ return !operator==(rOther);
+ }
+ };
+
+ struct KeyHash
+ {
+ size_t operator() ( const Key& rKey ) const
+ {
+ double nVal = rKey.mnId;
+ nVal *= 256.0;
+ nVal += rKey.mnCol;
+ return static_cast<size_t>(nVal);
+ }
+ };
+
+ typedef boost::unordered_map<Key, ScFormulaCellGroupRef, KeyHash> StoreType;
+ StoreType maStore;
+public:
+
+ void set( sal_Int32 nSharedId, sal_Int32 nCol, const ScFormulaCellGroupRef& xGroup )
+ {
+ Key aKey(nSharedId, nCol);
+ maStore.insert(StoreType::value_type(aKey, xGroup));
+ }
+
+ ScFormulaCellGroupRef get( sal_Int32 nSharedId, sal_Int32 nCol ) const
+ {
+ Key aKey(nSharedId, nCol);
+ StoreType::const_iterator it = maStore.find(aKey);
+ return it == maStore.end() ? ScFormulaCellGroupRef() : it->second;
+ }
+};
+
}
void ScOrcusSheet::set_formula(
@@ -291,57 +341,76 @@ void ScOrcusSheet::set_formula_result(os::row_t row, os::col_t col, const char*
}
void ScOrcusSheet::set_shared_formula(
- os::row_t row, os::col_t col, os::formula_grammar_t grammar, size_t sindex,
- const char* p_formula, size_t n_formula)
+ os::row_t /*row*/, os::col_t /*col*/, os::formula_grammar_t /*grammar*/, size_t /*sindex*/,
+ const char* /*p_formula*/, size_t /*n_formula*/)
{
- OUString aFormula( p_formula, n_formula, RTL_TEXTENCODING_UTF8 );
- formula::FormulaGrammar::Grammar eGrammar = getCalcGrammarFromOrcus( grammar );
- ScRangeName* pRangeName = mrDoc.getDoc().GetRangeName();
-
- OUString aName("shared_");
- aName += OUString::valueOf(sal_Int32(pRangeName->size()));
- ScRangeData* pSharedFormula = new ScRangeData(&mrDoc.getDoc(), aName, aFormula, ScAddress(col, row, mnTab), RT_SHARED, eGrammar);
- if(pRangeName->insert(pSharedFormula))
- {
- maSharedFormulas.insert( std::pair<size_t, ScRangeData*>(sindex, pSharedFormula) );
- ScTokenArray aArr;
- aArr.AddToken( formula::FormulaIndexToken( ocName, pSharedFormula->GetIndex() ) );
- mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aArr);
- cellInserted();
- }
+ // TODO: We need to revise this interface in orcus.
}
void ScOrcusSheet::set_shared_formula(
os::row_t row, os::col_t col, os::formula_grammar_t grammar, size_t sindex,
- const char* p_formula, size_t n_formula, const char* /*p_range*/, size_t /*n_range*/)
-{
- OUString aFormula( p_formula, n_formula, RTL_TEXTENCODING_UTF8 );
- formula::FormulaGrammar::Grammar eGrammar = getCalcGrammarFromOrcus( grammar );
- ScRangeName* pRangeName = mrDoc.getDoc().GetRangeName();
+ const char* p_formula, size_t n_formula, const char* p_range, size_t n_range)
+{
+ ScAddress aPos(col, row, mnTab);
+ OUString aFormula(p_formula, n_formula, RTL_TEXTENCODING_UTF8);
+ OUString aRangeStr(p_range, n_range, RTL_TEXTENCODING_UTF8);
+ formula::FormulaGrammar::Grammar eGram = getCalcGrammarFromOrcus(grammar);
+ formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::extractRefConvention(eGram);
+
+ // Convert the shared formula range.
+ ScRange aRange;
+ sal_uInt16 nRes = aRange.Parse(aRangeStr, &mrDoc.getDoc(), eConv);
+ if (!(nRes & SCA_VALID))
+ // Conversion failed.
+ return;
+
+ // Compile the formula expression into tokens.
+ ScCompiler aComp(&mrDoc.getDoc(), aPos);
+ aComp.SetGrammar(eGram);
+ ScTokenArray* pArray = aComp.CompileString(aFormula);
+ if (!pArray)
+ // Tokenization failed.
+ return;
- OUString aName("shared_");
- aName += OUString::valueOf(sal_Int32(pRangeName->size()));
- ScRangeData* pSharedFormula = new ScRangeData(&mrDoc.getDoc(), aName, aFormula, ScAddress(col, row, mnTab), RT_SHARED, eGrammar);
- if(pRangeName->insert(pSharedFormula))
+ for (sal_Int32 nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol)
{
- maSharedFormulas.insert( std::pair<size_t, ScRangeData*>(sindex, pSharedFormula) );
- ScTokenArray aArr;
- aArr.AddToken( formula::FormulaIndexToken( ocName, pSharedFormula->GetIndex() ) );
- mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aArr);
- cellInserted();
+ // Create one group per column, since Calc doesn't support shared
+ // formulas across multiple columns.
+ ScFormulaCellGroupRef xNewGroup(new ScFormulaCellGroup);
+ xNewGroup->mnStart = aRange.aStart.Row();
+ xNewGroup->mnLength = aRange.aEnd.Row() - aRange.aStart.Row() + 1;
+ xNewGroup->setCode(*pArray);
+ maFormulaGroups.set(sindex, nCol, xNewGroup);
}
+
+ ScFormulaCellGroupRef xGroup = maFormulaGroups.get(sindex, aPos.Col());
+ if (!xGroup)
+ return;
+
+ ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, xGroup);
+ mrDoc.setFormulaCell(aPos, pCell);
+ cellInserted();
+
+ // For now, orcus doesn't support setting cached result. Mark it for re-calculation.
+ pCell->SetDirty(true);
+ pCell->StartListeningTo(&mrDoc.getDoc());
}
void ScOrcusSheet::set_shared_formula(os::row_t row, os::col_t col, size_t sindex)
{
- if(maSharedFormulas.find(sindex) == maSharedFormulas.end())
+ ScAddress aPos(col, row, mnTab);
+
+ ScFormulaCellGroupRef xGroup = maFormulaGroups.get(sindex, aPos.Col());
+ if (!xGroup)
return;
- ScRangeData* pSharedFormula = maSharedFormulas.find(sindex)->second;
- ScTokenArray aArr;
- aArr.AddToken( formula::FormulaIndexToken( ocName, pSharedFormula->GetIndex() ) );
- mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aArr);
+ ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, xGroup);
+ mrDoc.setFormulaCell(aPos, pCell);
cellInserted();
+
+ // For now, orcus doesn't support setting cached result. Mark it for re-calculation.
+ pCell->SetDirty(true);
+ pCell->StartListeningTo(&mrDoc.getDoc());
}
void ScOrcusSheet::set_array_formula(