sc/qa/unit/data/xlsb/tdf151505.xlsb        |binary
 sc/qa/unit/data/xlsx/tdf157689.xlsx        |binary
 sc/qa/unit/subsequent_filters_test5.cxx    |   45 +++++++++++++++++++++++++++++
 sc/source/filter/inc/autofilterbuffer.hxx  |    2 +
 sc/source/filter/oox/autofilterbuffer.cxx  |   20 +++++++-----
 sc/source/filter/oox/autofiltercontext.cxx |    3 +
 sc/source/filter/oox/defnamesbuffer.cxx    |   12 +++++++
 7 files changed, 72 insertions(+), 10 deletions(-)

New commits:
commit e73fc4335bf20cb55db069208f489fa2519deeee
Author:     Markus Mohrhard <markus.mohrh...@googlemail.com>
AuthorDate: Thu Jul 17 09:11:18 2025 +0800
Commit:     Markus Mohrhard <markus.mohrh...@googlemail.com>
CommitDate: Thu Jul 17 08:18:21 2025 +0200

    tdf#151505: fix autofilter import in XLSB
    
    Change-Id: I880ba2f8ea384e092cd90d8b4fe2ad0356f6c1d8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187979
    Reviewed-by: Markus Mohrhard <markus.mohrh...@googlemail.com>
    Tested-by: Jenkins

diff --git a/sc/qa/unit/data/xlsb/tdf151505.xlsb 
b/sc/qa/unit/data/xlsb/tdf151505.xlsb
new file mode 100644
index 000000000000..72ecfe7d8093
Binary files /dev/null and b/sc/qa/unit/data/xlsb/tdf151505.xlsb differ
diff --git a/sc/qa/unit/subsequent_filters_test5.cxx 
b/sc/qa/unit/subsequent_filters_test5.cxx
index b4765657bcbe..3cc0a534da3a 100644
--- a/sc/qa/unit/subsequent_filters_test5.cxx
+++ b/sc/qa/unit/subsequent_filters_test5.cxx
@@ -1,4 +1,5 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
 /*
  * This file is part of the LibreOffice project.
  *
@@ -158,6 +159,27 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf157689)
     CPPUNIT_ASSERT(pAnonDBData->HasAutoFilter());
 }
 
+CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf151505)
+{
+    // testing the correct import of autofilter from XLSB
+    createScDoc("xlsb/tdf151505.xlsb");
+
+    ScDocument* pDoc = getScDoc();
+
+    ScDBData* pAnonDBData = pDoc->GetAnonymousDBData(0);
+    CPPUNIT_ASSERT(pAnonDBData);
+    ScRange aFilterRange;
+    pAnonDBData->GetArea(aFilterRange);
+    CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, 0, 1, 4, 0), aFilterRange); // A1:B5
+    CPPUNIT_ASSERT(pAnonDBData->HasAutoFilter());
+
+    // also check for the correct handling of the autofilter buttons
+    auto nFlag = pDoc->GetAttr(0, 0, 0, ATTR_MERGE_FLAG)->GetValue();
+    CPPUNIT_ASSERT(nFlag & ScMF::Auto);
+    nFlag = pDoc->GetAttr(1, 0, 0, ATTR_MERGE_FLAG)->GetValue();
+    CPPUNIT_ASSERT(nFlag & ScMF::Auto);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/oox/autofiltercontext.cxx 
b/sc/source/filter/oox/autofiltercontext.cxx
index 9cdbacea4e92..919ae0a634db 100644
--- a/sc/source/filter/oox/autofiltercontext.cxx
+++ b/sc/source/filter/oox/autofiltercontext.cxx
@@ -211,7 +211,8 @@ ContextHandlerRef AutoFilterContext::onCreateRecordContext( 
sal_Int32 nRecId, Se
 
 void AutoFilterContext::onStartRecord( SequenceInputStream& rStrm )
 {
-    mrAutoFilter.importAutoFilter( rStrm, getSheetIndex() );
+    if( getCurrentElement() == BIFF12_ID_AUTOFILTER )
+        mrAutoFilter.importAutoFilter( rStrm, getSheetIndex() );
 }
 
 } // namespace oox::xls
diff --git a/sc/source/filter/oox/defnamesbuffer.cxx 
b/sc/source/filter/oox/defnamesbuffer.cxx
index c68b8fd47346..7b2ebe3edd93 100644
--- a/sc/source/filter/oox/defnamesbuffer.cxx
+++ b/sc/source/filter/oox/defnamesbuffer.cxx
@@ -271,11 +271,21 @@ bool DefinedName::isValid(
 std::unique_ptr<ScTokenArray> DefinedName::getScTokens(
         const css::uno::Sequence<css::sheet::ExternalLinkInfo>& rExternalLinks 
)
 {
+    ScAddress aReferenceAddr(0, 0, (mnCalcSheet < 0 ? 0 : mnCalcSheet));
+    ScDocument& rDoc = getScDocument();
+    if (mxFormula) {
+        SequenceInputStream aInputStrm(*mxFormula);
+        ApiTokenSequence aTokens = 
getFormulaParser().importFormula(aReferenceAddr, FormulaType::Cell, aInputStrm);
+        std::unique_ptr<ScTokenArray> pArray(new ScTokenArray(rDoc));
+        (void)ScTokenConversion::ConvertToTokenArray( rDoc, *pArray, aTokens );
+        return pArray;
+    }
+
     // mnCalcSheet < 0 means global name and results in tab deleted when
     // compiling a reference without sheet reference. For a global name it
     // doesn't really matter which sheet is the position's default sheet if the
     // reference doesn't specify any. tdf#164895
-    ScCompiler aCompiler(getScDocument(), ScAddress(0, 0, (mnCalcSheet < 0 ? 0 
: mnCalcSheet)),
+    ScCompiler aCompiler(getScDocument(), aReferenceAddr,
             formula::FormulaGrammar::GRAM_OOXML);
     aCompiler.SetExternalLinks( rExternalLinks);
     std::unique_ptr<ScTokenArray> 
pArray(aCompiler.CompileString(maModel.maFormula));
commit fdc12da000fa238fc141e1d10e94af9099240658
Author:     Markus Mohrhard <markus.mohrh...@googlemail.com>
AuthorDate: Wed Jul 16 07:19:10 2025 +0800
Commit:     Markus Mohrhard <markus.mohrh...@googlemail.com>
CommitDate: Thu Jul 17 08:18:09 2025 +0200

    tdf#157689: don't use workbook DB range for importing autofilters
    
    When there was just a global anonymous DB range the import using the
    global DB range made sense. With the per-sheet anonymous DB ranges
    we can avoid this indirection and should use the range specified
    in the autofilter entry.
    
    Change-Id: Icc4879257c1f93a0977f118a8f89b6c87a5f5b52
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/187977
    Reviewed-by: Markus Mohrhard <markus.mohrh...@googlemail.com>
    Tested-by: Jenkins

diff --git a/sc/qa/unit/data/xlsx/tdf157689.xlsx 
b/sc/qa/unit/data/xlsx/tdf157689.xlsx
new file mode 100644
index 000000000000..6246f25f7c7d
Binary files /dev/null and b/sc/qa/unit/data/xlsx/tdf157689.xlsx differ
diff --git a/sc/qa/unit/subsequent_filters_test5.cxx 
b/sc/qa/unit/subsequent_filters_test5.cxx
index a49945bb1032..b4765657bcbe 100644
--- a/sc/qa/unit/subsequent_filters_test5.cxx
+++ b/sc/qa/unit/subsequent_filters_test5.cxx
@@ -19,6 +19,8 @@
 #include <com/sun/star/sheet/XDatabaseRange.hpp>
 #include <com/sun/star/sheet/XSpreadsheetDocument.hpp>
 
+#include <dbdata.hxx>
+
 using namespace css;
 using namespace css::uno;
 
@@ -135,6 +137,27 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest5, 
testTdf162177_EastersundayODF14)
     assertXPath(pXmlDoc, sPath, "formula", u"of:=EASTERSUNDAY(2024)");
 }
 
+CPPUNIT_TEST_FIXTURE(ScFiltersTest5, testTdf157689)
+{
+    // testing the correct import of autofilter on multiple sheets
+    createScDoc("xlsx/tdf157689.xlsx");
+
+    ScDocument* pDoc = getScDoc();
+
+    ScDBData* pAnonDBData = pDoc->GetAnonymousDBData(0);
+    CPPUNIT_ASSERT(pAnonDBData);
+    ScRange aFilterRange;
+    pAnonDBData->GetArea(aFilterRange);
+    CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, 0, 1, 3, 0), aFilterRange); // A1:B4
+    CPPUNIT_ASSERT(pAnonDBData->HasAutoFilter());
+
+    pAnonDBData = pDoc->GetAnonymousDBData(1);
+    CPPUNIT_ASSERT(pAnonDBData);
+    pAnonDBData->GetArea(aFilterRange);
+    CPPUNIT_ASSERT_EQUAL(ScRange(0, 0, 1, 1, 4, 1), aFilterRange); // A1:B5
+    CPPUNIT_ASSERT(pAnonDBData->HasAutoFilter());
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sc/source/filter/inc/autofilterbuffer.hxx 
b/sc/source/filter/inc/autofilterbuffer.hxx
index 70203c36f0a8..e7e51834a2fd 100644
--- a/sc/source/filter/inc/autofilterbuffer.hxx
+++ b/sc/source/filter/inc/autofilterbuffer.hxx
@@ -243,6 +243,8 @@ public:
     void                finalizeImport( const css::uno::Reference< 
css::sheet::XDatabaseRange >& rxDatabaseRange,
                                         sal_Int16 nSheet );
 
+    css::uno::Reference< css::sheet::XDatabaseRange > 
createDatabaseObject(sal_Int16 nSheet);
+
 private:
     typedef RefVector< FilterColumn > FilterColumnVector;
 
diff --git a/sc/source/filter/oox/autofilterbuffer.cxx 
b/sc/source/filter/oox/autofilterbuffer.cxx
index 39f88ab96778..d5567250fc3a 100644
--- a/sc/source/filter/oox/autofilterbuffer.cxx
+++ b/sc/source/filter/oox/autofilterbuffer.cxx
@@ -866,6 +866,14 @@ void AutoFilter::finalizeImport( const Reference< 
XDatabaseRange >& rxDatabaseRa
         OSL_FAIL("AutoFilter::finalizeImport(): cannot find matching DBData");
 }
 
+Reference< XDatabaseRange > AutoFilter::createDatabaseObject(sal_Int16 nSheet)
+{
+    ScRange aRangeCopy(maRange);
+    aRangeCopy.aStart.SetTab(nSheet);
+    aRangeCopy.aEnd.SetTab(nSheet);
+    return createUnnamedDatabaseRangeObject( maRange );
+}
+
 AutoFilterBuffer::AutoFilterBuffer( const WorkbookHelper& rHelper ) :
     WorkbookHelper( rHelper )
 {
@@ -880,17 +888,13 @@ AutoFilter& AutoFilterBuffer::createAutoFilter()
 
 void AutoFilterBuffer::finalizeImport( sal_Int16 nSheet )
 {
-    // rely on existence of the defined name '_FilterDatabase' containing the 
range address of the filtered area
-    const DefinedName* pFilterDBName = getDefinedNames().getByBuiltinId( 
BIFF_DEFNAME_FILTERDATABASE, nSheet ).get();
-    if(!pFilterDBName)
-        return;
-
-    ScRange aFilterRange;
-    if( !(pFilterDBName->getAbsoluteRange( aFilterRange ) && 
(aFilterRange.aStart.Tab() == nSheet)) )
+    if (maAutoFilters.empty()) {
         return;
+    }
 
+    std::shared_ptr<AutoFilter> xAutoFilter = maAutoFilters.front();
     // use the same name for the database range as used for the defined name 
'_FilterDatabase'
-    Reference< XDatabaseRange > xDatabaseRange = 
createUnnamedDatabaseRangeObject( aFilterRange );
+    Reference< XDatabaseRange > xDatabaseRange = 
xAutoFilter->createDatabaseObject(nSheet);
     // first, try to create an auto filter
     bool bHasAutoFilter = finalizeImport( xDatabaseRange, nSheet );
     // no success: try to create an advanced filter

Reply via email to