[Libreoffice-commits] core.git: 2 commits - sc/inc sc/source

Kohei Yoshida kohei.yoshida at gmail.com
Mon Dec 18 22:33:51 UTC 2017


 sc/inc/documentimport.hxx               |   10 -
 sc/source/core/data/documentimport.cxx  |   42 +++-
 sc/source/filter/inc/orcusinterface.hxx |   64 +++++-
 sc/source/filter/orcus/interface.cxx    |  319 +++++++++++++++++++++++++-------
 4 files changed, 362 insertions(+), 73 deletions(-)

New commits:
commit 1c7fa9528f7373e6798b597a42abe38f20a306aa
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Wed Dec 13 22:27:03 2017 -0500

    Defer cell value insertion until later.
    
    Because Calc's formula engine expects all named expressions to be
    present at the time of re-calculations, we need to delay insertion
    of cell values until after the named expressions are inserted into
    the document.
    
    Change-Id: I54c7d3dc86b3e2c5c192337b1cebfbdfb901ab1f
    Reviewed-on: https://gerrit.libreoffice.org/46665
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>
    Tested-by: Kohei Yoshida <libreoffice at kohei.us>

diff --git a/sc/inc/documentimport.hxx b/sc/inc/documentimport.hxx
index b4c35e1f99b5..d881da37cf2d 100644
--- a/sc/inc/documentimport.hxx
+++ b/sc/inc/documentimport.hxx
@@ -96,7 +96,15 @@ public:
     void setNumericCell(const ScAddress& rPos, double fVal);
     void setStringCell(const ScAddress& rPos, const OUString& rStr);
     void setEditCell(const ScAddress& rPos, EditTextObject* pEditText);
-    void setFormulaCell(const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar);
+
+    void setFormulaCell(
+        const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
+        const double* pResult = nullptr );
+
+    void setFormulaCell(
+        const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
+        const OUString& rResult );
+
     void setFormulaCell(const ScAddress& rPos, ScTokenArray* pArray);
     void setFormulaCell(const ScAddress& rPos, ScFormulaCell* pCell);
 
diff --git a/sc/source/core/data/documentimport.cxx b/sc/source/core/data/documentimport.cxx
index 183f3e1650af..6208789f416e 100644
--- a/sc/source/core/data/documentimport.cxx
+++ b/sc/source/core/data/documentimport.cxx
@@ -25,9 +25,7 @@
 
 #include <svl/sharedstringpool.hxx>
 #include <svl/languageoptions.hxx>
-
-#include <memory>
-#include <vector>
+#include <o3tl/make_unique.hxx>
 
 namespace {
 
@@ -271,7 +269,35 @@ void ScDocumentImport::setEditCell(const ScAddress& rPos, EditTextObject* pEditT
 }
 
 void ScDocumentImport::setFormulaCell(
-    const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar)
+    const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
+    const double* pResult )
+{
+    ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
+    if (!pTab)
+        return;
+
+    sc::ColumnBlockPosition* pBlockPos = mpImpl->getBlockPosition(rPos.Tab(), rPos.Col());
+
+    if (!pBlockPos)
+        return;
+
+    std::unique_ptr<ScFormulaCell> pFC =
+        o3tl::make_unique<ScFormulaCell>(&mpImpl->mrDoc, rPos, rFormula, eGrammar);
+
+    if (pResult)
+    {
+        // Set cached result to this formula cell.
+        pFC->SetResultDouble(*pResult);
+    }
+
+    sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
+    pBlockPos->miCellPos =
+        rCells.set(pBlockPos->miCellPos, rPos.Row(), pFC.release());
+}
+
+void ScDocumentImport::setFormulaCell(
+    const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
+    const OUString& rResult )
 {
     ScTable* pTab = mpImpl->mrDoc.FetchTable(rPos.Tab());
     if (!pTab)
@@ -282,9 +308,15 @@ void ScDocumentImport::setFormulaCell(
     if (!pBlockPos)
         return;
 
+    std::unique_ptr<ScFormulaCell> pFC =
+        o3tl::make_unique<ScFormulaCell>(&mpImpl->mrDoc, rPos, rFormula, eGrammar);
+
+    // Set cached result to this formula cell.
+    pFC->SetHybridString(mpImpl->mrDoc.GetSharedStringPool().intern(rResult));
+
     sc::CellStoreType& rCells = pTab->aCol[rPos.Col()].maCells;
     pBlockPos->miCellPos =
-        rCells.set(pBlockPos->miCellPos, rPos.Row(), new ScFormulaCell(&mpImpl->mrDoc, rPos, rFormula, eGrammar));
+        rCells.set(pBlockPos->miCellPos, rPos.Row(), pFC.release());
 }
 
 void ScDocumentImport::setFormulaCell(const ScAddress& rPos, ScTokenArray* pArray)
diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx
index 851271f9806a..07c35fa78dfe 100644
--- a/sc/source/filter/inc/orcusinterface.hxx
+++ b/sc/source/filter/inc/orcusinterface.hxx
@@ -273,6 +273,8 @@ public:
     virtual orcus::spreadsheet::range_size_t get_sheet_size() const override;
 
     SCTAB getIndex() const { return mnTab; }
+
+    const sc::SharedFormulaGroups& getSharedFormulaGroups() const;
 };
 
 class ScOrcusStyles : public orcus::spreadsheet::iface::import_styles
@@ -508,28 +510,51 @@ public:
 
 class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory
 {
-    struct StringCellCache
+    struct CellStoreToken
     {
+        enum class Type
+        {
+            Auto,
+            Numeric,
+            String,
+            Formula,
+            FormulaWithResult,
+            SharedFormula,
+            SharedFormulaWithResult,
+            Matrix
+        };
+
         ScAddress maPos;
-        size_t mnIndex;
+        Type meType;
 
-        StringCellCache(const ScAddress& rPos, size_t nIndex);
+        OUString maStr1;
+        OUString maStr2;
+        double mfValue;
+
+        uint32_t mnIndex1;
+        uint32_t mnIndex2;
+        formula::FormulaGrammar::Grammar meGrammar;
+
+        CellStoreToken( const ScAddress& rPos, Type eType );
+        CellStoreToken( const ScAddress& rPos, double fValue );
+        CellStoreToken( const ScAddress& rPos, uint32_t nIndex );
+        CellStoreToken( const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar );
     };
 
     typedef std::unordered_map<OUString, size_t> StringHashType;
-    typedef std::vector<StringCellCache> StringCellCaches;
+    typedef std::vector<CellStoreToken> CellStoreTokensType;
 
     ScDocumentImport maDoc;
 
     std::vector<OUString> maStrings;
     StringHashType maStringHash;
 
-    StringCellCaches maStringCells;
+    CellStoreTokensType maCellStoreTokens;
     ScOrcusGlobalSettings maGlobalSettings;
     ScOrcusRefResolver maRefResolver;
     ScOrcusSharedStrings maSharedStrings;
     ScOrcusNamedExpression maNamedExpressions;
-    std::vector< std::unique_ptr<ScOrcusSheet> > maSheets;
+    std::vector<std::unique_ptr<ScOrcusSheet>> maSheets;
     ScOrcusStyles maStyles;
 
     int mnProgress;
@@ -552,7 +577,19 @@ public:
     size_t appendString(const OUString& rStr);
     size_t addString(const OUString& rStr);
 
-    void pushStringCell(const ScAddress& rPos, size_t nStrIndex);
+    void pushCellStoreAutoToken( const ScAddress& rPos, const OUString& rVal );
+    void pushCellStoreToken( const ScAddress& rPos, uint32_t nStrIndex );
+    void pushCellStoreToken( const ScAddress& rPos, double fValue );
+    void pushCellStoreToken(
+        const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar );
+
+    void pushSharedFormulaToken( const ScAddress& rPos, uint32_t nIndex );
+    void pushMatrixFormulaToken(
+        const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
+        uint32_t nRowRange, uint32_t nColRange );
+
+    void pushFormulaResult( const ScAddress& rPos, double fValue );
+    void pushFormulaResult( const ScAddress& rPos, const OUString& rValue );
 
     void incrementProgress();
 
diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx
index c2fa116d0617..04581dc70d72 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -177,8 +177,27 @@ void ScOrcusNamedExpression::define_name(const char* p_name, size_t n_name, cons
     pNames->insert(pRange, false);
 }
 
-ScOrcusFactory::StringCellCache::StringCellCache(const ScAddress& rPos, size_t nIndex) :
-    maPos(rPos), mnIndex(nIndex) {}
+ScOrcusFactory::CellStoreToken::CellStoreToken( const ScAddress& rPos, Type eType ) :
+    maPos(rPos), meType(eType)
+{
+    rtl::math::setNan(&mfValue);
+}
+
+ScOrcusFactory::CellStoreToken::CellStoreToken( const ScAddress& rPos, double fValue ) :
+    maPos(rPos), meType(Type::Numeric), mfValue(fValue) {}
+
+ScOrcusFactory::CellStoreToken::CellStoreToken( const ScAddress& rPos, uint32_t nIndex ) :
+    maPos(rPos), meType(Type::String), mnIndex1(nIndex)
+{
+    rtl::math::setNan(&mfValue);
+}
+
+ScOrcusFactory::CellStoreToken::CellStoreToken(
+    const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar ) :
+    maPos(rPos), meType(Type::Formula), maStr1(rFormula), meGrammar(eGrammar)
+{
+    rtl::math::setNan(&mfValue);
+}
 
 ScOrcusFactory::ScOrcusFactory(ScDocument& rDoc) :
     maDoc(rDoc),
@@ -281,16 +300,112 @@ orcus::spreadsheet::iface::import_styles* ScOrcusFactory::get_styles()
 
 void ScOrcusFactory::finalize()
 {
+    auto toFormulaCell = [this]( const CellStoreToken& rToken ) -> std::unique_ptr<ScFormulaCell>
+    {
+        const ScOrcusSheet& rSheet = *maSheets.at(rToken.maPos.Tab());
+        const sc::SharedFormulaGroups& rSFG = rSheet.getSharedFormulaGroups();
+        const ScTokenArray* pArray = rSFG.get(rToken.mnIndex1);
+        if (!pArray)
+            return std::unique_ptr<ScFormulaCell>();
+
+        return o3tl::make_unique<ScFormulaCell>(&maDoc.getDoc(), rToken.maPos, *pArray);
+    };
+
     int nCellCount = 0;
-    StringCellCaches::const_iterator it = maStringCells.begin(), itEnd = maStringCells.end();
-    for (; it != itEnd; ++it)
+
+    for (const CellStoreToken& rToken : maCellStoreTokens)
     {
-        if (it->mnIndex >= maStrings.size())
-            // String index out-of-bound!  Something is up.
-            continue;
+        switch (rToken.meType)
+        {
+            case CellStoreToken::Type::Auto:
+            {
+                maDoc.setAutoInput(rToken.maPos, rToken.maStr1);
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::String:
+            {
+                if (rToken.mnIndex1 >= maStrings.size())
+                    // String index out-of-bound!  Something is up.
+                    break;
+
+                maDoc.setStringCell(rToken.maPos, maStrings[rToken.mnIndex1]);
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::Numeric:
+            {
+                maDoc.setNumericCell(rToken.maPos, rToken.mfValue);
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::Formula:
+            {
+                maDoc.setFormulaCell(
+                    rToken.maPos, rToken.maStr1, rToken.meGrammar);
+
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::FormulaWithResult:
+            {
+                if (rtl::math::isFinite(rToken.mfValue))
+                    maDoc.setFormulaCell(rToken.maPos, rToken.maStr1, rToken.meGrammar, &rToken.mfValue);
+                else
+                    maDoc.setFormulaCell(rToken.maPos, rToken.maStr1, rToken.meGrammar, rToken.maStr2);
+
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::SharedFormula:
+            {
+                std::unique_ptr<ScFormulaCell> pCell = toFormulaCell(rToken);
+                if (!pCell)
+                    break;
+
+                maDoc.setFormulaCell(rToken.maPos, pCell.release());
+
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::SharedFormulaWithResult:
+            {
+                std::unique_ptr<ScFormulaCell> pCell = toFormulaCell(rToken);
+                if (!pCell)
+                    break;
+
+                if (rtl::math::isFinite(rToken.mfValue))
+                    pCell->SetResultDouble(rToken.mfValue);
+                else
+                    pCell->SetHybridString(
+                        maDoc.getDoc().GetSharedStringPool().intern(rToken.maStr2));
+
+                maDoc.setFormulaCell(rToken.maPos, pCell.release());
+
+                ++nCellCount;
+                break;
+            }
+            case CellStoreToken::Type::Matrix:
+            {
+                if (!rToken.mnIndex1 || !rToken.mnIndex2)
+                    break;
+
+                ScRange aRange(rToken.maPos);
+                aRange.aEnd.IncCol(rToken.mnIndex1-1);
+                aRange.aEnd.IncRow(rToken.mnIndex2-1);
+
+                ScCompiler aComp(&maDoc.getDoc(), aRange.aStart, rToken.meGrammar);
+                std::unique_ptr<ScTokenArray> pArray(aComp.CompileString(rToken.maStr1));
+                if (!pArray)
+                    break;
+
+                maDoc.setMatrixCells(aRange, *pArray, rToken.meGrammar);
+                break;
+            }
+            default:
+                ;
+        }
 
-        maDoc.setStringCell(it->maPos, maStrings[it->mnIndex]);
-        ++nCellCount;
         if (nCellCount == 100000)
         {
             incrementProgress();
@@ -323,9 +438,96 @@ size_t ScOrcusFactory::addString(const OUString& rStr)
     return appendString(rStr);
 }
 
-void ScOrcusFactory::pushStringCell(const ScAddress& rPos, size_t nStrIndex)
+void ScOrcusFactory::pushCellStoreAutoToken( const ScAddress& rPos, const OUString& rVal )
+{
+    maCellStoreTokens.emplace_back(rPos, CellStoreToken::Type::Auto);
+    maCellStoreTokens.back().maStr1 = rVal;
+}
+
+void ScOrcusFactory::pushCellStoreToken( const ScAddress& rPos, uint32_t nStrIndex )
+{
+    maCellStoreTokens.emplace_back(rPos, nStrIndex);
+}
+
+void ScOrcusFactory::pushCellStoreToken( const ScAddress& rPos, double fValue )
+{
+    maCellStoreTokens.emplace_back(rPos, fValue);
+}
+
+void ScOrcusFactory::pushCellStoreToken(
+    const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar )
 {
-    maStringCells.emplace_back(rPos, nStrIndex);
+    maCellStoreTokens.emplace_back(rPos, rFormula, eGrammar);
+}
+
+void ScOrcusFactory::pushSharedFormulaToken( const ScAddress& rPos, uint32_t nIndex )
+{
+    maCellStoreTokens.emplace_back(rPos, CellStoreToken::Type::SharedFormula);
+    maCellStoreTokens.back().mnIndex1 = nIndex;
+}
+
+void ScOrcusFactory::pushMatrixFormulaToken(
+    const ScAddress& rPos, const OUString& rFormula, formula::FormulaGrammar::Grammar eGrammar,
+    uint32_t nRowRange, uint32_t nColRange )
+{
+    maCellStoreTokens.emplace_back(rPos, CellStoreToken::Type::Matrix);
+    CellStoreToken& rT = maCellStoreTokens.back();
+    rT.maStr1 = rFormula;
+    rT.meGrammar = eGrammar;
+    rT.mnIndex1 = nColRange;
+    rT.mnIndex2 = nRowRange;
+}
+
+void ScOrcusFactory::pushFormulaResult( const ScAddress& rPos, double fValue )
+{
+    // Formula result is expected to be pushed immediately following the
+    // formula token it belongs.
+    if (maCellStoreTokens.empty())
+        return;
+
+    CellStoreToken& rToken = maCellStoreTokens.back();
+    if (rToken.maPos != rPos)
+        return;
+
+    switch (rToken.meType)
+    {
+        case CellStoreToken::Type::Formula:
+            rToken.meType = CellStoreToken::Type::FormulaWithResult;
+            break;
+        case CellStoreToken::Type::SharedFormula:
+            rToken.meType = CellStoreToken::Type::SharedFormulaWithResult;
+            break;
+        default:
+            return;
+    }
+
+    rToken.mfValue = fValue;
+}
+
+void ScOrcusFactory::pushFormulaResult( const ScAddress& rPos, const OUString& rValue )
+{
+    // Formula result is expected to be pushed immediately following the
+    // formula token it belongs.
+    if (maCellStoreTokens.empty())
+        return;
+
+    CellStoreToken& rToken = maCellStoreTokens.back();
+    if (rToken.maPos != rPos)
+        return;
+
+    switch (rToken.meType)
+    {
+        case CellStoreToken::Type::Formula:
+            rToken.meType = CellStoreToken::Type::FormulaWithResult;
+            break;
+        case CellStoreToken::Type::SharedFormula:
+            rToken.meType = CellStoreToken::Type::SharedFormulaWithResult;
+            break;
+        default:
+            return;
+    }
+
+    rToken.maStr2 = rValue;
 }
 
 void ScOrcusFactory::incrementProgress()
@@ -620,30 +822,25 @@ os::iface::import_conditional_format* ScOrcusSheet::get_conditional_format()
 void ScOrcusSheet::set_auto(os::row_t row, os::col_t col, const char* p, size_t n)
 {
     OUString aVal(p, n, RTL_TEXTENCODING_UTF8);
-    mrDoc.setAutoInput(ScAddress(col, row, mnTab), aVal);
+    mrFactory.pushCellStoreAutoToken(ScAddress(col, row, mnTab), aVal);
     cellInserted();
 }
 
 void ScOrcusSheet::set_string(os::row_t row, os::col_t col, size_t sindex)
 {
-    // We need to defer string cells since the shared string pool is not yet
-    // populated at the time this method is called.  Orcus imports string
-    // table after the cells get imported.  We won't need to do this once we
-    // implement true shared strings in Calc core.
-
-    mrFactory.pushStringCell(ScAddress(col, row, mnTab), sindex);
+    mrFactory.pushCellStoreToken(ScAddress(col, row, mnTab), uint32_t(sindex));
     cellInserted();
 }
 
 void ScOrcusSheet::set_value(os::row_t row, os::col_t col, double value)
 {
-    mrDoc.setNumericCell(ScAddress(col, row, mnTab), value);
+    mrFactory.pushCellStoreToken(ScAddress(col, row, mnTab), value);
     cellInserted();
 }
 
 void ScOrcusSheet::set_bool(os::row_t row, os::col_t col, bool value)
 {
-    mrDoc.setNumericCell(ScAddress(col, row, mnTab), value ? 1.0 : 0.0);
+    mrFactory.pushCellStoreToken(ScAddress(col, row, mnTab), value ? 1.0 : 0.0);
     cellInserted();
 }
 
@@ -666,7 +863,7 @@ void ScOrcusSheet::set_date_time(
 
     fTime /= DATE_TIME_FACTOR;
 
-    mrDoc.setNumericCell(ScAddress(col, row, mnTab), nDateDiff + fTime);
+    mrFactory.pushCellStoreToken(ScAddress(col, row, mnTab), nDateDiff + fTime);
     cellInserted();
 }
 
@@ -692,35 +889,20 @@ void ScOrcusSheet::set_formula(
     os::row_t row, os::col_t col, os::formula_grammar_t grammar, const char* p, size_t n)
 {
     OUString aFormula(p, n, RTL_TEXTENCODING_UTF8);
-    formula::FormulaGrammar::Grammar eGrammar = getCalcGrammarFromOrcus( grammar );
-    mrDoc.setFormulaCell(ScAddress(col,row,mnTab), aFormula, eGrammar);
+    mrFactory.pushCellStoreToken(
+        ScAddress(col, row, mnTab), aFormula, getCalcGrammarFromOrcus(grammar));
     cellInserted();
 }
 
 void ScOrcusSheet::set_formula_result(os::row_t row, os::col_t col, const char* p, size_t n)
 {
-    ScFormulaCell* pCell = mrDoc.getDoc().GetFormulaCell(ScAddress(col, row, mnTab));
-    if (!pCell)
-    {
-        SAL_WARN("sc.orcus", "trying to set formula result for non formula "
-                "cell! Col: " << col << ";Row: " << row << ";Tab: " << mnTab);
-        return;
-    }
     OUString aResult( p, n, RTL_TEXTENCODING_UTF8);
-    pCell->SetHybridString(mrDoc.getDoc().GetSharedStringPool().intern(aResult));
+    mrFactory.pushFormulaResult(ScAddress(col, row, mnTab), aResult);
 }
 
-void ScOrcusSheet::set_formula_result(os::row_t row, os::col_t col, double /*val*/)
+void ScOrcusSheet::set_formula_result(os::row_t row, os::col_t col, double val)
 {
-    ScFormulaCell* pCell = mrDoc.getDoc().GetFormulaCell(ScAddress(col, row, mnTab));
-    if (!pCell)
-    {
-        SAL_WARN("sc.orcus", "trying to set formula result for non formula "
-                "cell! Col: " << col << ";Row: " << row << ";Tab: " << mnTab);
-        return;
-    }
-
-    // TODO: FIXME
+    mrFactory.pushFormulaResult(ScAddress(col, row, mnTab), val);
 }
 
 void ScOrcusSheet::set_shared_formula(
@@ -740,12 +922,8 @@ void ScOrcusSheet::set_shared_formula(
 
     maFormulaGroups.set(sindex, pArray);
 
-    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, *pArray);
-    mrDoc.setFormulaCell(aPos, pCell);
+    mrFactory.pushSharedFormulaToken(aPos, sindex);
     cellInserted();
-
-    // For now, orcus doesn't support setting cached result. Mark it for re-calculation.
-    pCell->SetDirty();
 }
 
 void ScOrcusSheet::set_shared_formula(
@@ -763,29 +941,19 @@ void ScOrcusSheet::set_shared_formula(os::row_t row, os::col_t col, size_t sinde
     if (!pArray)
         return;
 
-    ScFormulaCell* pCell = new ScFormulaCell(&mrDoc.getDoc(), aPos, *pArray);
-    mrDoc.setFormulaCell(aPos, pCell);
+    mrFactory.pushSharedFormulaToken(aPos, sindex);
     cellInserted();
-
-    // For now, orcus doesn't support setting cached result. Mark it for re-calculation.
-    pCell->SetDirty();
 }
 
 void ScOrcusSheet::set_array_formula(
     os::row_t row, os::col_t col, os::formula_grammar_t grammar,
     const char* p, size_t n, os::row_t array_rows, os::col_t array_cols)
 {
-    formula::FormulaGrammar::Grammar eGrammar = getCalcGrammarFromOrcus( grammar );
     OUString aFormula(p, n, RTL_TEXTENCODING_UTF8);
+    formula::FormulaGrammar::Grammar eGrammar = getCalcGrammarFromOrcus(grammar);
 
-    ScRange aRange(col, row, mnTab, col+array_cols, row + array_rows, mnTab);
-
-    ScCompiler aComp(&mrDoc.getDoc(), aRange.aStart, eGrammar);
-    std::unique_ptr<ScTokenArray> pArray(aComp.CompileString(aFormula));
-    if (!pArray)
-        return;
-
-    mrDoc.setMatrixCells(aRange, *pArray, eGrammar);
+    ScAddress aPos(col, row, mnTab);
+    mrFactory.pushMatrixFormulaToken(aPos, aFormula, eGrammar, array_rows, array_cols);
 }
 
 void ScOrcusSheet::set_array_formula(
@@ -803,6 +971,11 @@ orcus::spreadsheet::range_size_t ScOrcusSheet::get_sheet_size() const
     return ret;
 }
 
+const sc::SharedFormulaGroups& ScOrcusSheet::getSharedFormulaGroups() const
+{
+    return maFormulaGroups;
+}
+
 ScOrcusSharedStrings::ScOrcusSharedStrings(ScOrcusFactory& rFactory) :
     mrFactory(rFactory) {}
 
commit a72f3d40def7878ae487c8c34cd84da7d90fc99a
Author: Kohei Yoshida <kohei.yoshida at gmail.com>
Date:   Mon Dec 11 21:53:55 2017 -0500

    Pick up global named expressions.
    
    Formulas with named expressions don't work yet since they get
    imported before the named expressions do.  We need to insert formula
    cells after the named expressions.
    
    Change-Id: Id2d7c59194ce7c07a3580cc8d9afd9fdda660b24
    Reviewed-on: https://gerrit.libreoffice.org/46664
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>
    Tested-by: Kohei Yoshida <libreoffice at kohei.us>

diff --git a/sc/source/filter/inc/orcusinterface.hxx b/sc/source/filter/inc/orcusinterface.hxx
index e502d49296b1..851271f9806a 100644
--- a/sc/source/filter/inc/orcusinterface.hxx
+++ b/sc/source/filter/inc/orcusinterface.hxx
@@ -75,6 +75,17 @@ public:
     orcus::spreadsheet::range_t resolve_range(const char* p, size_t n) override;
 };
 
+class ScOrcusNamedExpression : public orcus::spreadsheet::iface::import_named_expression
+{
+    ScDocumentImport& mrDoc;
+    const ScOrcusGlobalSettings& mrGlobalSettings;
+
+public:
+    ScOrcusNamedExpression( ScDocumentImport& rDoc, const ScOrcusGlobalSettings& rGS );
+
+    virtual void define_name(const char* p_name, size_t n_name, const char* p_exp, size_t n_exp) override;
+};
+
 class ScOrcusSharedStrings : public orcus::spreadsheet::iface::import_shared_strings
 {
     ScOrcusFactory& mrFactory;
@@ -517,6 +528,7 @@ class ScOrcusFactory : public orcus::spreadsheet::iface::import_factory
     ScOrcusGlobalSettings maGlobalSettings;
     ScOrcusRefResolver maRefResolver;
     ScOrcusSharedStrings maSharedStrings;
+    ScOrcusNamedExpression maNamedExpressions;
     std::vector< std::unique_ptr<ScOrcusSheet> > maSheets;
     ScOrcusStyles maStyles;
 
@@ -533,6 +545,7 @@ public:
     virtual orcus::spreadsheet::iface::import_sheet* get_sheet(orcus::spreadsheet::sheet_t sheet_index) override;
     virtual orcus::spreadsheet::iface::import_global_settings* get_global_settings() override;
     virtual orcus::spreadsheet::iface::import_shared_strings* get_shared_strings() override;
+    virtual orcus::spreadsheet::iface::import_named_expression* get_named_expression() override;
     virtual orcus::spreadsheet::iface::import_styles* get_styles() override;
     virtual void finalize() override;
 
diff --git a/sc/source/filter/orcus/interface.cxx b/sc/source/filter/orcus/interface.cxx
index e8c216308941..c2fa116d0617 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -157,6 +157,26 @@ os::range_t ScOrcusRefResolver::resolve_range(const char* p, size_t n)
     return ret;
 }
 
+ScOrcusNamedExpression::ScOrcusNamedExpression(
+    ScDocumentImport& rDoc, const ScOrcusGlobalSettings& rGS ) :
+    mrDoc(rDoc), mrGlobalSettings(rGS) {}
+
+void ScOrcusNamedExpression::define_name(const char* p_name, size_t n_name, const char* p_exp, size_t n_exp)
+{
+    OUString aName(p_name, n_name, RTL_TEXTENCODING_UTF8);
+    OUString aExpr(p_exp, n_exp, RTL_TEXTENCODING_UTF8);
+
+    ScRangeName* pNames = mrDoc.getDoc().GetRangeName();
+    if (!pNames)
+        return;
+
+    ScRangeData* pRange = new ScRangeData(
+        &mrDoc.getDoc(), aName, aExpr, ScAddress(), ScRangeData::Type::Name,
+        mrGlobalSettings.getCalcGrammar());
+
+    pNames->insert(pRange, false);
+}
+
 ScOrcusFactory::StringCellCache::StringCellCache(const ScAddress& rPos, size_t nIndex) :
     maPos(rPos), mnIndex(nIndex) {}
 
@@ -165,6 +185,7 @@ ScOrcusFactory::ScOrcusFactory(ScDocument& rDoc) :
     maGlobalSettings(maDoc),
     maRefResolver(maGlobalSettings),
     maSharedStrings(*this),
+    maNamedExpressions(maDoc, maGlobalSettings),
     maStyles(rDoc),
     mnProgress(0) {}
 
@@ -248,6 +269,11 @@ orcus::spreadsheet::iface::import_shared_strings* ScOrcusFactory::get_shared_str
     return &maSharedStrings;
 }
 
+orcus::spreadsheet::iface::import_named_expression* ScOrcusFactory::get_named_expression()
+{
+    return &maNamedExpressions;
+}
+
 orcus::spreadsheet::iface::import_styles* ScOrcusFactory::get_styles()
 {
     return &maStyles;


More information about the Libreoffice-commits mailing list