summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorDennis Francis <dennis.francis@collabora.com>2023-05-13 13:37:39 +0530
committerDennis Francis <dennis.francis@collabora.com>2023-05-20 17:06:40 +0200
commit49d6567a196f4bfafb45b07b1b88e7c00c134bfd (patch)
tree1fbd6c34bd95c7a552ec465c6bd193c7c8d611ee /sc
parent5ac21f4914d80c76fdfe6610d59adab0d756265b (diff)
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 <jenkinscollaboraoffice@gmail.com> Reviewed-by: Dennis Francis <dennis.francis@collabora.com>
Diffstat (limited to 'sc')
-rw-r--r--sc/qa/unit/data/xlsx/tablerefsnamed.xlsxbin0 -> 10387 bytes
-rw-r--r--sc/qa/unit/subsequent_filters_test2.cxx17
-rw-r--r--sc/source/core/tool/interpr1.cxx43
3 files changed, 50 insertions, 10 deletions
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
--- /dev/null
+++ b/sc/qa/unit/data/xlsx/tablerefsnamed.xlsx
Binary files 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;