sc: import @-wrapped XLSX cells as scalar formulas, not CSE arrays
XLSX tags a cell holding =@(expr) with t="array" ref=<self>,
because the OOXML writer evaluates the @ in array context. The
import path honoured the tag and routed such cells through
setMatrixCells, so GetFormula wrapped the imported text in {}
braces. A user-typed =@(F3:F5+0) came back as {=@(F3:F5+0)},
reading as a CSE array even though @ keeps the cell scalar.
When the t="array" range is a single cell and the parse array
starts with @, construct a plain ScFormulaCell instead of
calling setMatrixCells. The @ collapses the operand, so there
is nothing to spill.
testIntersectionOperatorXlsxRoundTrip loads the fixture and
asserts the @-wrapped cells read back as plain formulas, both
on import and after a round trip.
Signed-off-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.co.uk>
Change-Id: I05020fa2810a8f2d4f0c9374a9a8afc39e2d9e5e
Reviewed-on: https://gerrit.collaboraoffice.com/c/online/+/5536
Tested-by: Tomaž Vajngerl <tomaz.vajngerl@collabora.com>
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
(cherry picked from commit 75eda52e374810561261485ed038e70d9e2edab1)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/207869
Tested-by: Xisco Fauli <xiscofauli@libreoffice.org>
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
committed by
Xisco Fauli
parent
14d723ea36
commit
49e9da81fa
Binary file not shown.
@@ -1680,6 +1680,37 @@ CPPUNIT_TEST_FIXTURE(ScFiltersTest, testCmRoundTripXLSX)
|
||||
CPPUNIT_ASSERT(pMaster);
|
||||
CPPUNIT_ASSERT(pMaster->IsDynamicArrayMaster());
|
||||
}
|
||||
CPPUNIT_TEST_FIXTURE(ScFiltersTest, testIntersectionOperatorXlsxRoundTrip)
|
||||
{
|
||||
// The fixture has A1:A4 = {42, 69, 13, 666} and three cells
|
||||
// that read back the upper-left value 42 through implicit
|
||||
// intersection. All three import as plain formulas, so
|
||||
// GetFormula returns them without {} wrapping. The same shape
|
||||
// survives an XLSX round trip.
|
||||
|
||||
auto assertFormulas = [](ScDocument* pDoc) {
|
||||
// C1: plain =A1:A4 range reference. No t="array" tag, so
|
||||
// the cell collapses through implicit intersection at row 1.
|
||||
CPPUNIT_ASSERT_EQUAL(u"=A1:A4"_ustr, pDoc->GetFormula(2, 0, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(42.0, pDoc->GetValue(ScAddress(2, 0, 0)));
|
||||
|
||||
// D1: t="array" wrapper around (A1:A4+0). The outer paren
|
||||
// pair the writer adds is stripped on import.
|
||||
CPPUNIT_ASSERT_EQUAL(u"=@(A1:A4+0)"_ustr, pDoc->GetFormula(3, 0, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(42.0, pDoc->GetValue(ScAddress(3, 0, 0)));
|
||||
|
||||
// E1: t="array" wrapper around TRANSPOSE(A1:A4). The
|
||||
// argument is a function call, so no outer paren strip.
|
||||
CPPUNIT_ASSERT_EQUAL(u"=@(TRANSPOSE(A1:A4))"_ustr, pDoc->GetFormula(4, 0, 0));
|
||||
CPPUNIT_ASSERT_EQUAL(42.0, pDoc->GetValue(ScAddress(4, 0, 0)));
|
||||
};
|
||||
|
||||
createScDoc("xlsx/IntersectionOperatorFixture.xlsx");
|
||||
assertFormulas(getScDoc());
|
||||
|
||||
saveAndReload(TestFilter::XLSX);
|
||||
assertFormulas(getScDoc());
|
||||
}
|
||||
|
||||
CPPUNIT_TEST_FIXTURE(ScFiltersTest, testArrayFormulaSpillXLSX)
|
||||
{
|
||||
|
||||
@@ -381,6 +381,25 @@ void applyArrayFormulas(
|
||||
if (pArray)
|
||||
{
|
||||
lcl_stripRedundantParentheses(*pArray, {ocSingleValue});
|
||||
|
||||
// A single-cell t="array" that starts with @ imports as
|
||||
// a plain ScFormulaCell, not a CSE array. The @ collapses
|
||||
// the operand to a scalar, so the cell reads back as
|
||||
// =@(expr) instead of {=@(expr)}.
|
||||
const sal_uInt16 nParseLength = pArray->GetLen();
|
||||
const formula::FormulaToken* pFirst = nParseLength ? pArray->GetArray()[0] : nullptr;
|
||||
const bool bSingleCellRange
|
||||
= rAddressItem.maRange.aStart == rAddressItem.maRange.aEnd;
|
||||
if (bSingleCellRange && pFirst
|
||||
&& pFirst->GetOpCode() == ocSingleValue)
|
||||
{
|
||||
aComp.CompileTokenArray();
|
||||
ScFormulaCell* pCell = new ScFormulaCell(rDoc.getDoc(), aPos,
|
||||
std::move(pArray));
|
||||
rDoc.setFormulaCell(aPos, pCell);
|
||||
continue;
|
||||
}
|
||||
|
||||
rDoc.setMatrixCells(rAddressItem.maRange, *pArray,
|
||||
formula::FormulaGrammar::GRAM_OOXML,
|
||||
rAddressItem.mbCachedSpill);
|
||||
|
||||
Reference in New Issue
Block a user