From e2c74162925c7dc7e87c8818b0b83cf4dd3dbc40 Mon Sep 17 00:00:00 2001 From: lidp20 <1697871629@qq.com> Date: Tue, 4 Jul 2023 00:06:37 +0800 Subject: [PATCH] This closes #1565, support adjust formula when instering columns and rows (#1567) --- adjust.go | 30 ++++++++++++++++++++++++++++-- adjust_test.go | 20 ++++++++++++++++++++ rows.go | 2 +- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/adjust.go b/adjust.go index 7fc9faa4..5f408979 100644 --- a/adjust.go +++ b/adjust.go @@ -131,6 +131,7 @@ func (f *File) adjustColDimensions(ws *xlsxWorksheet, col, offset int) error { if cellCol, cellRow, _ := CellNameToCoordinates(v.R); col <= cellCol { if newCol := cellCol + offset; newCol > 0 { ws.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow) + _ = f.adjustFormula(ws.SheetData.Row[rowIdx].C[colIdx].F, columns, offset, false) } } } @@ -152,21 +153,46 @@ func (f *File) adjustRowDimensions(ws *xlsxWorksheet, row, offset int) error { for i := 0; i < len(ws.SheetData.Row); i++ { r := &ws.SheetData.Row[i] if newRow := r.R + offset; r.R >= row && newRow > 0 { - f.adjustSingleRowDimensions(r, newRow) + f.adjustSingleRowDimensions(r, newRow, offset, false) } } return nil } // adjustSingleRowDimensions provides a function to adjust single row dimensions. -func (f *File) adjustSingleRowDimensions(r *xlsxRow, num int) { +func (f *File) adjustSingleRowDimensions(r *xlsxRow, num, offset int, si bool) { r.R = num for i, col := range r.C { colName, _, _ := SplitCellName(col.R) r.C[i].R, _ = JoinCellName(colName, num) + _ = f.adjustFormula(col.F, rows, offset, si) } } +// adjustFormula provides a function to adjust shared formula reference. +func (f *File) adjustFormula(formula *xlsxF, dir adjustDirection, offset int, si bool) error { + if formula != nil && formula.Ref != "" { + coordinates, err := rangeRefToCoordinates(formula.Ref) + if err != nil { + return err + } + if dir == columns { + coordinates[0] += offset + coordinates[2] += offset + } else { + coordinates[1] += offset + coordinates[3] += offset + } + if formula.Ref, err = f.coordinatesToRangeRef(coordinates); err != nil { + return err + } + if si && formula.Si != nil { + formula.Si = intPtr(*formula.Si + 1) + } + } + return nil +} + // adjustHyperlinks provides a function to update hyperlinks when inserting or // deleting rows or columns. func (f *File) adjustHyperlinks(ws *xlsxWorksheet, sheet string, dir adjustDirection, num, offset int) { diff --git a/adjust_test.go b/adjust_test.go index c90a3f5c..f6147e64 100644 --- a/adjust_test.go +++ b/adjust_test.go @@ -445,3 +445,23 @@ func TestAdjustCols(t *testing.T) { assert.NoError(t, f.Close()) } + +func TestAdjustFormula(t *testing.T) { + f := NewFile() + formulaType, ref := STCellFormulaTypeShared, "C1:C5" + assert.NoError(t, f.SetCellFormula("Sheet1", "C1", "=A1+B1", FormulaOpts{Ref: &ref, Type: &formulaType})) + assert.NoError(t, f.DuplicateRowTo("Sheet1", 1, 10)) + assert.NoError(t, f.InsertCols("Sheet1", "B", 1)) + assert.NoError(t, f.InsertRows("Sheet1", 1, 1)) + for cell, expected := range map[string]string{"D2": "=A1+B1", "D3": "=A2+B2", "D11": "=A1+B1"} { + formula, err := f.GetCellFormula("Sheet1", cell) + assert.NoError(t, err) + assert.Equal(t, expected, formula) + } + assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustFormula.xlsx"))) + assert.NoError(t, f.Close()) + + assert.NoError(t, f.adjustFormula(nil, rows, 0, false)) + assert.Equal(t, f.adjustFormula(&xlsxF{Ref: "-"}, rows, 0, false), ErrParameterInvalid) + assert.Equal(t, f.adjustFormula(&xlsxF{Ref: "XFD1:XFD1"}, columns, 1, false), ErrColumnNumber) +} diff --git a/rows.go b/rows.go index 7351d160..332bedda 100644 --- a/rows.go +++ b/rows.go @@ -662,7 +662,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error { } rowCopy.C = append(make([]xlsxC, 0, len(rowCopy.C)), rowCopy.C...) - f.adjustSingleRowDimensions(&rowCopy, row2) + f.adjustSingleRowDimensions(&rowCopy, row2, row2-row, true) if idx2 != -1 { ws.SheetData.Row[idx2] = rowCopy