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;

Reply via email to