Support adjust formula for entire cols/rows reference (#1702)
- Update the unit tests
This commit is contained in:
parent
a8cbcfa39b
commit
cf3e0164d9
206
adjust.go
206
adjust.go
|
@ -15,6 +15,7 @@ import (
|
|||
"bytes"
|
||||
"encoding/xml"
|
||||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/xuri/efp"
|
||||
|
@ -154,23 +155,31 @@ func (f *File) adjustRowDimensions(sheet string, ws *xlsxWorksheet, row, offset
|
|||
if newRow := lastRow.R + offset; lastRow.R >= row && newRow > 0 && newRow > TotalRows {
|
||||
return ErrMaxRows
|
||||
}
|
||||
for i := 0; i < len(ws.SheetData.Row); i++ {
|
||||
numOfRows := len(ws.SheetData.Row)
|
||||
for i := 0; i < numOfRows; i++ {
|
||||
r := &ws.SheetData.Row[i]
|
||||
if newRow := r.R + offset; r.R >= row && newRow > 0 {
|
||||
if err := f.adjustSingleRowDimensions(sheet, r, row, offset, false); err != nil {
|
||||
return err
|
||||
}
|
||||
r.adjustSingleRowDimensions(offset)
|
||||
}
|
||||
if err := f.adjustSingleRowFormulas(sheet, r, row, offset, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// adjustSingleRowDimensions provides a function to adjust single row dimensions.
|
||||
func (f *File) adjustSingleRowDimensions(sheet string, r *xlsxRow, num, offset int, si bool) error {
|
||||
func (r *xlsxRow) adjustSingleRowDimensions(offset int) {
|
||||
r.R += offset
|
||||
for i, col := range r.C {
|
||||
colName, _, _ := SplitCellName(col.R)
|
||||
r.C[i].R, _ = JoinCellName(colName, r.R)
|
||||
}
|
||||
}
|
||||
|
||||
// adjustSingleRowFormulas provides a function to adjust single row formulas.
|
||||
func (f *File) adjustSingleRowFormulas(sheet string, r *xlsxRow, num, offset int, si bool) error {
|
||||
for _, col := range r.C {
|
||||
if err := f.adjustFormula(sheet, col.F, rows, num, offset, si); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -178,54 +187,151 @@ func (f *File) adjustSingleRowDimensions(sheet string, r *xlsxRow, num, offset i
|
|||
return nil
|
||||
}
|
||||
|
||||
// adjustCellRef provides a function to adjust cell reference.
|
||||
func (f *File) adjustCellRef(ref string, dir adjustDirection, num, offset int) (string, error) {
|
||||
if !strings.Contains(ref, ":") {
|
||||
ref += ":" + ref
|
||||
}
|
||||
coordinates, err := rangeRefToCoordinates(ref)
|
||||
if err != nil {
|
||||
return ref, err
|
||||
}
|
||||
if dir == columns {
|
||||
if coordinates[0] >= num {
|
||||
coordinates[0] += offset
|
||||
}
|
||||
if coordinates[2] >= num {
|
||||
coordinates[2] += offset
|
||||
}
|
||||
} else {
|
||||
if coordinates[1] >= num {
|
||||
coordinates[1] += offset
|
||||
}
|
||||
if coordinates[3] >= num {
|
||||
coordinates[3] += offset
|
||||
}
|
||||
}
|
||||
return f.coordinatesToRangeRef(coordinates)
|
||||
}
|
||||
|
||||
// adjustFormula provides a function to adjust formula reference and shared
|
||||
// formula reference.
|
||||
func (f *File) adjustFormula(sheet string, formula *xlsxF, dir adjustDirection, num, offset int, si bool) error {
|
||||
if formula == nil {
|
||||
return nil
|
||||
}
|
||||
adjustRef := func(ref string) (string, error) {
|
||||
coordinates, err := rangeRefToCoordinates(ref)
|
||||
if err != nil {
|
||||
return ref, err
|
||||
}
|
||||
if dir == columns {
|
||||
coordinates[0] += offset
|
||||
coordinates[2] += offset
|
||||
} else {
|
||||
coordinates[1] += offset
|
||||
coordinates[3] += offset
|
||||
}
|
||||
return f.coordinatesToRangeRef(coordinates)
|
||||
}
|
||||
var err error
|
||||
if formula.Ref != "" {
|
||||
if formula.Ref, err = adjustRef(formula.Ref); err != nil {
|
||||
if formula.Ref, err = f.adjustCellRef(formula.Ref, dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
if si && formula.Si != nil {
|
||||
formula.Si = intPtr(*formula.Si + 1)
|
||||
}
|
||||
}
|
||||
if formula.T == STCellFormulaTypeArray {
|
||||
formula.Content, err = adjustRef(strings.TrimPrefix(formula.Content, "="))
|
||||
return err
|
||||
}
|
||||
if formula.Content != "" && !strings.ContainsAny(formula.Content, "[:]") {
|
||||
content, err := f.adjustFormulaRef(sheet, formula.Content, dir, num, offset)
|
||||
if err != nil {
|
||||
if formula.Content != "" {
|
||||
if formula.Content, err = f.adjustFormulaRef(sheet, formula.Content, dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
formula.Content = content
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// adjustFormulaRef returns adjusted formula text by giving adjusting direction
|
||||
// and the base number of column or row, and offset.
|
||||
func (f *File) adjustFormulaRef(sheet string, text string, dir adjustDirection, num, offset int) (string, error) {
|
||||
// isFunctionStop provides a function to check if token is a function stop.
|
||||
func isFunctionStop(token efp.Token) bool {
|
||||
return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStop
|
||||
}
|
||||
|
||||
// isFunctionStart provides a function to check if token is a function start.
|
||||
func isFunctionStart(token efp.Token) bool {
|
||||
return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStart
|
||||
}
|
||||
|
||||
// adjustFormulaColumnName adjust column name in the formula reference.
|
||||
func adjustFormulaColumnName(name string, dir adjustDirection, num, offset int) (string, error) {
|
||||
if name == "" {
|
||||
return name, nil
|
||||
}
|
||||
col, err := ColumnNameToNumber(name)
|
||||
if err != nil {
|
||||
return name, err
|
||||
}
|
||||
if dir == columns && col >= num {
|
||||
col += offset
|
||||
return ColumnNumberToName(col)
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// adjustFormulaRowNumber adjust row number in the formula reference.
|
||||
func adjustFormulaRowNumber(name string, dir adjustDirection, num, offset int) (string, error) {
|
||||
if name == "" {
|
||||
return name, nil
|
||||
}
|
||||
row, _ := strconv.Atoi(name)
|
||||
if dir == rows && row >= num {
|
||||
row += offset
|
||||
if row > TotalRows {
|
||||
return name, ErrMaxRows
|
||||
}
|
||||
return strconv.Itoa(row), nil
|
||||
}
|
||||
return name, nil
|
||||
}
|
||||
|
||||
// adjustFormulaOperand adjust range operand tokens for the formula.
|
||||
func (f *File) adjustFormulaOperand(token efp.Token, dir adjustDirection, num int, offset int) (string, error) {
|
||||
var col, row, operand string
|
||||
for _, r := range token.TValue {
|
||||
if ('A' <= r && r <= 'Z') || ('a' <= r && r <= 'z') {
|
||||
col += string(r)
|
||||
continue
|
||||
}
|
||||
if '0' <= r && r <= '9' {
|
||||
row += string(r)
|
||||
if col != "" {
|
||||
name, err := adjustFormulaColumnName(col, dir, num, offset)
|
||||
if err != nil {
|
||||
return operand, err
|
||||
}
|
||||
operand += name
|
||||
col = ""
|
||||
}
|
||||
continue
|
||||
}
|
||||
if row != "" {
|
||||
name, err := adjustFormulaRowNumber(row, dir, num, offset)
|
||||
if err != nil {
|
||||
return operand, err
|
||||
}
|
||||
operand += name
|
||||
row = ""
|
||||
}
|
||||
if col != "" {
|
||||
name, err := adjustFormulaColumnName(col, dir, num, offset)
|
||||
if err != nil {
|
||||
return operand, err
|
||||
}
|
||||
operand += name
|
||||
col = ""
|
||||
}
|
||||
operand += string(r)
|
||||
}
|
||||
name, err := adjustFormulaColumnName(col, dir, num, offset)
|
||||
if err != nil {
|
||||
return operand, err
|
||||
}
|
||||
operand += name
|
||||
name, err = adjustFormulaRowNumber(row, dir, num, offset)
|
||||
operand += name
|
||||
return operand, err
|
||||
}
|
||||
|
||||
// adjustFormulaRef returns adjusted formula by giving adjusting direction and
|
||||
// the base number of column or row, and offset.
|
||||
func (f *File) adjustFormulaRef(sheet, formula string, dir adjustDirection, num, offset int) (string, error) {
|
||||
var (
|
||||
formulaText string
|
||||
val string
|
||||
definedNames []string
|
||||
ps = efp.ExcelParser()
|
||||
)
|
||||
|
@ -234,32 +340,34 @@ func (f *File) adjustFormulaRef(sheet string, text string, dir adjustDirection,
|
|||
definedNames = append(definedNames, definedName.Name)
|
||||
}
|
||||
}
|
||||
for _, token := range ps.Parse(text) {
|
||||
for _, token := range ps.Parse(formula) {
|
||||
if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeRange {
|
||||
if inStrSlice(definedNames, token.TValue, true) != -1 {
|
||||
formulaText += token.TValue
|
||||
val += token.TValue
|
||||
continue
|
||||
}
|
||||
c, r, err := CellNameToCoordinates(token.TValue)
|
||||
if strings.ContainsAny(token.TValue, "[]") {
|
||||
val += token.TValue
|
||||
continue
|
||||
}
|
||||
operand, err := f.adjustFormulaOperand(token, dir, num, offset)
|
||||
if err != nil {
|
||||
return formulaText, err
|
||||
return val, err
|
||||
}
|
||||
if dir == columns && c >= num {
|
||||
c += offset
|
||||
}
|
||||
if dir == rows {
|
||||
r += offset
|
||||
}
|
||||
cell, err := CoordinatesToCellName(c, r, strings.Contains(token.TValue, "$"))
|
||||
if err != nil {
|
||||
return formulaText, err
|
||||
}
|
||||
formulaText += cell
|
||||
val += operand
|
||||
continue
|
||||
}
|
||||
formulaText += token.TValue
|
||||
if isFunctionStart(token) {
|
||||
val += token.TValue + string(efp.ParenOpen)
|
||||
continue
|
||||
}
|
||||
if isFunctionStop(token) {
|
||||
val += token.TValue + string(efp.ParenClose)
|
||||
continue
|
||||
}
|
||||
val += token.TValue
|
||||
}
|
||||
return formulaText, nil
|
||||
return val, nil
|
||||
}
|
||||
|
||||
// adjustHyperlinks provides a function to update hyperlinks when inserting or
|
||||
|
|
269
adjust_test.go
269
adjust_test.go
|
@ -451,6 +451,63 @@ func TestAdjustCols(t *testing.T) {
|
|||
assert.NoError(t, f.Close())
|
||||
}
|
||||
|
||||
func TestAdjustColDimensions(t *testing.T) {
|
||||
f := NewFile()
|
||||
ws, err := f.workSheetReader("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
|
||||
assert.Equal(t, ErrColumnNumber, f.adjustColDimensions("Sheet1", ws, 1, MaxColumns))
|
||||
}
|
||||
|
||||
func TestAdjustRowDimensions(t *testing.T) {
|
||||
f := NewFile()
|
||||
ws, err := f.workSheetReader("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
|
||||
assert.Equal(t, ErrMaxRows, f.adjustRowDimensions("Sheet1", ws, 1, TotalRows))
|
||||
}
|
||||
|
||||
func TestAdjustHyperlinks(t *testing.T) {
|
||||
f := NewFile()
|
||||
ws, err := f.workSheetReader("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
|
||||
f.adjustHyperlinks(ws, "Sheet1", rows, 3, -1)
|
||||
|
||||
// Test adjust hyperlinks location with positive offset
|
||||
assert.NoError(t, f.SetCellHyperLink("Sheet1", "F5", "Sheet1!A1", "Location"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
|
||||
link, target, err := f.GetCellHyperLink("Sheet1", "F6")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, link)
|
||||
assert.Equal(t, target, "Sheet1!A1")
|
||||
|
||||
// Test adjust hyperlinks location with negative offset
|
||||
assert.NoError(t, f.RemoveRow("Sheet1", 1))
|
||||
link, target, err = f.GetCellHyperLink("Sheet1", "F5")
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, link)
|
||||
assert.Equal(t, target, "Sheet1!A1")
|
||||
|
||||
// Test adjust hyperlinks location on remove row
|
||||
assert.NoError(t, f.RemoveRow("Sheet1", 5))
|
||||
link, target, err = f.GetCellHyperLink("Sheet1", "F5")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, link)
|
||||
assert.Empty(t, target)
|
||||
|
||||
// Test adjust hyperlinks location on remove column
|
||||
assert.NoError(t, f.SetCellHyperLink("Sheet1", "F5", "Sheet1!A1", "Location"))
|
||||
assert.NoError(t, f.RemoveCol("Sheet1", "F"))
|
||||
link, target, err = f.GetCellHyperLink("Sheet1", "F5")
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, link)
|
||||
assert.Empty(t, target)
|
||||
|
||||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustHyperlinks.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
}
|
||||
|
||||
func TestAdjustFormula(t *testing.T) {
|
||||
f := NewFile()
|
||||
formulaType, ref := STCellFormulaTypeShared, "C1:C5"
|
||||
|
@ -467,7 +524,7 @@ func TestAdjustFormula(t *testing.T) {
|
|||
assert.NoError(t, f.Close())
|
||||
|
||||
assert.NoError(t, f.adjustFormula("Sheet1", nil, rows, 0, 0, false))
|
||||
assert.Equal(t, ErrParameterInvalid, f.adjustFormula("Sheet1", &xlsxF{Ref: "-"}, rows, 0, 0, false))
|
||||
assert.Equal(t, newCellNameToCoordinatesError("-", newInvalidCellNameError("-")), f.adjustFormula("Sheet1", &xlsxF{Ref: "-"}, rows, 0, 0, false))
|
||||
assert.Equal(t, ErrColumnNumber, f.adjustFormula("Sheet1", &xlsxF{Ref: "XFD1:XFD1"}, columns, 0, 1, false))
|
||||
|
||||
_, err := f.adjustFormulaRef("Sheet1", "XFE1", columns, 0, 1)
|
||||
|
@ -482,6 +539,18 @@ func TestAdjustFormula(t *testing.T) {
|
|||
assert.NoError(t, f.SetCellFormula("Sheet1", "B2", fmt.Sprintf("A%d", TotalRows)))
|
||||
assert.Equal(t, ErrMaxRows, f.InsertRows("Sheet1", 1, 1))
|
||||
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B3", "SUM(1048576:1:2)"))
|
||||
assert.Equal(t, ErrMaxRows, f.InsertRows("Sheet1", 1, 1))
|
||||
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B3", "SUM(XFD:A:B)"))
|
||||
assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))
|
||||
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B3", "SUM(A:B:XFD)"))
|
||||
assert.Equal(t, ErrColumnNumber, f.InsertCols("Sheet1", "A", 1))
|
||||
|
||||
// Test adjust formula with defined name in formula text
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetDefinedName(&DefinedName{
|
||||
|
@ -497,9 +566,205 @@ func TestAdjustFormula(t *testing.T) {
|
|||
// Test adjust formula with array formula
|
||||
f = NewFile()
|
||||
formulaType, reference := STCellFormulaTypeArray, "A3:A3"
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A3", "=A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A3", "A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A4")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A2:A3", formula)
|
||||
|
||||
// Test adjust formula on duplicate row with array formula
|
||||
f = NewFile()
|
||||
formulaType, reference = STCellFormulaTypeArray, "A3"
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A3", "A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A4")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A2:A3", formula)
|
||||
|
||||
// Test adjust formula on duplicate row with relative and absolute cell references
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B10", "A$10+$A11"))
|
||||
assert.NoError(t, f.DuplicateRowTo("Sheet1", 10, 2))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B2")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A$2+$A3", formula)
|
||||
|
||||
t.Run("for_cells_affected_directly", func(t *testing.T) {
|
||||
// Test insert row in middle of range with relative and absolute cell references
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "$A1+A$2"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
formula, err := f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "$A1+A$3", formula)
|
||||
assert.NoError(t, f.RemoveRow("Sheet1", 2))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "$A1+A$2", formula)
|
||||
|
||||
// Test insert column in middle of range
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "B1+C1"))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "B1+D1", formula)
|
||||
assert.NoError(t, f.RemoveCol("Sheet1", "C"))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "B1+C1", formula)
|
||||
|
||||
// Test insert row and column in a rectangular range
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "D4+D5+E4+E5"))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "E", 1))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 5, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "D4+D6+F4+F6", formula)
|
||||
|
||||
// Test insert row in middle of range
|
||||
f = NewFile()
|
||||
formulaType, reference := STCellFormulaTypeArray, "B1:B1"
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "A1:A2", FormulaOpts{Ref: &reference, Type: &formulaType}))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A1:A3", formula)
|
||||
assert.NoError(t, f.RemoveRow("Sheet1", 2))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A1:A2", formula)
|
||||
|
||||
// Test insert column in middle of range
|
||||
f = NewFile()
|
||||
formulaType, reference = STCellFormulaTypeArray, "A1:A1"
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "B1:C1", FormulaOpts{Ref: &reference, Type: &formulaType}))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "B1:D1", formula)
|
||||
assert.NoError(t, f.RemoveCol("Sheet1", "C"))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "B1:C1", formula)
|
||||
|
||||
// Test insert row and column in a rectangular range
|
||||
f = NewFile()
|
||||
formulaType, reference = STCellFormulaTypeArray, "A1:A1"
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "A1", "D4:E5", FormulaOpts{Ref: &reference, Type: &formulaType}))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "E", 1))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 5, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "A1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "D4:F6", formula)
|
||||
})
|
||||
t.Run("for_cells_affected_indirectly", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "A3+A4"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
formula, err := f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A4+A5", formula)
|
||||
assert.NoError(t, f.RemoveRow("Sheet1", 2))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "A3+A4", formula)
|
||||
|
||||
f = NewFile()
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "D3+D4"))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "E3+E4", formula)
|
||||
assert.NoError(t, f.RemoveCol("Sheet1", "C"))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "D3+D4", formula)
|
||||
})
|
||||
t.Run("for_entire_cols_rows_reference", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
// Test adjust formula on insert row in the middle of the range
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(A2:A3:A4,,Table1[])"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
|
||||
formula, err := f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(A2:A4:A5,,Table1[])", formula)
|
||||
|
||||
// Test adjust formula on insert at the top of the range
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(A3:A5:A6,,Table1[])", formula)
|
||||
|
||||
f = NewFile()
|
||||
// Test adjust formula on insert row in the middle of the range
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(A2,A3)"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(A2,A4)", formula)
|
||||
|
||||
// Test adjust formula on insert row at the top of the range
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(A3,A5)", formula)
|
||||
|
||||
f = NewFile()
|
||||
// Test adjust formula on insert col in the middle of the range
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(C3:D3)"))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(C3:E3)", formula)
|
||||
|
||||
// Test adjust formula on insert at the top of the range
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(D3:F3)", formula)
|
||||
|
||||
f = NewFile()
|
||||
// Test adjust formula on insert column in the middle of the range
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(C3,D3)"))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(C3,E3)", formula)
|
||||
|
||||
// Test adjust formula on insert column at the top of the range
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(D3,F3)", formula)
|
||||
|
||||
f = NewFile()
|
||||
// Test adjust formula on insert row in the middle of the range (range of whole row)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(2:3)"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(2:4)", formula)
|
||||
|
||||
// Test adjust formula on insert row at the top of the range (range of whole row)
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(3:5)", formula)
|
||||
|
||||
f = NewFile()
|
||||
// Test adjust formula on insert row in the middle of the range (range of whole column)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM(C:D)"))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "D", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(C:E)", formula)
|
||||
|
||||
// Test adjust formula on insert row at the top of the range (range of whole column)
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "C", 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(D:F)", formula)
|
||||
})
|
||||
}
|
||||
|
|
3
rows.go
3
rows.go
|
@ -652,7 +652,8 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
|||
}
|
||||
|
||||
rowCopy.C = append(make([]xlsxC, 0, len(rowCopy.C)), rowCopy.C...)
|
||||
_ = f.adjustSingleRowDimensions(sheet, &rowCopy, row, row2-row, true)
|
||||
rowCopy.adjustSingleRowDimensions(row2 - row)
|
||||
_ = f.adjustSingleRowFormulas(sheet, &rowCopy, row, row2-row, true)
|
||||
|
||||
if idx2 != -1 {
|
||||
ws.SheetData.Row[idx2] = rowCopy
|
||||
|
|
Loading…
Reference in New Issue