external/liborcus/UnpackedTarball_liborcus.mk |    1 
 external/liborcus/autofilter-crash.patch      |   34 +++
 sc/Library_scfilt.mk                          |    1 
 sc/inc/queryentry.hxx                         |    1 
 sc/source/core/tool/queryentry.cxx            |    9 
 sc/source/filter/inc/orcus_autofilter.hxx     |  111 +++++++++
 sc/source/filter/inc/orcusinterface.hxx       |    9 
 sc/source/filter/orcus/autofilter.cxx         |  291 ++++++++++++++++++++++++++
 sc/source/filter/orcus/interface.cxx          |   17 +
 9 files changed, 467 insertions(+), 7 deletions(-)

New commits:
commit 08c9e64c0bedc05767dbcdfb879d389e0c413d85
Author:     Kohei Yoshida <ko...@libreoffice.org>
AuthorDate: Thu Mar 6 22:27:20 2025 -0500
Commit:     Kohei Yoshida <ko...@libreoffice.org>
CommitDate: Sat Mar 8 03:40:19 2025 +0100

    Import autofilter via orcus interface
    
    This should address tdf#154311.
    
    Change-Id: I84401ad7a9982eaa868e68d7ae612debf09ecf9e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182606
    Tested-by: Jenkins
    Reviewed-by: Kohei Yoshida <ko...@libreoffice.org>

diff --git a/external/liborcus/UnpackedTarball_liborcus.mk 
b/external/liborcus/UnpackedTarball_liborcus.mk
index b866f59c6ac9..24412db28496 100644
--- a/external/liborcus/UnpackedTarball_liborcus.mk
+++ b/external/liborcus/UnpackedTarball_liborcus.mk
@@ -20,6 +20,7 @@ $(eval $(call gb_UnpackedTarball_add_patches,liborcus,\
        external/liborcus/libtool.patch.0 \
        external/liborcus/styles-element-rules.patch \
        external/liborcus/enum-labels.patch \
+       external/liborcus/autofilter-crash.patch \
 ))
 
 ifeq ($(OS),WNT)
diff --git a/external/liborcus/autofilter-crash.patch 
b/external/liborcus/autofilter-crash.patch
new file mode 100644
index 000000000000..d434cc94356e
--- /dev/null
+++ b/external/liborcus/autofilter-crash.patch
@@ -0,0 +1,34 @@
+From 2ff46664c61f2cce545ac7ca972d6e9c6ffa270d Mon Sep 17 00:00:00 2001
+From: Kohei Yoshida <kohei.yosh...@gmail.com>
+Date: Thu, 27 Feb 2025 21:39:52 -0500
+Subject: [PATCH] Filter node stack may be empty when no filtering is applied
+
+But when the stack is not empty, then the assert condition still
+stands.  This is related to #207.
+---
+ src/liborcus/xls_xml_auto_filter_context.cpp | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/liborcus/xls_xml_auto_filter_context.cpp 
b/src/liborcus/xls_xml_auto_filter_context.cpp
+index 509c0b25..34a9210c 100644
+--- a/src/liborcus/xls_xml_auto_filter_context.cpp
++++ b/src/liborcus/xls_xml_auto_filter_context.cpp
+@@ -193,9 +193,12 @@ void xls_xml_auto_filter_context::end_auto_filter()
+     if (!mp_auto_filter)
+         return;
+ 
+-    assert(m_filter_node_stack.size() == 1u); // root node
+-    m_filter_node_stack.back()->commit();
+-    m_filter_node_stack.pop_back();
++    if (!m_filter_node_stack.empty())
++    {
++        assert(m_filter_node_stack.size() == 1u); // root node
++        m_filter_node_stack.back()->commit();
++        m_filter_node_stack.pop_back();
++    }
+     mp_auto_filter->commit();
+ }
+ 
+-- 
+2.34.1
+
diff --git a/sc/Library_scfilt.mk b/sc/Library_scfilt.mk
index e4936656676e..d060e3880ae7 100644
--- a/sc/Library_scfilt.mk
+++ b/sc/Library_scfilt.mk
@@ -234,6 +234,7 @@ $(eval $(call gb_Library_use_externals,scfilt,\
 ))
 
 $(eval $(call gb_Library_add_exception_objects,scfilt,\
+       sc/source/filter/orcus/autofilter \
        sc/source/filter/orcus/interface \
        sc/source/filter/orcus/orcusfiltersimpl \
        sc/source/filter/orcus/xmlcontext \
diff --git a/sc/inc/queryentry.hxx b/sc/inc/queryentry.hxx
index 9798b83df785..ad130549cb0f 100644
--- a/sc/inc/queryentry.hxx
+++ b/sc/inc/queryentry.hxx
@@ -66,6 +66,7 @@ struct SC_DLLPUBLIC ScQueryEntry final
 
     ScQueryEntry();
     ScQueryEntry(const ScQueryEntry& r);
+    ScQueryEntry(ScQueryEntry&& r) noexcept;
     ~ScQueryEntry();
 
     /// creates pSearchParam and pSearchText if necessary
diff --git a/sc/source/core/tool/queryentry.cxx 
b/sc/source/core/tool/queryentry.cxx
index d66382d2e2b8..a39dabdcf559 100644
--- a/sc/source/core/tool/queryentry.cxx
+++ b/sc/source/core/tool/queryentry.cxx
@@ -56,6 +56,15 @@ ScQueryEntry::ScQueryEntry(const ScQueryEntry& r) :
 {
 }
 
+ScQueryEntry::ScQueryEntry(ScQueryEntry&& r) noexcept :
+    bDoQuery(r.bDoQuery),
+    nField(r.nField),
+    eOp(r.eOp),
+    eConnect(r.eConnect),
+    maQueryItems(std::move(r.maQueryItems))
+{
+}
+
 ScQueryEntry::~ScQueryEntry()
 {
 }
diff --git a/sc/source/filter/inc/orcus_autofilter.hxx 
b/sc/source/filter/inc/orcus_autofilter.hxx
new file mode 100644
index 000000000000..22be6a29db4d
--- /dev/null
+++ b/sc/source/filter/inc/orcus_autofilter.hxx
@@ -0,0 +1,111 @@
+/* -*- 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/.
+ */
+
+#pragma once
+
+#include <address.hxx>
+#include <documentimport.hxx>
+#include <queryentry.hxx>
+
+#include <orcus/spreadsheet/import_interface_auto_filter.hpp>
+
+#include <vector>
+#include <functional>
+
+class ScOrcusGlobalSettings;
+
+class ScOrcusAutoFilterMultiValues
+    : public orcus::spreadsheet::iface::import_auto_filter_multi_values
+{
+public:
+    using commitFuncType = std::function<void(ScQueryEntry)>;
+
+    ScOrcusAutoFilterMultiValues(ScDocument& rDoc, const 
ScOrcusGlobalSettings& rGS);
+
+    void add_value(std::string_view value) override;
+
+    void commit() override;
+
+    void reset(commitFuncType func);
+
+private:
+    ScDocument& mrDoc;
+    const ScOrcusGlobalSettings& mrGlobalSettings;
+
+    ScQueryEntry maEntry;
+    commitFuncType maCommitFunc;
+};
+
+class ScOrcusAutoFilterNode : public 
orcus::spreadsheet::iface::import_auto_filter_node
+{
+public:
+    using commitFuncType = std::function<void(std::vector<ScQueryEntry>, 
bool)>;
+
+    ScOrcusAutoFilterNode(ScDocument& rDoc, const ScOrcusGlobalSettings& rGS);
+
+    virtual void append_item(orcus::spreadsheet::col_t field,
+                             orcus::spreadsheet::auto_filter_op_t op, double 
value) override;
+
+    virtual void append_item(orcus::spreadsheet::col_t field,
+                             orcus::spreadsheet::auto_filter_op_t op, 
std::string_view value,
+                             bool regex) override;
+
+    virtual void append_item(orcus::spreadsheet::col_t field,
+                             orcus::spreadsheet::auto_filter_op_t op) override;
+
+    virtual orcus::spreadsheet::iface::import_auto_filter_node*
+    start_node(orcus::spreadsheet::auto_filter_node_op_t op) override;
+
+    virtual orcus::spreadsheet::iface::import_auto_filter_multi_values*
+    start_multi_values(orcus::spreadsheet::col_t field) override;
+
+    virtual void commit() override;
+
+    void reset(SCCOL nStartCol, ScQueryConnect eConn, commitFuncType func);
+
+private:
+    ScDocument& mrDoc;
+    const ScOrcusGlobalSettings& mrGlobalSettings;
+    ScOrcusAutoFilterMultiValues maMultiValues;
+    std::unique_ptr<ScOrcusAutoFilterNode> mxChild;
+
+    SCCOL mnStartCol = -1;
+    ScQueryConnect meConn;
+    bool mbHasRegex = false;
+
+    std::vector<ScQueryEntry> maEntries;
+    commitFuncType maCommitFunc;
+};
+
+class ScOrcusAutoFilter : public orcus::spreadsheet::iface::import_auto_filter
+{
+public:
+    ScOrcusAutoFilter(ScDocumentImport& rDoc, const ScOrcusGlobalSettings& 
rGS, SCTAB nTab);
+    ScOrcusAutoFilter(const ScOrcusAutoFilter&) = delete;
+    ~ScOrcusAutoFilter();
+
+    virtual orcus::spreadsheet::iface::import_auto_filter_node*
+    start_node(orcus::spreadsheet::auto_filter_node_op_t op) override;
+
+    virtual void commit() override;
+
+    void reset(const orcus::spreadsheet::range_t& range);
+
+private:
+    ScDocumentImport& mrDoc;
+
+    ScOrcusAutoFilterNode maNode;
+    std::unique_ptr<ScDBData> mxData;
+
+    const SCTAB mnTab;
+    SCCOL mnCol1;
+    SCCOL mnCol2;
+    SCROW mnRow1;
+    SCROW mnRow2;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/orcusinterface.hxx 
b/sc/source/filter/inc/orcusinterface.hxx
index d9c7e2eacacc..1ff420a358cd 100644
--- a/sc/source/filter/inc/orcusinterface.hxx
+++ b/sc/source/filter/inc/orcusinterface.hxx
@@ -18,6 +18,7 @@
 #include <editeng/svxenum.hxx>
 #include <editeng/editobj.hxx>
 
+#include "orcus_autofilter.hxx"
 #include "sharedformulagroups.hxx"
 
 #include <conditio.hxx>
@@ -366,7 +367,7 @@ class ScOrcusSheet : public 
orcus::spreadsheet::iface::import_sheet
     friend class ScOrcusArrayFormula;
 
     ScDocumentImport& mrDoc;
-    SCTAB mnTab;
+    const SCTAB mnTab;
     ScOrcusFactory& mrFactory;
     ScOrcusStyles& mrStyles;
     sc::SharedFormulaGroups maFormulaGroups;
@@ -376,6 +377,7 @@ class ScOrcusSheet : public 
orcus::spreadsheet::iface::import_sheet
     ScOrcusNamedExpression maNamedExpressions;
     ScOrcusFormula maFormula;
     ScOrcusArrayFormula maArrayFormula;
+    ScOrcusAutoFilter maAutoFilter;
 
     int mnCellCount;
 
@@ -384,7 +386,7 @@ class ScOrcusSheet : public 
orcus::spreadsheet::iface::import_sheet
     ScDocumentImport& getDoc();
 
 public:
-    ScOrcusSheet(ScDocumentImport& rDoc, SCTAB nTab, ScOrcusFactory& rFactory);
+    ScOrcusSheet(ScDocumentImport& rDoc, const ScOrcusGlobalSettings& rGS, 
SCTAB nTab, ScOrcusFactory& rFactory);
 
     virtual orcus::spreadsheet::iface::import_sheet_properties* 
get_sheet_properties() override;
     virtual orcus::spreadsheet::iface::import_conditional_format* 
get_conditional_format() override;
@@ -411,6 +413,9 @@ public:
 
     virtual void fill_down_cells(orcus::spreadsheet::row_t row, 
orcus::spreadsheet::col_t col, orcus::spreadsheet::row_t range_size) override;
 
+    virtual orcus::spreadsheet::iface::import_auto_filter*
+        start_auto_filter(const orcus::spreadsheet::range_t& range) override;
+
     SCTAB getIndex() const { return mnTab; }
 
     const sc::SharedFormulaGroups& getSharedFormulaGroups() const;
diff --git a/sc/source/filter/orcus/autofilter.cxx 
b/sc/source/filter/orcus/autofilter.cxx
new file mode 100644
index 000000000000..344dbcdc0b06
--- /dev/null
+++ b/sc/source/filter/orcus/autofilter.cxx
@@ -0,0 +1,291 @@
+/* -*- 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 <orcus_autofilter.hxx>
+#include <orcusinterface.hxx>
+#include <dbdata.hxx>
+#include <globalnames.hxx>
+#include <queryparam.hxx>
+
+#include <svl/sharedstringpool.hxx>
+
+#include <memory>
+
+namespace os = orcus::spreadsheet;
+
+namespace
+{
+ScQueryConnect toQueryConnect(os::auto_filter_node_op_t op)
+{
+    switch (op)
+    {
+        case os::auto_filter_node_op_t::op_and:
+            return SC_AND;
+        case os::auto_filter_node_op_t::op_or:
+            return SC_OR;
+        case os::auto_filter_node_op_t::unspecified:;
+    }
+
+    throw std::runtime_error("filter node operator type is not specified");
+}
+
+void setQueryOp(ScQueryEntry& rEntry, os::auto_filter_op_t op)
+{
+    switch (op)
+    {
+        case os::auto_filter_op_t::empty:
+            rEntry.bDoQuery = true;
+            rEntry.SetQueryByEmpty();
+            break;
+        case os::auto_filter_op_t::not_empty:
+            rEntry.bDoQuery = true;
+            rEntry.SetQueryByNonEmpty();
+            break;
+        case os::auto_filter_op_t::equal:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_EQUAL;
+            break;
+        case os::auto_filter_op_t::not_equal:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_NOT_EQUAL;
+            break;
+        case os::auto_filter_op_t::contain:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_CONTAINS;
+            break;
+        case os::auto_filter_op_t::not_contain:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_DOES_NOT_CONTAIN;
+            break;
+        case os::auto_filter_op_t::begin_with:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_BEGINS_WITH;
+            break;
+        case os::auto_filter_op_t::not_begin_with:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_DOES_NOT_BEGIN_WITH;
+            break;
+        case os::auto_filter_op_t::end_with:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_ENDS_WITH;
+            break;
+        case os::auto_filter_op_t::not_end_with:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_DOES_NOT_END_WITH;
+            break;
+        case os::auto_filter_op_t::greater:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_GREATER;
+            break;
+        case os::auto_filter_op_t::greater_equal:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_GREATER_EQUAL;
+            break;
+        case os::auto_filter_op_t::less:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_LESS;
+            break;
+        case os::auto_filter_op_t::less_equal:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_LESS_EQUAL;
+            break;
+        case os::auto_filter_op_t::top:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_TOPVAL;
+            break;
+        case os::auto_filter_op_t::bottom:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_BOTVAL;
+            break;
+        case os::auto_filter_op_t::top_percent:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_TOPPERC;
+            break;
+        case os::auto_filter_op_t::bottom_percent:
+            rEntry.bDoQuery = true;
+            rEntry.eOp = SC_BOTPERC;
+            break;
+        case os::auto_filter_op_t::top_percent_range:
+        case os::auto_filter_op_t::bottom_percent_range:
+        case os::auto_filter_op_t::unspecified:
+            rEntry.bDoQuery = false;
+            break;
+    }
+}
+}
+
+ScOrcusAutoFilterMultiValues::ScOrcusAutoFilterMultiValues(ScDocument& rDoc,
+                                                           const 
ScOrcusGlobalSettings& rGS)
+    : mrDoc(rDoc)
+    , mrGlobalSettings(rGS)
+{
+}
+
+void ScOrcusAutoFilterMultiValues::add_value(std::string_view value)
+{
+    OUString aStr(value.data(), value.size(), 
mrGlobalSettings.getTextEncoding());
+
+    ScQueryEntry::Item aItem;
+    aItem.maString = mrDoc.GetSharedStringPool().intern(aStr);
+    aItem.meType = ScQueryEntry::ByString;
+
+    maEntry.GetQueryItems().push_back(aItem);
+}
+
+void ScOrcusAutoFilterMultiValues::commit() { 
maCommitFunc(std::move(maEntry)); }
+
+void ScOrcusAutoFilterMultiValues::reset(commitFuncType func)
+{
+    maEntry.Clear();
+    maEntry.bDoQuery = true;
+    maCommitFunc = std::move(func);
+}
+
+ScOrcusAutoFilterNode::ScOrcusAutoFilterNode(ScDocument& rDoc, const 
ScOrcusGlobalSettings& rGS)
+    : mrDoc(rDoc)
+    , mrGlobalSettings(rGS)
+    , maMultiValues(rDoc, rGS)
+{
+}
+
+void ScOrcusAutoFilterNode::append_item(os::col_t field, os::auto_filter_op_t 
op, double value)
+{
+    ScQueryEntry aEntry;
+    aEntry.nField = mnStartCol + field;
+    aEntry.eConnect = meConn;
+    setQueryOp(aEntry, op);
+    aEntry.GetQueryItem().meType = ScQueryEntry::ByValue;
+    aEntry.GetQueryItem().mfVal = value;
+
+    maEntries.push_back(aEntry);
+}
+
+void ScOrcusAutoFilterNode::append_item(os::col_t field, os::auto_filter_op_t 
op,
+                                        std::string_view value, bool regex)
+{
+    ScQueryEntry aEntry;
+    aEntry.nField = mnStartCol + field;
+    aEntry.eConnect = meConn;
+    setQueryOp(aEntry, op);
+    aEntry.GetQueryItem().meType = ScQueryEntry::ByString;
+
+    OUString aStr(value.data(), value.size(), 
mrGlobalSettings.getTextEncoding());
+    aEntry.GetQueryItem().maString = mrDoc.GetSharedStringPool().intern(aStr);
+
+    maEntries.push_back(aEntry);
+
+    if (regex)
+        mbHasRegex = true;
+}
+
+void ScOrcusAutoFilterNode::append_item(os::col_t field, os::auto_filter_op_t 
op)
+{
+    ScQueryEntry aEntry;
+    aEntry.nField = mnStartCol + field;
+    aEntry.eConnect = meConn;
+    setQueryOp(aEntry, op);
+
+    maEntries.push_back(aEntry);
+}
+
+os::iface::import_auto_filter_node* 
ScOrcusAutoFilterNode::start_node(os::auto_filter_node_op_t op)
+{
+    auto func = [this](std::vector<ScQueryEntry> aEntries, bool bHasRegex) {
+        if (aEntries.empty())
+            return;
+
+        aEntries[0].eConnect = meConn;
+
+        for (auto& rEntry : aEntries)
+            maEntries.push_back(std::move(rEntry));
+
+        if (bHasRegex)
+            mbHasRegex = true;
+    };
+
+    mxChild = std::make_unique<ScOrcusAutoFilterNode>(mrDoc, mrGlobalSettings);
+    mxChild->reset(mnStartCol, toQueryConnect(op), std::move(func));
+    return mxChild.get();
+}
+
+os::iface::import_auto_filter_multi_values*
+ScOrcusAutoFilterNode::start_multi_values(os::col_t field)
+{
+    auto func = [this, field](ScQueryEntry aEntry) {
+        aEntry.nField = mnStartCol + field;
+        maEntries.push_back(std::move(aEntry));
+    };
+
+    maMultiValues.reset(std::move(func));
+    return &maMultiValues;
+}
+
+void ScOrcusAutoFilterNode::commit() { maCommitFunc(std::move(maEntries), 
mbHasRegex); }
+
+void ScOrcusAutoFilterNode::reset(SCCOL nStartCol, ScQueryConnect eConn, 
commitFuncType func)
+{
+    mnStartCol = nStartCol;
+    meConn = eConn;
+
+    mxChild.reset();
+    maEntries.clear();
+    maCommitFunc = std::move(func);
+}
+
+ScOrcusAutoFilter::ScOrcusAutoFilter(ScDocumentImport& rDoc, const 
ScOrcusGlobalSettings& rGS,
+                                     SCTAB nTab)
+    : mrDoc(rDoc)
+    , maNode(rDoc.getDoc(), rGS)
+    , mnTab(nTab)
+{
+}
+
+ScOrcusAutoFilter::~ScOrcusAutoFilter() = default;
+
+os::iface::import_auto_filter_node* 
ScOrcusAutoFilter::start_node(os::auto_filter_node_op_t op)
+{
+    ScDBData& rData = *mxData;
+    auto func = [&rData](std::vector<ScQueryEntry> aEntries, bool bHasRegex) {
+        ScQueryParam aParam;
+
+        if (bHasRegex)
+            aParam.eSearchType = utl::SearchParam::SearchType::Regexp;
+
+        for (auto& rEntry : aEntries)
+            aParam.AppendEntry() = std::move(rEntry);
+
+        rData.SetQueryParam(aParam);
+    };
+
+    maNode.reset(mnCol1, toQueryConnect(op), std::move(func));
+    return &maNode;
+}
+
+void ScOrcusAutoFilter::commit()
+{
+    auto& rDoc = mrDoc.getDoc();
+    rDoc.SetAnonymousDBData(mnTab, std::move(mxData));
+
+    for (SCCOL nCol = mnCol1; nCol <= mnCol2; ++nCol)
+    {
+        auto nFlag = rDoc.GetAttr(nCol, mnRow1, mnTab, 
ATTR_MERGE_FLAG)->GetValue();
+        rDoc.ApplyAttr(nCol, mnRow1, mnTab, ScMergeFlagAttr(nFlag | 
ScMF::Auto));
+    }
+}
+
+void ScOrcusAutoFilter::reset(const os::range_t& range)
+{
+    mnCol1 = range.first.column;
+    mnCol2 = range.last.column;
+    mnRow1 = range.first.row;
+    mnRow2 = range.last.row;
+
+    mxData = std::make_unique<ScDBData>(STR_DB_LOCAL_NONAME, mnTab, mnCol1, 
mnRow1, mnCol2, mnRow2);
+    mxData->SetAutoFilter(true);
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/orcus/interface.cxx 
b/sc/source/filter/orcus/interface.cxx
index e64a6134c674..aaa8b8e0281b 100644
--- a/sc/source/filter/orcus/interface.cxx
+++ b/sc/source/filter/orcus/interface.cxx
@@ -329,7 +329,7 @@ orcus::spreadsheet::iface::import_sheet* 
ScOrcusFactory::append_sheet(
         // The calc document initializes with one sheet already present.
         assert(maDoc.getSheetCount() == 1);
         maDoc.setSheetName(0, aTabName);
-        maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, 0, *this));
+        maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, 
maGlobalSettings, 0, *this));
         return maSheets.back().get();
     }
 
@@ -337,7 +337,7 @@ orcus::spreadsheet::iface::import_sheet* 
ScOrcusFactory::append_sheet(
         return nullptr;
 
     SCTAB nTab = maDoc.getSheetCount() - 1;
-    maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, nTab, *this));
+    maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, maGlobalSettings, 
nTab, *this));
     return maSheets.back().get();
 }
 
@@ -373,7 +373,7 @@ orcus::spreadsheet::iface::import_sheet* 
ScOrcusFactory::get_sheet(std::string_v
         return it->get();
 
     // Create a new orcus sheet instance for this.
-    maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, nTab, *this));
+    maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, maGlobalSettings, 
nTab, *this));
     return maSheets.back().get();
 }
 
@@ -389,7 +389,7 @@ orcus::spreadsheet::iface::import_sheet* 
ScOrcusFactory::get_sheet(orcus::spread
         return it->get();
 
     // Create a new orcus sheet instance for this.
-    maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, nTab, *this));
+    maSheets.push_back(std::make_unique<ScOrcusSheet>(maDoc, maGlobalSettings, 
nTab, *this));
     return maSheets.back().get();
 }
 
@@ -963,7 +963,7 @@ void ScOrcusConditionalFormat::commit_format()
     mpCurrentFormat.reset(new ScConditionalFormat(0, &mrDoc));
 }
 
-ScOrcusSheet::ScOrcusSheet(ScDocumentImport& rDoc, SCTAB nTab, ScOrcusFactory& 
rFactory) :
+ScOrcusSheet::ScOrcusSheet(ScDocumentImport& rDoc, const 
ScOrcusGlobalSettings& rGS, SCTAB nTab, ScOrcusFactory& rFactory) :
     mrDoc(rDoc),
     mnTab(nTab),
     mrFactory(rFactory),
@@ -973,6 +973,7 @@ ScOrcusSheet::ScOrcusSheet(ScDocumentImport& rDoc, SCTAB 
nTab, ScOrcusFactory& r
     maNamedExpressions(rDoc, rFactory.getGlobalSettings(), nTab),
     maFormula(*this),
     maArrayFormula(*this),
+    maAutoFilter(rDoc, rGS, nTab),
     mnCellCount(0)
 {
 }
@@ -1301,6 +1302,12 @@ void ScOrcusSheet::fill_down_cells(os::row_t row, 
os::col_t col, os::row_t range
     cellInserted();
 }
 
+os::iface::import_auto_filter* ScOrcusSheet::start_auto_filter(const 
os::range_t& range)
+{
+    maAutoFilter.reset(range);
+    return &maAutoFilter;
+}
+
 const sc::SharedFormulaGroups& ScOrcusSheet::getSharedFormulaGroups() const
 {
     return maFormulaGroups;

Reply via email to