sc: take the error constants from the grammar in use

The formula writer substitutes an error constant for anything that has
no spelling in the target format, and it took that string from the
native symbol table. That table is translated, so a build in another
language wrote a translated "#REF!" into the saved formula, where only
the English spelling reads back. It now takes the string from the
table of the grammar being written, which changes nothing for the
native grammar.

Reading had a gap of its own. The OOXML table had a second "#REF!" row
for the stop opcode, and the symbol map keeps the first spelling it
finds in opcode order, so that row shadowed the error constant and a
bare #REF! read from a file gave #NAME?. Nothing needs a spelling for
the stop opcode, so the row is gone.

Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: Idbe8ce87d6ad6346106622379ff59908a36eb7f7
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/10163
Reviewed-by: Miklos Vajna <vmiklos@collabora.com>
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
(cherry picked from commit 75160522f6a9de4999b824725326475ba8d713f1)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/210313
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
Tested-by: Jenkins
This commit is contained in:
Tomaž Vajngerl
2026-09-01 09:08:38 +02:00
committed by Xisco Fauli
parent 62eced2131
commit d9dcb8a4cc
3 changed files with 23 additions and 4 deletions
-1
View File
@@ -989,7 +989,6 @@ const std::pair<const char *, int> RID_STRLIST_FUNCTION_NAMES_ENGLISH_OOXML[] =
{ "_xlfn.ORG.LIBREOFFICE.RAND.NV" , ocRandomNV },
{ "_xlfn.ORG.LIBREOFFICE.RANDBETWEEN.NV" , ocRandbetweenNV },
{ "_xlfn.RANDARRAY" , ocRandArray },
{ "#REF!", ocStop },
{ "_xludf.", ocUDExternal },
{ nullptr, -1 }
};
+3 -3
View File
@@ -2891,14 +2891,14 @@ bool FormulaCompiler::AppendTokenOrError(OUStringBuffer& rBuffer, const FormulaT
// A call with no name would come out as "#NAME!()", which no reader
// accepts, so the error string replaces the whole formula.
rBuffer.setLength(0);
rBuffer.append(GetNativeSymbol(ocErrRef));
rBuffer.append(mxSymbols->getSymbol(ocErrRef));
return false;
}
if (eOp == ocExternal || eOp == ocPush)
{
// A function token that lost its name. The error string stands in for
// this one token only.
rBuffer.append(GetNativeSymbol(ocErrRef));
rBuffer.append(mxSymbols->getSymbol(ocErrRef));
rpToken = maArrIterator.Next();
return true;
}
@@ -2913,7 +2913,7 @@ bool FormulaCompiler::AppendTokenOrError(OUStringBuffer& rBuffer, const FormulaT
// The error would come out as "#NAME?$C7", which no reader accepts,
// so the error string replaces the whole formula.
rBuffer.setLength(0);
rBuffer.append(GetNativeSymbol(ocErrName));
rBuffer.append(mxSymbols->getSymbol(ocErrName));
return false;
}
}
+20
View File
@@ -7416,6 +7416,26 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testAUnionListPartJoinsWhenItBeginsWithARefer
formula::FormulaGrammar::GRAM_OOXML);
CPPUNIT_ASSERT_EQUAL(300.0, m_pDoc->GetValue(ScAddress(3, 13, 0)));
// An error constant part becomes the result of the union, wherever the blank around the
// separator is.
m_pDoc->SetFormula(ScAddress(3, 14, 0), u"=(A1, #REF!)"_ustr,
formula::FormulaGrammar::GRAM_OOXML);
CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(3, 14, 0)));
m_pDoc->SetFormula(ScAddress(3, 16, 0), u"=(A1 ,#REF!)"_ustr,
formula::FormulaGrammar::GRAM_OOXML);
CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(3, 16, 0)));
// The same list read the way it arrives from a file: no leading equals sign, and the
// implicit intersections worked out during the parse.
{
ScCompiler aCompiler(*m_pDoc, ScAddress(3, 17, 0), formula::FormulaGrammar::GRAM_OOXML,
true, false);
std::unique_ptr<ScTokenArray> pArray = aCompiler.CompileString(u"(A1 ,#REF!)"_ustr);
aCompiler.CompileTokenArray();
m_pDoc->SetFormula(ScAddress(3, 17, 0), *pArray);
CPPUNIT_ASSERT_EQUAL(FormulaError::NoRef, m_pDoc->GetErrCode(ScAddress(3, 17, 0)));
}
// An @ part sits on the reference after it, and a bare list has no value anyway.
m_pDoc->SetFormula(ScAddress(3, 15, 0), u"=(A1, _xlfn.SINGLE(B1))"_ustr,
formula::FormulaGrammar::GRAM_OOXML);