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/filter/orcus | |
parent | 3c4fb3d0741a762fd21cc4e0dad631a81f1057f3 (diff) |
Rework shared formula import in orcus handler.
Change-Id: I3a6ed347565fff7cc984960929c66997e3a18f1e
Diffstat (limited to 'sc/source/filter/orcus')
-rw-r--r-- | sc/source/filter/orcus/interface.cxx | 143 |
1 files changed, 106 insertions, 37 deletions
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( |