sc/qa/unit/data/xlsx/tablerefsnamed.xlsx |binary sc/qa/unit/subsequent_filters_test2.cxx | 15 ++++++++++ sc/source/core/tool/interpr1.cxx | 43 +++++++++++++++++++++++-------- 3 files changed, 48 insertions(+), 10 deletions(-)
New commits: commit 4536694edb7e564ea1f4ae871e9107f52ed0972f 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:07:21 2023 +0200 tdf#155369 ScIndirect: handle names that resolve to... table structured references. Conflicts: sc/qa/unit/subsequent_filters_test2.cxx Change-Id: I897feeeb49e63c1758cf64450799acb192e2d593 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151888 Tested-by: Jenkins 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 cd5f073f46c4..a00558730d0b 100644 --- a/sc/qa/unit/subsequent_filters_test2.cxx +++ b/sc/qa/unit/subsequent_filters_test2.cxx @@ -1565,6 +1565,21 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest2, testBorderDirectionsXLSXML) } } +CPPUNIT_TEST_FIXTURE(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_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 9e2277f60392..2f48398827ed 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -8187,6 +8187,12 @@ void ScInterpreter::ScDBVarP() PushDouble(fVal/fCount); } +static 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(); @@ -8223,6 +8229,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 @@ -8238,8 +8248,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(), @@ -8256,6 +8272,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); @@ -8291,9 +8310,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) { @@ -8305,9 +8325,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) { @@ -8323,8 +8344,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) { @@ -8361,7 +8384,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;