From 3eb431b90eb1f855ae373ff3d8f3b2c5dcb10bf3 Mon Sep 17 00:00:00 2001 From: DrRobotto Date: Tue, 22 Sep 2026 17:15:11 +0200 Subject: [PATCH] tdf#162609 - Do not match error cells against numeric query items Change-Id: I7dea4e56cfbd9516df02b308c5d1e444ac370105 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/211325 Tested-by: Jenkins Reviewed-by: Andreas Heinisch --- sc/qa/unit/ucalc.cxx | 42 ++++++++++++++++++++++++++ sc/source/core/data/queryevaluator.cxx | 4 ++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/sc/qa/unit/ucalc.cxx b/sc/qa/unit/ucalc.cxx index 87be0c5cd500..6d49fedd9142 100644 --- a/sc/qa/unit/ucalc.cxx +++ b/sc/qa/unit/ucalc.cxx @@ -3935,6 +3935,48 @@ CPPUNIT_TEST_FIXTURE(Test, testAutofilterOptimizations) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(Test, testTdf162609_autofilterErrorValue) +{ + m_pDoc->InsertTab(0, u"Test"_ustr); + + // A1 is the header, A2:A11 contain 0-9 and A12 an error. With 10 query items, + // the optimized search would incorrectly match the error cell against the 0. + constexpr sal_Int32 nItems = 10; + m_pDoc->SetString(0, 0, 0, u"Number"_ustr); + for (sal_Int32 i = 0; i < nItems; ++i) + m_pDoc->SetValue(0, i + 1, 0, i); + m_pDoc->SetString(0, nItems + 1, 0, u"=NA()"_ustr); + CPPUNIT_ASSERT_EQUAL(u"#N/A"_ustr, m_pDoc->GetString(0, nItems + 1, 0)); + + ScDBData* pDBData = new ScDBData(u"NONAME"_ustr, 0, 0, 0, 0, nItems + 1); + m_pDoc->SetAnonymousDBData(0, std::unique_ptr(pDBData)); + pDBData->SetAutoFilter(true); + + // Select every value the autofilter offers except the error one + ScQueryParam aParam; + pDBData->GetQueryParam(aParam); + ScQueryEntry& rEntry = aParam.GetEntry(0); + rEntry.bDoQuery = true; + rEntry.nField = 0; + rEntry.eOp = SC_EQUAL; + rEntry.GetQueryItems().resize(nItems); + for (sal_Int32 i = 0; i < nItems; ++i) + { + rEntry.GetQueryItems()[i].mfVal = i; + rEntry.GetQueryItems()[i].maString + = m_pDoc->GetSharedStringPool().intern(OUString::number(i)); + } + pDBData->SetQueryParam(aParam); + m_pDoc->Query(0, aParam, true); + + // Without the fix in place, this test would have failed + // because the row with the error value was not filtered out + CPPUNIT_ASSERT_MESSAGE("row with #N/A should be hidden", m_pDoc->RowHidden(nItems + 1, 0)); + CPPUNIT_ASSERT_MESSAGE("row with 0 should be visible", !m_pDoc->RowHidden(1, 0)); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(Test, testTdf76441) { m_pDoc->InsertTab(0, u"Test"_ustr); diff --git a/sc/source/core/data/queryevaluator.cxx b/sc/source/core/data/queryevaluator.cxx index 4fc793b4d73e..d0d3776413bc 100644 --- a/sc/source/core/data/queryevaluator.cxx +++ b/sc/source/core/data/queryevaluator.cxx @@ -692,10 +692,12 @@ std::pair ScQueryEvaluator::processEntry(SCROW nRow, SCCOL nCol, // For ScQueryEntry::ByValue check that the cell either is a value or is a formula // that has a value and is not an error (those are compared as strings). This // is basically simplified isQueryByValue(). + // tdf#162609 - keep error cells out of the numeric comparison since GetValue() + // returns 0.0 which could match a query item containing 0 if (aCell.getType() == CELLTYPE_VALUE) value = aCell.getDouble(); else if (aCell.getType() == CELLTYPE_FORMULA - && aCell.getFormula()->GetErrCode() != FormulaError::NONE + && aCell.getFormula()->GetErrCode() == FormulaError::NONE && aCell.getFormula()->IsValue()) { value = aCell.getFormula()->GetValue();