From 4f66fada43cf50767066c756def7eb39654e376b Mon Sep 17 00:00:00 2001 From: Eike Rathke Date: Mon, 19 Sep 2022 12:29:34 +0200 Subject: Resolves: tdf#151046 INDIRECT() try named expressions and DB range names first ... as older 1K columns allowed names that would now match a 16k columns cell address, which ConvertSingleRef() would already resolve. Change-Id: I9322732e554da20c81856c0a30c41a246356f65b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140147 Reviewed-by: Eike Rathke Tested-by: Jenkins (cherry picked from commit cc28ea4c4483df1643154adc50bd537e35fabb05) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/140154 Reviewed-by: Xisco Fauli --- sc/source/core/tool/interpr1.cxx | 130 ++++++++++++++++++++------------------- 1 file changed, 66 insertions(+), 64 deletions(-) diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 25f334d6835d..e09620605d35 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -8190,6 +8190,72 @@ void ScInterpreter::ScIndirect() const ScAddress::Details aDetailsXlA1( FormulaGrammar::CONV_XL_A1, aPos ); SCTAB nTab = aPos.Tab(); + // 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 + { + ScRangeData* pData = ScRangeStringConverter::GetRangeDataFromString( sRefStr, nTab, mrDoc, eConv); + if (!pData) + break; + + // We need this in order to obtain a good range. + pData->ValidateTabRefs(); + + ScRange aRange; + + // This is the usual way to treat named ranges containing + // relative references. + if (!pData->IsReference( aRange, aPos)) + break; + + if (aRange.aStart == aRange.aEnd) + PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab()); + else + PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), aRange.aEnd.Col(), + aRange.aEnd.Row(), aRange.aEnd.Tab()); + + // success! + return; + } + while (false); + + do + { + OUString aName( ScGlobal::getCharClass().uppercase( sRefStr)); + ScDBCollection::NamedDBs& rDBs = mrDoc.GetDBCollection()->getNamedDBs(); + const ScDBData* pData = rDBs.findByUpperName( aName); + if (!pData) + break; + + ScRange aRange; + pData->GetArea( aRange); + + // In Excel, specifying a table name without [] resolves to the + // same as with [], a range that excludes header and totals + // rows and contains only data rows. Do the same. + if (pData->HasHeader()) + aRange.aStart.IncRow(); + if (pData->HasTotals()) + aRange.aEnd.IncRow(-1); + + if (aRange.aStart.Row() > aRange.aEnd.Row()) + break; + + if (aRange.aStart == aRange.aEnd) + PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab()); + else + PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), aRange.aEnd.Col(), + aRange.aEnd.Row(), aRange.aEnd.Tab()); + + // success! + return; + } + while (false); + ScRefAddress aRefAd, aRefAd2; ScAddress::ExternalInfo aExtInfo; if ( ConvertDoubleRef(mrDoc, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) || @@ -8220,70 +8286,6 @@ void ScInterpreter::ScIndirect() } else { - do - { - ScRangeData* pData = ScRangeStringConverter::GetRangeDataFromString( sRefStr, nTab, mrDoc, eConv); - if (!pData) - break; - - // We need this in order to obtain a good range. - pData->ValidateTabRefs(); - - ScRange aRange; - - // This is the usual way to treat named ranges containing - // relative references. - if (!pData->IsReference( aRange, aPos)) - break; - - if (aRange.aStart == aRange.aEnd) - PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aStart.Tab()); - else - PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aStart.Tab(), aRange.aEnd.Col(), - aRange.aEnd.Row(), aRange.aEnd.Tab()); - - // success! - return; - } - while (false); - - do - { - OUString aName( ScGlobal::getCharClass().uppercase( sRefStr)); - ScDBCollection::NamedDBs& rDBs = mrDoc.GetDBCollection()->getNamedDBs(); - const ScDBData* pData = rDBs.findByUpperName( aName); - if (!pData) - break; - - ScRange aRange; - pData->GetArea( aRange); - - // In Excel, specifying a table name without [] resolves to the - // same as with [], a range that excludes header and totals - // rows and contains only data rows. Do the same. - if (pData->HasHeader()) - aRange.aStart.IncRow(); - if (pData->HasTotals()) - aRange.aEnd.IncRow(-1); - - if (aRange.aStart.Row() > aRange.aEnd.Row()) - break; - - if (aRange.aStart == aRange.aEnd) - PushSingleRef( aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aStart.Tab()); - else - PushDoubleRef( aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aStart.Tab(), aRange.aEnd.Col(), - aRange.aEnd.Row(), aRange.aEnd.Tab()); - - // success! - return; - } - while (false); - // It may be even a TableRef or an external name. // Anything else that resolves to one reference could be added // here, but we don't want to compile every arbitrary string. This -- cgit