[Libreoffice-commits] core.git: Branch 'distro/collabora/cp-5.3' - sc/inc sc/Library_sc.mk sc/source

Kohei Yoshida kohei.yoshida at collabora.com
Wed May 24 21:04:29 UTC 2017


 sc/Library_sc.mk                       |    1 
 sc/inc/cellvalue.hxx                   |   33 ++++++++++++++++++-----
 sc/inc/column.hxx                      |    5 +++
 sc/inc/columniterator.hxx              |   29 ++++++++++++++++++++
 sc/inc/document.hxx                    |   13 +++++++++
 sc/inc/formulacell.hxx                 |   10 +++++++
 sc/inc/mtvcellfunc.hxx                 |   12 ++++++++
 sc/inc/table.hxx                       |    5 +++
 sc/source/core/data/cellvalue.cxx      |   46 +++++++++++++++++++++++++++++++++
 sc/source/core/data/column4.cxx        |   26 ++++++++++++++++++
 sc/source/core/data/columniterator.cxx |   37 ++++++++++++++++++++++++++
 sc/source/core/data/document10.cxx     |   23 ++++++++++++++++
 sc/source/core/data/dpcache.cxx        |   46 +++++++++++++++++++++------------
 sc/source/core/data/formulacell.cxx    |   14 ++++++++--
 sc/source/core/data/mtvcellfunc.cxx    |   31 ++++++++++++++++++++++
 sc/source/core/data/table7.cxx         |   18 ++++++++++++
 16 files changed, 324 insertions(+), 25 deletions(-)

New commits:
commit be5429112c8ed1a4ecd8b032aa85f14e3625e7e9
Author: Kohei Yoshida <kohei.yoshida at collabora.com>
Date:   Mon May 22 21:08:56 2017 -0400

    tdf#107945: properly iterate over mtv during pivot cache loading.
    
    This reduces the total time required for populating the pivot cache
    by ~60%.
    
    Reviewed-on: https://gerrit.libreoffice.org/37971
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Kohei Yoshida <libreoffice at kohei.us>
    (cherry picked from commit d4cd8677889ec3807c194ef5b462f8e031807e5b)
    
     Conflicts:
            sc/inc/document.hxx
            sc/source/core/data/formulacell.cxx
    
    Change-Id: I6a8511959c20231a8a5dbd0b0a9a3d0930a1fa0c

diff --git a/sc/Library_sc.mk b/sc/Library_sc.mk
index 3714c966a62e..329fe87840b8 100644
--- a/sc/Library_sc.mk
+++ b/sc/Library_sc.mk
@@ -167,6 +167,7 @@ $(eval $(call gb_Library_add_exception_objects,sc,\
     sc/source/core/data/markarr \
     sc/source/core/data/markdata \
     sc/source/core/data/markmulti \
+    sc/source/core/data/mtvcellfunc \
     sc/source/core/data/mtvelements \
     sc/source/core/data/olinetab \
     sc/source/core/data/pagepar \
diff --git a/sc/inc/cellvalue.hxx b/sc/inc/cellvalue.hxx
index 4ebd29889fee..430212245870 100644
--- a/sc/inc/cellvalue.hxx
+++ b/sc/inc/cellvalue.hxx
@@ -132,19 +132,38 @@ struct SC_DLLPUBLIC ScRefCellValue
 
     bool hasNumeric() const;
 
+    bool hasError() const;
+
     double getValue();
 
-    /** Retrieve string value.
+    /**
+     * Retrieve a numeric value without modifying the states of any objects in
+     * the referenced document store.
+     */
+    double getRawValue() const;
 
-        @param  pDoc
-                Needed to resolve EditCells' field contents, obtain a
-                ScFieldEditEngine from that document. May be NULL if there is
-                no ScDocument in the calling context but then the document
-                specific fields can not be resolved. See
-                ScEditUtil::GetString().
+    /**
+     *  Retrieve string value.
+     *
+     *  Note that this method is NOT thread-safe.
+     *
+     *  @param  pDoc
+     *          Needed to resolve EditCells' field contents, obtain a
+     *          ScFieldEditEngine from that document. May be NULL if there is
+     *          no ScDocument in the calling context but then the document
+     *          specific fields can not be resolved. See
+     *          ScEditUtil::GetString().
      */
     OUString getString( const ScDocument* pDoc );
 
+    /**
+     * Retrieve a string value without modifying the states of any objects in
+     * the referenced document store.
+     *
+     * This method is thread-safe.
+     */
+    OUString getRawString( const ScDocument* pDoc ) const;
+
     bool isEmpty() const;
 
     bool hasEmptyValue();
diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx
index 143610767117..f0a30d82e568 100644
--- a/sc/inc/column.hxx
+++ b/sc/inc/column.hxx
@@ -67,6 +67,7 @@ class CompileFormulaContext;
 struct SetFormulaDirtyContext;
 class RefMovedHint;
 enum class MatrixEdge;
+class ColumnIterator;
 
 }
 
@@ -666,6 +667,10 @@ public:
     void SwapNonEmpty(
         sc::TableValues& rValues, sc::StartListeningContext& rStartCxt, sc::EndListeningContext& rEndCxt );
 
+    std::unique_ptr<sc::ColumnIterator> GetColumnIterator( SCROW nRow1, SCROW nRow2 ) const;
+
+    void EnsureFormulaCellResults( SCROW nRow1, SCROW nRow2 );
+
 #if DUMP_COLUMN_STORAGE
     void DumpColumnStorage() const;
 #endif
diff --git a/sc/inc/columniterator.hxx b/sc/inc/columniterator.hxx
index 4e8c951be750..e4906204c9b4 100644
--- a/sc/inc/columniterator.hxx
+++ b/sc/inc/columniterator.hxx
@@ -50,6 +50,35 @@ private:
     void checkEndRow();
 };
 
+namespace sc {
+
+/**
+ * This iterator lets you iterate over cells over specified range in a
+ * single column.  It does not modify the state of the cells, and therefore
+ * is thread safe.
+ */
+class ColumnIterator
+{
+    CellStoreType::const_position_type maPos;
+    CellStoreType::const_position_type maPosEnd;
+
+public:
+    ColumnIterator( const CellStoreType& rCells, SCROW nRow1, SCROW nRow2 );
+    ~ColumnIterator();
+
+    void next();
+
+    SCROW getRow() const;
+
+    bool hasCell() const;
+
+    mdds::mtv::element_t getType() const;
+
+    ScRefCellValue getCell() const;
+};
+
+}
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index bd9313346ecc..6db9ab6d616e 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -83,6 +83,7 @@ struct ReorderParam;
 class FormulaGroupAreaListener;
 class ColumnSet;
 class UpdatedRangeNames;
+class ColumnIterator;
 
 }
 
@@ -2291,6 +2292,18 @@ public:
     const SvtBroadcaster* GetBroadcaster( const ScAddress& rPos ) const;
     void DeleteBroadcasters( sc::ColumnBlockPosition& rBlockPos, const ScAddress& rTopPos, SCROW nLength );
 
+    /**
+     * Make sure all of the formula cells in the specified range have been
+     * fully calculated.  This method only re-calculates those formula cells
+     * that have been flagged dirty.
+     *
+     * @param rRange range in which to potentially calculate the formula
+     *               cells.
+     */
+    void EnsureFormulaCellResults( const ScRange& rRange );
+
+    std::unique_ptr<sc::ColumnIterator> GetColumnIterator( SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const;
+
 #if DUMP_COLUMN_STORAGE
     SC_DLLPUBLIC void DumpColumnStorage( SCTAB nTab, SCCOL nCol ) const;
 #endif
diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx
index 71812a2aab15..ad21cc21d7f4 100644
--- a/sc/inc/formulacell.hxx
+++ b/sc/inc/formulacell.hxx
@@ -298,6 +298,16 @@ public:
     bool            IsValueNoError() const;
     double          GetValue();
     svl::SharedString GetString();
+
+    /**
+     * Get a numeric value without potentially triggering re-calculation.
+     */
+    double GetRawValue() const;
+
+    /**
+     * Get a string value without potentially triggering re-calculation.
+     */
+    svl::SharedString GetRawString() const;
     const ScMatrix* GetMatrix();
     bool            GetMatrixOrigin( ScAddress& rPos ) const;
     void            GetResultDimensions( SCSIZE& rCols, SCSIZE& rRows );
diff --git a/sc/inc/mtvcellfunc.hxx b/sc/inc/mtvcellfunc.hxx
index db72fd4a3278..195e6449007a 100644
--- a/sc/inc/mtvcellfunc.hxx
+++ b/sc/inc/mtvcellfunc.hxx
@@ -13,6 +13,10 @@
 #include "mtvelements.hxx"
 #include "mtvfunctions.hxx"
 
+#include <functional>
+
+class ScFormulaCell;
+
 namespace sc {
 
 template<typename Func>
@@ -32,6 +36,14 @@ ProcessFormula(
         CellStoreType, formula_block, FuncElem, FuncElseNoOp<size_t> >(it, rStore, nRow1, nRow2, rFuncElem, aElse);
 }
 
+/**
+ * Process formula cells found within specified row range. This function
+ * allows modifications of the states of the formula function objects.
+ */
+CellStoreType::iterator ProcessFormula(
+    const CellStoreType::iterator& it, CellStoreType& rStore, SCROW nRow1, SCROW nRow2,
+    std::function<void(size_t,ScFormulaCell*)> aFuncElem );
+
 template<typename FuncElem, typename FuncElse>
 typename CellStoreType::iterator
 ProcessFormula(
diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx
index 9b2219eda8c2..81e8329b4b88 100644
--- a/sc/inc/table.hxx
+++ b/sc/inc/table.hxx
@@ -77,6 +77,7 @@ class CompileFormulaContext;
 struct SetFormulaDirtyContext;
 class RefMovedHint;
 struct ReorderParam;
+class ColumnIterator;
 
 }
 
@@ -962,6 +963,10 @@ public:
     void TransferCellValuesTo( SCCOL nCol, SCROW nRow, size_t nLen, sc::CellValues& rDest );
     void CopyCellValuesFrom( SCCOL nCol, SCROW nRow, const sc::CellValues& rSrc );
 
+    std::unique_ptr<sc::ColumnIterator> GetColumnIterator( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const;
+
+    void EnsureFormulaCellResults( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 );
+
     void ConvertFormulaToValue(
         sc::EndListeningContext& rCxt, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
         sc::TableValues* pUndo );
diff --git a/sc/source/core/data/cellvalue.cxx b/sc/source/core/data/cellvalue.cxx
index efe66f789596..75b7c5bbb12f 100644
--- a/sc/source/core/data/cellvalue.cxx
+++ b/sc/source/core/data/cellvalue.cxx
@@ -17,6 +17,7 @@
 #include "editutil.hxx"
 #include "tokenarray.hxx"
 #include <formula/token.hxx>
+#include <formula/errorcodes.hxx>
 #include <svl/sharedstring.hxx>
 
 namespace {
@@ -178,6 +179,27 @@ OUString getStringImpl( const CellT& rCell, const ScDocument* pDoc )
     return EMPTY_OUSTRING;
 }
 
+template<typename CellT>
+OUString getRawStringImpl( const CellT& rCell, const ScDocument* pDoc )
+{
+    switch (rCell.meType)
+    {
+        case CELLTYPE_VALUE:
+            return OUString::number(rCell.mfValue);
+        case CELLTYPE_STRING:
+            return rCell.mpString->getString();
+        case CELLTYPE_EDIT:
+            if (rCell.mpEditText)
+                return ScEditUtil::GetString(*rCell.mpEditText, pDoc);
+        break;
+        case CELLTYPE_FORMULA:
+            return rCell.mpFormula->GetRawString().getString();
+        default:
+            ;
+    }
+    return EMPTY_OUSTRING;
+}
+
 }
 
 ScCellValue::ScCellValue() : meType(CELLTYPE_NONE), mfValue(0.0) {}
@@ -544,6 +566,11 @@ bool ScRefCellValue::hasNumeric() const
     return hasNumericImpl(meType, mpFormula);
 }
 
+bool ScRefCellValue::hasError() const
+{
+    return meType == CELLTYPE_FORMULA && mpFormula->GetErrCode() != FormulaError::NONE;
+}
+
 double ScRefCellValue::getValue()
 {
     switch (meType)
@@ -558,11 +585,30 @@ double ScRefCellValue::getValue()
     return 0.0;
 }
 
+double ScRefCellValue::getRawValue() const
+{
+    switch (meType)
+    {
+        case CELLTYPE_VALUE:
+            return mfValue;
+        case CELLTYPE_FORMULA:
+            return mpFormula->GetRawValue();
+        default:
+            ;
+    }
+    return 0.0;
+}
+
 OUString ScRefCellValue::getString( const ScDocument* pDoc )
 {
     return getStringImpl(*this, pDoc);
 }
 
+OUString ScRefCellValue::getRawString( const ScDocument* pDoc ) const
+{
+    return getRawStringImpl(*this, pDoc);
+}
+
 bool ScRefCellValue::isEmpty() const
 {
     return meType == CELLTYPE_NONE;
diff --git a/sc/source/core/data/column4.cxx b/sc/source/core/data/column4.cxx
index 69d95f96fa64..a50092c0ea9b 100644
--- a/sc/source/core/data/column4.cxx
+++ b/sc/source/core/data/column4.cxx
@@ -14,6 +14,7 @@
 #include <document.hxx>
 #include <cellvalues.hxx>
 #include <columnspanset.hxx>
+#include <columniterator.hxx>
 #include <listenercontext.hxx>
 #include <tokenstringcontext.hxx>
 #include <mtvcellfunc.hxx>
@@ -30,6 +31,7 @@
 #include <sharedformula.hxx>
 
 #include <svl/sharedstringpool.hxx>
+#include <o3tl/make_unique.hxx>
 
 #include <vector>
 #include <cassert>
@@ -1574,4 +1576,28 @@ void ScColumn::SetNeedsListeningGroup( SCROW nRow )
         (*pp)->SetNeedsListening(true);
 }
 
+std::unique_ptr<sc::ColumnIterator> ScColumn::GetColumnIterator( SCROW nRow1, SCROW nRow2 ) const
+{
+    if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
+        return std::unique_ptr<sc::ColumnIterator>();
+
+    return o3tl::make_unique<sc::ColumnIterator>(maCells, nRow1, nRow2);
+}
+
+void ScColumn::EnsureFormulaCellResults( SCROW nRow1, SCROW nRow2 )
+{
+    if (!ValidRow(nRow1) || !ValidRow(nRow2) || nRow1 > nRow2)
+        return;
+
+    if (!HasFormulaCell(nRow1, nRow2))
+        return;
+
+    sc::ProcessFormula(maCells.begin(), maCells, nRow1, nRow2,
+        []( size_t /*nRow*/, ScFormulaCell* pCell )
+        {
+            pCell->MaybeInterpret();
+        }
+    );
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/columniterator.cxx b/sc/source/core/data/columniterator.cxx
index 4e363f8f319e..10f87459f91e 100644
--- a/sc/source/core/data/columniterator.cxx
+++ b/sc/source/core/data/columniterator.cxx
@@ -168,4 +168,41 @@ void ScColumnTextWidthIterator::checkEndRow()
     miBlockCur = miBlockEnd;
 }
 
+namespace sc {
+
+ColumnIterator::ColumnIterator( const CellStoreType& rCells, SCROW nRow1, SCROW nRow2 ) :
+    maPos(rCells.position(nRow1)),
+    maPosEnd(rCells.position(maPos.first, nRow2+1))
+{
+}
+
+ColumnIterator::~ColumnIterator() {}
+
+void ColumnIterator::next()
+{
+    maPos = CellStoreType::next_position(maPos);
+}
+
+SCROW ColumnIterator::getRow() const
+{
+    return CellStoreType::logical_position(maPos);
+}
+
+bool ColumnIterator::hasCell() const
+{
+    return maPos != maPosEnd;
+}
+
+mdds::mtv::element_t ColumnIterator::getType() const
+{
+    return maPos.first->type;
+}
+
+ScRefCellValue ColumnIterator::getCell() const
+{
+    return toRefCell(maPos.first, maPos.second);
+}
+
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/document10.cxx b/sc/source/core/data/document10.cxx
index 35632d44536f..a2dc93205f91 100644
--- a/sc/source/core/data/document10.cxx
+++ b/sc/source/core/data/document10.cxx
@@ -20,6 +20,7 @@
 #include <bcaslot.hxx>
 #include <cellvalues.hxx>
 #include <docpool.hxx>
+#include <columniterator.hxx>
 
 #include "dociter.hxx"
 #include "patattr.hxx"
@@ -903,4 +904,26 @@ bool ScDocument::IsEditActionAllowed(
     return true;
 }
 
+std::unique_ptr<sc::ColumnIterator> ScDocument::GetColumnIterator( SCTAB nTab, SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
+{
+    const ScTable* pTab = FetchTable(nTab);
+    if (!pTab)
+        return std::unique_ptr<sc::ColumnIterator>();
+
+    return pTab->GetColumnIterator(nCol, nRow1, nRow2);
+}
+
+void ScDocument::EnsureFormulaCellResults( const ScRange& rRange )
+{
+    for (SCTAB nTab = rRange.aStart.Tab(); nTab <= rRange.aEnd.Tab(); ++nTab)
+    {
+        ScTable* pTab = FetchTable(nTab);
+        if (!pTab)
+            continue;
+
+        pTab->EnsureFormulaCellResults(
+            rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row());
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/dpcache.cxx b/sc/source/core/data/dpcache.cxx
index fd41b12a3782..2db6ff88a8b8 100644
--- a/sc/source/core/data/dpcache.cxx
+++ b/sc/source/core/data/dpcache.cxx
@@ -29,6 +29,8 @@
 #include "dpitemdata.hxx"
 #include "dputil.hxx"
 #include "dpnumgroupinfo.hxx"
+#include <columniterator.hxx>
+#include <cellvalue.hxx>
 
 #include <rtl/math.hxx>
 #include <unotools/textsearch.hxx>
@@ -104,9 +106,10 @@ private:
     ScDocument* mpDoc;
 };
 
-OUString createLabelString(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
+OUString createLabelString( const ScDocument* pDoc, SCCOL nCol, const ScRefCellValue& rCell )
 {
-    OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
+    OUString aDocStr = rCell.getRawString(pDoc);
+
     if (aDocStr.isEmpty())
     {
         // Replace an empty label string with column name.
@@ -122,25 +125,24 @@ OUString createLabelString(ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab)
 }
 
 void initFromCell(
-    ScDPCache& rCache, ScDocument* pDoc, SCCOL nCol, SCROW nRow, SCTAB nTab,
+    ScDPCache& rCache, ScDocument* pDoc, const ScAddress& rPos,
+    const ScRefCellValue& rCell,
     ScDPItemData& rData, sal_uInt32& rNumFormat)
 {
-    OUString aDocStr = pDoc->GetString(nCol, nRow, nTab);
+    OUString aDocStr = rCell.getRawString(pDoc);
     rNumFormat = 0;
 
-    ScAddress aPos(nCol, nRow, nTab);
-
-    if (pDoc->GetErrCode(aPos) != FormulaError::NONE)
+    if (rCell.hasError())
     {
         rData.SetErrorString(rCache.InternString(aDocStr));
     }
-    else if (pDoc->HasValueData(nCol, nRow, nTab))
+    else if (rCell.hasNumeric())
     {
-        double fVal = pDoc->GetValue(aPos);
-        rNumFormat = pDoc->GetNumberFormat(aPos);
+        double fVal = rCell.getRawValue();
+        rNumFormat = pDoc->GetNumberFormat(rPos);
         rData.SetValue(fVal);
     }
-    else if (pDoc->HasData(nCol, nRow, nTab))
+    else if (!rCell.isEmpty())
     {
         rData.SetString(rCache.InternString(aDocStr));
     }
@@ -321,21 +323,33 @@ void ScDPCache::InitFromDoc(ScDocument* pDoc, const ScRange& rRange)
 
     maLabelNames.reserve(mnColumnCount+1);
 
+    // Ensure that none of the formula cells in the data range are dirty.
+    pDoc->EnsureFormulaCellResults(rRange);
+
     ScDPItemData aData;
     for (sal_uInt16 nCol = nStartCol; nCol <= nEndCol; ++nCol)
     {
-        AddLabel(createLabelString(pDoc, nCol, nStartRow, nDocTab));
+        std::unique_ptr<sc::ColumnIterator> pIter =
+            pDoc->GetColumnIterator(nDocTab, nCol, nStartRow, nEndRow);
+        assert(pIter);
+        assert(pIter->hasCell());
+
+        AddLabel(createLabelString(pDoc, nCol, pIter->getCell()));
+        pIter->next();
+
         Field& rField = *maFields[nCol-nStartCol].get();
         std::vector<Bucket> aBuckets;
         aBuckets.reserve(nEndRow-nStartRow); // skip the topmost label cell.
 
         // Push back all original values.
-        SCROW nOffset = nStartRow + 1;
-        for (SCROW i = 0, n = nEndRow-nStartRow; i < n; ++i)
+        for (SCROW i = 0, n = nEndRow-nStartRow; i < n; ++i, pIter->next())
         {
-            SCROW nRow = i + nOffset;
+            assert(pIter->hasCell());
+
             sal_uInt32 nNumFormat = 0;
-            initFromCell(*this, pDoc, nCol, nRow, nDocTab, aData, nNumFormat);
+            ScAddress aPos(nCol, pIter->getRow(), nDocTab);
+            initFromCell(*this, pDoc, aPos, pIter->getCell(), aData, nNumFormat);
+
             aBuckets.push_back(Bucket(aData, i));
 
             if (!aData.IsEmpty())
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index b19bfba89bc9..4c6471f781a0 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -2608,15 +2608,25 @@ bool ScFormulaCell::IsValueNoError() const
 double ScFormulaCell::GetValue()
 {
     MaybeInterpret();
+    return GetRawValue();
+}
+
+svl::SharedString ScFormulaCell::GetString()
+{
+    MaybeInterpret();
+    return GetRawString();
+}
+
+double ScFormulaCell::GetRawValue() const
+{
     if ((pCode->GetCodeError() == FormulaError::NONE || pCode->GetCodeError() == FormulaError::DoubleRef) &&
             aResult.GetResultError() == FormulaError::NONE)
         return aResult.GetDouble();
     return 0.0;
 }
 
-svl::SharedString ScFormulaCell::GetString()
+svl::SharedString ScFormulaCell::GetRawString() const
 {
-    MaybeInterpret();
     if ((pCode->GetCodeError() == FormulaError::NONE || pCode->GetCodeError() == FormulaError::DoubleRef) &&
             aResult.GetResultError() == FormulaError::NONE)
         return aResult.GetString();
diff --git a/sc/source/core/data/mtvcellfunc.cxx b/sc/source/core/data/mtvcellfunc.cxx
new file mode 100644
index 000000000000..98f6998cc120
--- /dev/null
+++ b/sc/source/core/data/mtvcellfunc.cxx
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 <mtvcellfunc.hxx>
+
+namespace sc {
+
+CellStoreType::iterator ProcessFormula(
+    const CellStoreType::iterator& it, CellStoreType& rStore, SCROW nRow1, SCROW nRow2,
+    std::function<void(size_t,ScFormulaCell*)> aFuncElem )
+{
+    using FuncType = std::function<void(size_t,ScFormulaCell*)>;
+    using ElseFuncType = std::function<void(mdds::mtv::element_t, size_t, size_t)>;
+
+    // empty function for handling the 'else' part.
+    static ElseFuncType aFuncElse =
+        [](mdds::mtv::element_t,size_t,size_t) {};
+
+    return ProcessElements1<
+        CellStoreType, formula_block,
+        FuncType, ElseFuncType>(
+            it, rStore, nRow1, nRow2, aFuncElem, aFuncElse);
+}
+
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/core/data/table7.cxx b/sc/source/core/data/table7.cxx
index 6179737aec93..b8bd98e5d1a9 100644
--- a/sc/source/core/data/table7.cxx
+++ b/sc/source/core/data/table7.cxx
@@ -17,6 +17,7 @@
 #include <cellvalues.hxx>
 #include "olinetab.hxx"
 #include <tabprotection.hxx>
+#include <columniterator.hxx>
 
 bool ScTable::IsMerged( SCCOL nCol, SCROW nRow ) const
 {
@@ -392,6 +393,23 @@ bool ScTable::IsEditActionAllowed(
     return false;
 }
 
+std::unique_ptr<sc::ColumnIterator> ScTable::GetColumnIterator( SCCOL nCol, SCROW nRow1, SCROW nRow2 ) const
+{
+    if (!ValidCol(nCol) || nCol >= aCol.size())
+        return std::unique_ptr<sc::ColumnIterator>();
+
+    return aCol[nCol].GetColumnIterator(nRow1, nRow2);
+}
+
+void ScTable::EnsureFormulaCellResults( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2 )
+{
+    if (nCol2 < nCol1 || !ValidCol(nCol1) || !ValidCol(nCol2))
+        return;
+
+    for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
+        aCol[nCol].EnsureFormulaCellResults(nRow1, nRow2);
+}
+
 void ScTable::finalizeOutlineImport()
 {
     if (pOutlineTable && pRowFlags)


More information about the Libreoffice-commits mailing list