diff --git a/sc/qa/unit/ucalc_formula2.cxx b/sc/qa/unit/ucalc_formula2.cxx index dff1ad66acdc..ea3e84bc6a5c 100644 --- a/sc/qa/unit/ucalc_formula2.cxx +++ b/sc/qa/unit/ucalc_formula2.cxx @@ -6468,6 +6468,32 @@ CPPUNIT_TEST_FIXTURE(TestFormula2, testCallableWhereNumberExpected) m_pDoc->DeleteTab(0); } +CPPUNIT_TEST_FIXTURE(TestFormula2, testAtFormulaIgnoresDynamicArrayMasterFlag) +{ + // An @-prefixed formula opts out of dynamic-array spilling. + // SetDynamicArrayMaster ignores a request to enable the flag on + // such a cell, so an OOXML cm="1" arriving on an @-cell does not + // turn into a #SPILL! at interpret time. + + sc::AutoCalcSwitch aACSwitch(*m_pDoc, true); + m_pDoc->InsertTab(0, u"Sheet1"_ustr); + + m_pDoc->SetValue(ScAddress(0, 0, 0), 1.0); + m_pDoc->SetValue(ScAddress(0, 1, 0), 2.0); + m_pDoc->SetValue(ScAddress(0, 2, 0), 3.0); + + m_pDoc->SetFormula(ScAddress(1, 0, 0), u"=@(A1:A3+0)"_ustr, + formula::FormulaGrammar::GRAM_NATIVE); + ScFormulaCell* pCell = m_pDoc->GetFormulaCell(ScAddress(1, 0, 0)); + CPPUNIT_ASSERT(pCell); + + pCell->SetDynamicArrayMaster(true); + CPPUNIT_ASSERT(!pCell->IsDynamicArrayMaster()); + CPPUNIT_ASSERT_EQUAL(1.0, m_pDoc->GetValue(ScAddress(1, 0, 0))); + + m_pDoc->DeleteTab(0); +} + CPPUNIT_TEST_FIXTURE(TestFormula2, testMatrixConcatRendersBooleansAsTrueFalse) { // A boolean value pulled into a string context renders as the diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index 34c969a343f7..264cb573d8a5 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -2731,6 +2731,13 @@ void ScFormulaCell::SetCompile( bool bVal ) void ScFormulaCell::SetDynamicArrayMaster(bool bDynamic) { + // A formula with @ on top of its RPN opts out of dynamic-array + // spilling: the operator collapses any array operand to a single + // value, so there is nothing to spill. XLSX still emits the cm="1" + // marker on such cells, so reject the request rather than letting + // the spill check fire against a 1x1 declared matrix. + if (bDynamic && pCode && rpnTopIsImplicitIntersection(*pCode)) + return; mbDynamicArrayMaster = bDynamic; // A plain single-cell formula that opts into the dynamic-array flag // becomes a 1x1 matrix master so the first interpret can expand it