sc/qa/unit/data/xlsx/tablerefsnamed.xlsx |binary sc/qa/unit/subsequent_filters_test2.cxx | 17 ++++++++++++ sc/source/core/tool/interpr1.cxx | 43 +++++++++++++++++++++++-------- 3 files changed, 50 insertions(+), 10 deletions(-)
New commits: commit 49d6567a196f4bfafb45b07b1b88e7c00c134bfd Author: Dennis Francis <dennis.fran...@collabora.com> AuthorDate: Sat May 13 13:37:39 2023 +0530 Commit: Dennis Francis <dennis.fran...@collabora.com> CommitDate: Sat May 20 17:06:40 2023 +0200 tdf#155369 ScIndirect: handle names that resolve to... table structured references. Change-Id: I897feeeb49e63c1758cf64450799acb192e2d593 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151720 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Dennis Francis <dennis.fran...@collabora.com> diff --git a/sc/qa/unit/data/xlsx/tablerefsnamed.xlsx b/sc/qa/unit/data/xlsx/tablerefsnamed.xlsx new file mode 100644 index 000000000000..825103d54993 Binary files /dev/null and b/sc/qa/unit/data/xlsx/tablerefsnamed.xlsx differ diff --git a/sc/qa/unit/subsequent_filters_test2.cxx b/sc/qa/unit/subsequent_filters_test2.cxx index 850026d3bc46..f2fd4196dfa1 100644 --- a/sc/qa/unit/subsequent_filters_test2.cxx +++ b/sc/qa/unit/subsequent_filters_test2.cxx @@ -192,6 +192,7 @@ public: void testTdf151818_SmartArtFontColor(); void testTdf82984_zip64XLSXImport(); void testSingleLine(); + void testNamedTableRef(); CPPUNIT_TEST_SUITE(ScFiltersTest2); @@ -314,6 +315,7 @@ public: CPPUNIT_TEST(testTdf151818_SmartArtFontColor); CPPUNIT_TEST(testTdf82984_zip64XLSXImport); CPPUNIT_TEST(testSingleLine); + CPPUNIT_TEST(testNamedTableRef); CPPUNIT_TEST_SUITE_END(); }; @@ -3078,6 +3080,21 @@ void ScFiltersTest2::testSingleLine() testCells(pDoc); } +void ScFiltersTest2::testNamedTableRef() +{ + createScDoc("xlsx/tablerefsnamed.xlsx"); + ScDocument* pDoc = getScDoc(); + for (sal_Int32 nRow = 1; nRow < 7; ++nRow) + { + ScFormulaCell* pFC = pDoc->GetFormulaCell(ScAddress(5, nRow, 0)); + CPPUNIT_ASSERT(pFC); + // Without the fix there will be #REF in F2:F7. + CPPUNIT_ASSERT_EQUAL(FormulaError::NONE, pFC->GetErrCode()); + // Without the fix value will be 0 (FALSE). + CPPUNIT_ASSERT_EQUAL(1.0, pDoc->GetValue(ScAddress(6, nRow, 0))); + } +} + CPPUNIT_TEST_SUITE_REGISTRATION(ScFiltersTest2); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index b833e3f48f24..7283002f328d 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -8181,6 +8181,12 @@ void ScInterpreter::ScDBVarP() PushDouble(fVal/fCount); } +bool lcl_IsTableStructuredRef(const OUString& sRefStr, sal_Int32& nIndex) +{ + nIndex = ScGlobal::FindUnquoted(sRefStr, '['); + return (nIndex > 0 && ScGlobal::FindUnquoted(sRefStr, ']', nIndex + 1) > nIndex); +} + void ScInterpreter::ScIndirect() { sal_uInt8 nParamCount = GetByte(); @@ -8217,6 +8223,10 @@ void ScInterpreter::ScIndirect() const ScAddress::Details aDetailsXlA1( FormulaGrammar::CONV_XL_A1, aPos ); SCTAB nTab = aPos.Tab(); + bool bTableRefNamed = false; + sal_Int32 nTableRefNamedIndex = -1; + OUString sTabRefStr; + // Named expressions and DB range names need to be tried first, as older 1K // columns allowed names that would now match a 16k columns cell address. do @@ -8232,8 +8242,14 @@ void ScInterpreter::ScIndirect() // This is the usual way to treat named ranges containing // relative references. - if (!pData->IsReference( aRange, aPos)) + if (!pData->IsReference(aRange, aPos)) + { + sTabRefStr = pData->GetSymbol(); + bTableRefNamed = lcl_IsTableStructuredRef(sTabRefStr, nTableRefNamedIndex); + // if bTableRefNamed is true, we have a name that maps to a table structured reference. + // Such a case is handled below. break; + } if (aRange.aStart == aRange.aEnd) PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(), @@ -8250,6 +8266,9 @@ void ScInterpreter::ScIndirect() do { + if (bTableRefNamed) + break; + const OUString & aName( sSharedRefStr.getIgnoreCaseString() ); ScDBCollection::NamedDBs& rDBs = mrDoc.GetDBCollection()->getNamedDBs(); const ScDBData* pData = rDBs.findByUpperName( aName); @@ -8285,9 +8304,10 @@ void ScInterpreter::ScIndirect() ScRefAddress aRefAd, aRefAd2; ScAddress::ExternalInfo aExtInfo; - if ( ConvertDoubleRef(mrDoc, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) || - ( bTryXlA1 && ConvertDoubleRef(mrDoc, sRefStr, nTab, aRefAd, - aRefAd2, aDetailsXlA1, &aExtInfo) ) ) + if ( !bTableRefNamed && + (ConvertDoubleRef(mrDoc, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) || + ( bTryXlA1 && ConvertDoubleRef(mrDoc, sRefStr, nTab, aRefAd, + aRefAd2, aDetailsXlA1, &aExtInfo) ) ) ) { if (aExtInfo.mbExternal) { @@ -8299,9 +8319,10 @@ void ScInterpreter::ScIndirect() else PushDoubleRef( aRefAd, aRefAd2); } - else if ( ConvertSingleRef(mrDoc, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) || - ( bTryXlA1 && ConvertSingleRef (mrDoc, sRefStr, nTab, aRefAd, - aDetailsXlA1, &aExtInfo) ) ) + else if ( !bTableRefNamed && + (ConvertSingleRef(mrDoc, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) || + ( bTryXlA1 && ConvertSingleRef (mrDoc, sRefStr, nTab, aRefAd, + aDetailsXlA1, &aExtInfo) ) ) ) { if (aExtInfo.mbExternal) { @@ -8317,8 +8338,10 @@ void ScInterpreter::ScIndirect() // Anything else that resolves to one reference could be added // here, but we don't want to compile every arbitrary string. This // is already nasty enough... - sal_Int32 nIndex = ScGlobal::FindUnquoted( sRefStr, '['); - const bool bTableRef = (nIndex > 0 && ScGlobal::FindUnquoted( sRefStr, ']', nIndex+1) > nIndex); + sal_Int32 nIndex = bTableRefNamed ? nTableRefNamedIndex : -1; + bool bTableRef = bTableRefNamed; + if (!bTableRefNamed) + bTableRef = lcl_IsTableStructuredRef(sRefStr, nIndex); bool bExternalName = false; // External references would had been consumed above already. if (!bTableRef) { @@ -8355,7 +8378,7 @@ void ScInterpreter::ScIndirect() { ScCompiler aComp( mrDoc, aPos, mrDoc.GetGrammar()); aComp.SetRefConvention( eConv); // must be after grammar - std::unique_ptr<ScTokenArray> pTokArr( aComp.CompileString( sRefStr)); + std::unique_ptr<ScTokenArray> pTokArr( aComp.CompileString(bTableRefNamed ? sTabRefStr : sRefStr)); if (pTokArr->GetCodeError() != FormulaError::NONE || !pTokArr->GetLen()) break;