@@ -185,6 +185,21 @@ func TestRecalcWorkbookWithoutFormulas(t *testing.T) {
185185 assert .NoError (t , f .Recalc ())
186186}
187187
188+ func TestRecalcRejectsChartSheet (t * testing.T ) {
189+ f := NewFile ()
190+ assert .NoError (t , f .SetCellInt ("Sheet1" , "A1" , 1 ))
191+ assert .NoError (t , f .SetCellInt ("Sheet1" , "A2" , 2 ))
192+ assert .NoError (t , f .AddChartSheet ("Chart1" , & Chart {
193+ Type : Col ,
194+ Series : []ChartSeries {{
195+ Categories : "Sheet1!$A$1:$A$2" ,
196+ Values : "Sheet1!$A$1:$A$2" ,
197+ }},
198+ }))
199+
200+ assert .Error (t , f .Recalc (RecalcOptions {Sheet : "Chart1" }))
201+ }
202+
188203func TestRecalcAggregatesFailures (t * testing.T ) {
189204 // An unsupported function on one cell must not prevent other cells
190205 // from being recalculated. The returned error is the join of
@@ -240,7 +255,7 @@ func TestRecalcRefScope(t *testing.T) {
240255 assert .NoError (t , f .Recalc (RecalcOptions {Sheet : "Sheet1" , Ref : "A1:A10" }))
241256
242257 assert .Equal (t , "2" , cellXML (t , f , "Sheet1" , "A2" ).V )
243- assert .Empty (t , cellXML (t , f , "Sheet1" , "B2" ).V , "B2 out of scope " )
258+ assert .Empty (t , cellXML (t , f , "Sheet1" , "B2" ).V , "B2 cache remains empty " )
244259}
245260
246261func TestRecalcOptionRejects (t * testing.T ) {
@@ -249,3 +264,53 @@ func TestRecalcOptionRejects(t *testing.T) {
249264 assert .ErrorContains (t , f .Recalc (RecalcOptions {Sheet : "Nope" }), `"Nope"` )
250265 assert .ErrorContains (t , f .Recalc (RecalcOptions {Sheet : "Sheet1" , Ref : "not-a-range" }), "invalid Ref" )
251266}
267+
268+ func TestCollectRecalcCellsSkipsMalformedCellReference (t * testing.T ) {
269+ f := NewFile ()
270+ assert .NoError (t , f .SetCellFormula ("Sheet1" , "A1" , "1+1" ))
271+ assert .NoError (t , f .SetCellFormula ("Sheet1" , "B1" , "2+2" ))
272+ ws , err := f .workSheetReader ("Sheet1" )
273+ assert .NoError (t , err )
274+ ws .SheetData .Row [0 ].C [0 ].R = "bad-ref"
275+
276+ cells , err := f .collectRecalcCells (RecalcOptions {Sheet : "Sheet1" })
277+ assert .NoError (t , err )
278+ assert .Equal (t , []recalcTarget {{sheet : "Sheet1" , cell : "B1" }}, cells )
279+ }
280+
281+ func TestSetCellCachedValueRejectsBadTarget (t * testing.T ) {
282+ f := NewFile ()
283+
284+ assert .Error (t , f .setCellCachedValue ("Nope" , "A1" , newNumberFormulaArg (1 )))
285+ assert .Error (t , f .setCellCachedValue ("Sheet1" , "bad-ref" , newNumberFormulaArg (1 )))
286+ }
287+
288+ func TestSetCachedArgTypes (t * testing.T ) {
289+ cases := []struct {
290+ name string
291+ arg formulaArg
292+ wantT string
293+ wantV string
294+ }{
295+ {"string" , newStringFormulaArg ("ready" ), "str" , "ready" },
296+ {"formula_error" , newErrorFormulaArg (formulaErrorVALUE , formulaErrorVALUE ), "e" , formulaErrorVALUE },
297+ {"empty" , newEmptyFormulaArg (), "" , "" },
298+ {"unknown" , formulaArg {Type : ArgUnknown }, "" , "" },
299+ {"matrix_scalar_head" , newMatrixFormulaArg ([][]formulaArg {{newStringFormulaArg ("top" )}}), "str" , "top" },
300+ {"matrix_nested_head" , newMatrixFormulaArg ([][]formulaArg {{newMatrixFormulaArg ([][]formulaArg {{newNumberFormulaArg (1 )}})}}), "" , "" },
301+ {"list_scalar_head" , newListFormulaArg ([]formulaArg {newNumberFormulaArg (12 )}), "" , "12" },
302+ {"list_nested_head" , newListFormulaArg ([]formulaArg {newListFormulaArg ([]formulaArg {newNumberFormulaArg (2 )})}), "" , "" },
303+ {"list_empty" , newListFormulaArg (nil ), "" , "" },
304+ }
305+ for _ , tc := range cases {
306+ t .Run (tc .name , func (t * testing.T ) {
307+ c := & xlsxC {T : "inlineStr" , V : "stale" , IS : & xlsxSI {}}
308+
309+ setCachedArg (c , tc .arg )
310+
311+ assert .Nil (t , c .IS )
312+ assert .Equal (t , tc .wantT , c .T )
313+ assert .Equal (t , tc .wantV , c .V )
314+ })
315+ }
316+ }
0 commit comments