diff options
author | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-07 18:46:57 -0400 |
---|---|---|
committer | Kohei Yoshida <kohei.yoshida@gmail.com> | 2013-08-12 19:46:26 -0400 |
commit | c3f631ea5c09072a2e6bbb1f3a71b3a331b62713 (patch) | |
tree | 201ad4ec4476eab50cdf17a707e160ea66cdc6e5 /sc/source | |
parent | 3c4fb3d0741a762fd21cc4e0dad631a81f1057f3 (diff) |
Rework shared formula import in orcus handler.
Change-Id: I3a6ed347565fff7cc984960929c66997e3a18f1e
Diffstat (limited to 'sc/source')
-rw-r--r-- | sc/source/filter/ftools/sharedformulagroups.cxx | 49 | ||||
-rw-r--r-- | sc/source/filter/inc/orcusinterface.hxx | 4 | ||||
-rw-r--r-- | sc/source/filter/inc/sharedformulagroups.hxx | 50 | ||||
-rw-r--r-- | sc/source/filter/oox/formulabuffer.cxx | 58 | ||||
-rw-r--r-- | sc/source/filter/orcus/interface.cxx | 143 |
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( |