Skip to content

Commit

Permalink
This closes #1565, support adjust formula when instering columns and …
Browse files Browse the repository at this point in the history
…rows (#1567)
  • Loading branch information
lidp20 authored Jul 3, 2023
1 parent 700af6a commit e2c7416
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 3 deletions.
30 changes: 28 additions & 2 deletions adjust.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
}
Expand All @@ -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) {
Expand Down
20 changes: 20 additions & 0 deletions adjust_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
2 changes: 1 addition & 1 deletion rows.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit e2c7416

Please sign in to comment.