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.francis@collabora.com>
Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152083
diff --git a/sc/qa/unit/data/xlsx/tablerefsnamed.xlsx b/sc/qa/unit/data/xlsx/tablerefsnamed.xlsx
new file mode 100644
index 0000000..825103d
--- /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 da79b48..177fcc7 100644
--- a/sc/qa/unit/subsequent_filters_test2.cxx
+++ b/sc/qa/unit/subsequent_filters_test2.cxx
@@ -190,6 +190,7 @@ public:
void testTdf83671_SmartArt_import();
void testTdf83671_SmartArt_import2();
void testTdf151818_SmartArtFontColor();
void testNamedTableRef();
CPPUNIT_TEST_SUITE(ScFiltersTest2);
@@ -310,6 +311,7 @@ public:
CPPUNIT_TEST(testTdf83671_SmartArt_import);
CPPUNIT_TEST(testTdf83671_SmartArt_import2);
CPPUNIT_TEST(testTdf151818_SmartArtFontColor);
CPPUNIT_TEST(testNamedTableRef);
CPPUNIT_TEST_SUITE_END();
};
@@ -3035,6 +3037,21 @@ void ScFiltersTest2::testTdf151818_SmartArtFontColor()
}
}
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 b833e3f..32ec733 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);
}
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();
@@ -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;