Support to adjust formula cross worksheet on inserting/deleting columns/rows (#1705)
This commit is contained in:
parent
5bba8f9805
commit
b41a6cc3cd
107
adjust.go
107
adjust.go
|
@ -17,6 +17,7 @@ import (
|
|||
"io"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/xuri/efp"
|
||||
)
|
||||
|
@ -128,15 +129,24 @@ func (f *File) adjustColDimensions(sheet string, ws *xlsxWorksheet, col, offset
|
|||
}
|
||||
}
|
||||
}
|
||||
for rowIdx := range ws.SheetData.Row {
|
||||
for colIdx, v := range ws.SheetData.Row[rowIdx].C {
|
||||
if cellCol, cellRow, _ := CellNameToCoordinates(v.R); col <= cellCol {
|
||||
if newCol := cellCol + offset; newCol > 0 {
|
||||
ws.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
|
||||
}
|
||||
for _, sheetN := range f.GetSheetList() {
|
||||
worksheet, err := f.workSheetReader(sheetN)
|
||||
if err != nil {
|
||||
if err.Error() == newNotWorksheetError(sheetN).Error() {
|
||||
continue
|
||||
}
|
||||
if err := f.adjustFormula(sheet, ws.SheetData.Row[rowIdx].C[colIdx].F, columns, col, offset, false); err != nil {
|
||||
return err
|
||||
return err
|
||||
}
|
||||
for rowIdx := range worksheet.SheetData.Row {
|
||||
for colIdx, v := range worksheet.SheetData.Row[rowIdx].C {
|
||||
if cellCol, cellRow, _ := CellNameToCoordinates(v.R); sheetN == sheet && col <= cellCol {
|
||||
if newCol := cellCol + offset; newCol > 0 {
|
||||
worksheet.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
|
||||
}
|
||||
}
|
||||
if err := f.adjustFormula(sheet, sheetN, worksheet.SheetData.Row[rowIdx].C[colIdx].F, columns, col, offset, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,6 +156,25 @@ func (f *File) adjustColDimensions(sheet string, ws *xlsxWorksheet, col, offset
|
|||
// adjustRowDimensions provides a function to update row dimensions when
|
||||
// inserting or deleting rows or columns.
|
||||
func (f *File) adjustRowDimensions(sheet string, ws *xlsxWorksheet, row, offset int) error {
|
||||
for _, sheetN := range f.GetSheetList() {
|
||||
if sheetN == sheet {
|
||||
continue
|
||||
}
|
||||
worksheet, err := f.workSheetReader(sheetN)
|
||||
if err != nil {
|
||||
if err.Error() == newNotWorksheetError(sheetN).Error() {
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
numOfRows := len(worksheet.SheetData.Row)
|
||||
for i := 0; i < numOfRows; i++ {
|
||||
r := &worksheet.SheetData.Row[i]
|
||||
if err = f.adjustSingleRowFormulas(sheet, sheetN, r, row, offset, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
totalRows := len(ws.SheetData.Row)
|
||||
if totalRows == 0 {
|
||||
return nil
|
||||
|
@ -160,7 +189,7 @@ func (f *File) adjustRowDimensions(sheet string, ws *xlsxWorksheet, row, offset
|
|||
if newRow := r.R + offset; r.R >= row && newRow > 0 {
|
||||
r.adjustSingleRowDimensions(offset)
|
||||
}
|
||||
if err := f.adjustSingleRowFormulas(sheet, r, row, offset, false); err != nil {
|
||||
if err := f.adjustSingleRowFormulas(sheet, sheet, r, row, offset, false); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -177,9 +206,9 @@ func (r *xlsxRow) adjustSingleRowDimensions(offset int) {
|
|||
}
|
||||
|
||||
// adjustSingleRowFormulas provides a function to adjust single row formulas.
|
||||
func (f *File) adjustSingleRowFormulas(sheet string, r *xlsxRow, num, offset int, si bool) error {
|
||||
func (f *File) adjustSingleRowFormulas(sheet, sheetN 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 {
|
||||
if err := f.adjustFormula(sheet, sheetN, col.F, rows, num, offset, si); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -215,12 +244,12 @@ func (f *File) adjustCellRef(ref string, dir adjustDirection, num, offset int) (
|
|||
|
||||
// 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 {
|
||||
func (f *File) adjustFormula(sheet, sheetN string, formula *xlsxF, dir adjustDirection, num, offset int, si bool) error {
|
||||
if formula == nil {
|
||||
return nil
|
||||
}
|
||||
var err error
|
||||
if formula.Ref != "" {
|
||||
if formula.Ref != "" && sheet == sheetN {
|
||||
if formula.Ref, err = f.adjustCellRef(formula.Ref, dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -229,7 +258,7 @@ func (f *File) adjustFormula(sheet string, formula *xlsxF, dir adjustDirection,
|
|||
}
|
||||
}
|
||||
if formula.Content != "" {
|
||||
if formula.Content, err = f.adjustFormulaRef(sheet, formula.Content, dir, num, offset); err != nil {
|
||||
if formula.Content, err = f.adjustFormulaRef(sheet, sheetN, formula.Content, dir, num, offset); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@ -246,11 +275,19 @@ func isFunctionStart(token efp.Token) bool {
|
|||
return token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStart
|
||||
}
|
||||
|
||||
// escapeSheetName enclose sheet name in single quotation marks if the giving
|
||||
// worksheet name includes spaces or non-alphabetical characters.
|
||||
func escapeSheetName(name string) string {
|
||||
if strings.IndexFunc(name, func(r rune) bool {
|
||||
return !unicode.IsLetter(r) && !unicode.IsNumber(r)
|
||||
}) != -1 {
|
||||
return string(efp.QuoteSingle) + name + string(efp.QuoteSingle)
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -264,9 +301,6 @@ func adjustFormulaColumnName(name string, dir adjustDirection, num, offset int)
|
|||
|
||||
// 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
|
||||
|
@ -300,16 +334,19 @@ func adjustFormulaOperandRef(row, col, operand string, dir adjustDirection, num
|
|||
}
|
||||
|
||||
// adjustFormulaOperand adjust range operand tokens for the formula.
|
||||
func (f *File) adjustFormulaOperand(token efp.Token, dir adjustDirection, num int, offset int) (string, error) {
|
||||
func (f *File) adjustFormulaOperand(sheet, sheetN string, token efp.Token, dir adjustDirection, num int, offset int) (string, error) {
|
||||
var (
|
||||
err error
|
||||
sheet, col, row, operand string
|
||||
cell = token.TValue
|
||||
tokens = strings.Split(token.TValue, "!")
|
||||
err error
|
||||
sheetName, col, row, operand string
|
||||
cell = token.TValue
|
||||
tokens = strings.Split(token.TValue, "!")
|
||||
)
|
||||
if len(tokens) == 2 { // have a worksheet
|
||||
sheet, cell = tokens[0], tokens[1]
|
||||
operand = string(efp.QuoteSingle) + sheet + string(efp.QuoteSingle) + "!"
|
||||
sheetName, cell = tokens[0], tokens[1]
|
||||
operand = escapeSheetName(sheetName) + "!"
|
||||
}
|
||||
if sheet != sheetN && sheet != sheetName {
|
||||
return operand + cell, err
|
||||
}
|
||||
for _, r := range cell {
|
||||
if ('A' <= r && r <= 'Z') || ('a' <= r && r <= 'z') {
|
||||
|
@ -333,19 +370,13 @@ func (f *File) adjustFormulaOperand(token efp.Token, dir adjustDirection, num in
|
|||
}
|
||||
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
|
||||
_, _, operand, err = adjustFormulaOperandRef(row, col, operand, dir, num, offset)
|
||||
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) {
|
||||
func (f *File) adjustFormulaRef(sheet, sheetN, formula string, dir adjustDirection, num, offset int) (string, error) {
|
||||
var (
|
||||
val string
|
||||
definedNames []string
|
||||
|
@ -366,7 +397,7 @@ func (f *File) adjustFormulaRef(sheet, formula string, dir adjustDirection, num,
|
|||
val += token.TValue
|
||||
continue
|
||||
}
|
||||
operand, err := f.adjustFormulaOperand(token, dir, num, offset)
|
||||
operand, err := f.adjustFormulaOperand(sheet, sheetN, token, dir, num, offset)
|
||||
if err != nil {
|
||||
return val, err
|
||||
}
|
||||
|
@ -382,7 +413,7 @@ func (f *File) adjustFormulaRef(sheet, formula string, dir adjustDirection, num,
|
|||
continue
|
||||
}
|
||||
if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText {
|
||||
val += string(efp.QuoteDouble) + token.TValue + string(efp.QuoteDouble)
|
||||
val += string(efp.QuoteDouble) + strings.ReplaceAll(token.TValue, "\"", "\"\"") + string(efp.QuoteDouble)
|
||||
continue
|
||||
}
|
||||
val += token.TValue
|
||||
|
@ -420,7 +451,7 @@ func (f *File) adjustHyperlinks(ws *xlsxWorksheet, sheet string, dir adjustDirec
|
|||
}
|
||||
for i := range ws.Hyperlinks.Hyperlink {
|
||||
link := &ws.Hyperlinks.Hyperlink[i] // get reference
|
||||
link.Ref, _ = f.adjustFormulaRef(sheet, link.Ref, dir, num, offset)
|
||||
link.Ref, _ = f.adjustFormulaRef(sheet, sheet, link.Ref, dir, num, offset)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
175
adjust_test.go
175
adjust_test.go
|
@ -457,6 +457,12 @@ func TestAdjustColDimensions(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
|
||||
assert.Equal(t, ErrColumnNumber, f.adjustColDimensions("Sheet1", ws, 1, MaxColumns))
|
||||
|
||||
_, err = f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
f.Sheet.Delete("xl/worksheets/sheet2.xml")
|
||||
f.Pkg.Store("xl/worksheets/sheet2.xml", MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.adjustColDimensions("Sheet2", ws, 2, 1), "XML syntax error on line 1: invalid UTF-8")
|
||||
}
|
||||
|
||||
func TestAdjustRowDimensions(t *testing.T) {
|
||||
|
@ -465,6 +471,20 @@ func TestAdjustRowDimensions(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "C3", "A1+B1"))
|
||||
assert.Equal(t, ErrMaxRows, f.adjustRowDimensions("Sheet1", ws, 1, TotalRows))
|
||||
|
||||
_, err = f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
f.Sheet.Delete("xl/worksheets/sheet2.xml")
|
||||
f.Pkg.Store("xl/worksheets/sheet2.xml", MacintoshCyrillicCharset)
|
||||
assert.EqualError(t, f.adjustRowDimensions("Sheet1", ws, 2, 1), "XML syntax error on line 1: invalid UTF-8")
|
||||
|
||||
f = NewFile()
|
||||
_, err = f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
ws, err = f.workSheetReader("Sheet1")
|
||||
assert.NoError(t, err)
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B2", fmt.Sprintf("Sheet2!A%d", TotalRows)))
|
||||
assert.Equal(t, ErrMaxRows, f.adjustRowDimensions("Sheet2", ws, 1, TotalRows))
|
||||
}
|
||||
|
||||
func TestAdjustHyperlinks(t *testing.T) {
|
||||
|
@ -523,13 +543,13 @@ func TestAdjustFormula(t *testing.T) {
|
|||
assert.NoError(t, f.SaveAs(filepath.Join("test", "TestAdjustFormula.xlsx")))
|
||||
assert.NoError(t, f.Close())
|
||||
|
||||
assert.NoError(t, f.adjustFormula("Sheet1", nil, 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))
|
||||
assert.NoError(t, f.adjustFormula("Sheet1", "Sheet1", nil, rows, 0, 0, false))
|
||||
assert.Equal(t, newCellNameToCoordinatesError("-", newInvalidCellNameError("-")), f.adjustFormula("Sheet1", "Sheet1", &xlsxF{Ref: "-"}, rows, 0, 0, false))
|
||||
assert.Equal(t, ErrColumnNumber, f.adjustFormula("Sheet1", "Sheet1", &xlsxF{Ref: "XFD1:XFD1"}, columns, 0, 1, false))
|
||||
|
||||
_, err := f.adjustFormulaRef("Sheet1", "XFE1", columns, 0, 1)
|
||||
_, err := f.adjustFormulaRef("Sheet1", "Sheet1", "XFE1", columns, 0, 1)
|
||||
assert.Equal(t, ErrColumnNumber, err)
|
||||
_, err = f.adjustFormulaRef("Sheet1", "XFD1", columns, 0, 1)
|
||||
_, err = f.adjustFormulaRef("Sheet1", "Sheet1", "XFD1", columns, 0, 1)
|
||||
assert.Equal(t, ErrColumnNumber, err)
|
||||
|
||||
f = NewFile()
|
||||
|
@ -699,17 +719,17 @@ func TestAdjustFormula(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('Sheet1'!A2,A3)"))
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", "B1", "SUM('Sheet 1'!A2,A3)"))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 3, 1))
|
||||
formula, err = f.GetCellFormula("Sheet1", "B1")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM('Sheet1'!A2,A4)", formula)
|
||||
assert.Equal(t, "SUM('Sheet 1'!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('Sheet1'!A3,A5)", formula)
|
||||
assert.Equal(t, "SUM('Sheet 1'!A3,A5)", formula)
|
||||
|
||||
f = NewFile()
|
||||
// Test adjust formula on insert col in the middle of the range
|
||||
|
@ -767,4 +787,143 @@ func TestAdjustFormula(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
assert.Equal(t, "SUM(D:F)", formula)
|
||||
})
|
||||
t.Run("for_all_worksheet_cells_with_rows_insert", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
_, err := f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
// Tests formulas referencing Sheet2 should update but those referencing the original sheet should not
|
||||
tbl := [][]string{
|
||||
{"B1", "Sheet2!A1+Sheet2!A2", "Sheet2!A1+Sheet2!A3", "Sheet2!A2+Sheet2!A4"},
|
||||
{"C1", "A1+A2", "A1+A2", "A1+A2"},
|
||||
{"D1", "Sheet2!B1:B2", "Sheet2!B1:B3", "Sheet2!B2:B4"},
|
||||
{"E1", "B1:B2", "B1:B2", "B1:B2"},
|
||||
{"F1", "SUM(Sheet2!C1:C2)", "SUM(Sheet2!C1:C3)", "SUM(Sheet2!C2:C4)"},
|
||||
{"G1", "SUM(C1:C2)", "SUM(C1:C2)", "SUM(C1:C2)"},
|
||||
{"H1", "SUM(Sheet2!D1,Sheet2!D2)", "SUM(Sheet2!D1,Sheet2!D3)", "SUM(Sheet2!D2,Sheet2!D4)"},
|
||||
{"I1", "SUM(D1,D2)", "SUM(D1,D2)", "SUM(D1,D2)"},
|
||||
}
|
||||
for _, preset := range tbl {
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
|
||||
}
|
||||
// Test adjust formula on insert row in the middle of the range
|
||||
assert.NoError(t, f.InsertRows("Sheet2", 2, 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[2], formula)
|
||||
}
|
||||
|
||||
// Test adjust formula on insert row in the top of the range
|
||||
assert.NoError(t, f.InsertRows("Sheet2", 1, 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[3], formula)
|
||||
}
|
||||
})
|
||||
t.Run("for_all_worksheet_cells_with_cols_insert", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
_, err := f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
tbl := [][]string{
|
||||
{"A1", "Sheet2!A1+Sheet2!B1", "Sheet2!A1+Sheet2!C1", "Sheet2!B1+Sheet2!D1"},
|
||||
{"A2", "A1+B1", "A1+B1", "A1+B1"},
|
||||
{"A3", "Sheet2!A2:B2", "Sheet2!A2:C2", "Sheet2!B2:D2"},
|
||||
{"A4", "A2:B2", "A2:B2", "A2:B2"},
|
||||
{"A5", "SUM(Sheet2!A3:B3)", "SUM(Sheet2!A3:C3)", "SUM(Sheet2!B3:D3)"},
|
||||
{"A6", "SUM(A3:B3)", "SUM(A3:B3)", "SUM(A3:B3)"},
|
||||
{"A7", "SUM(Sheet2!A4,Sheet2!B4)", "SUM(Sheet2!A4,Sheet2!C4)", "SUM(Sheet2!B4,Sheet2!D4)"},
|
||||
{"A8", "SUM(A4,B4)", "SUM(A4,B4)", "SUM(A4,B4)"},
|
||||
}
|
||||
for _, preset := range tbl {
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
|
||||
}
|
||||
// Test adjust formula on insert column in the middle of the range
|
||||
assert.NoError(t, f.InsertCols("Sheet2", "B", 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[2], formula)
|
||||
}
|
||||
// Test adjust formula on insert column in the top of the range
|
||||
assert.NoError(t, f.InsertCols("Sheet2", "A", 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[3], formula)
|
||||
}
|
||||
})
|
||||
t.Run("for_cross_sheet_ref_with_rows_insert)", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
_, err := f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
_, err = f.NewSheet("Sheet3")
|
||||
assert.NoError(t, err)
|
||||
// Tests formulas referencing Sheet2 should update but those referencing
|
||||
// the original sheet or Sheet 3 should not update
|
||||
tbl := [][]string{
|
||||
{"B1", "Sheet2!A1+Sheet2!A2+Sheet1!A3+Sheet1!A4", "Sheet2!A1+Sheet2!A3+Sheet1!A3+Sheet1!A4", "Sheet2!A2+Sheet2!A4+Sheet1!A3+Sheet1!A4"},
|
||||
{"C1", "Sheet2!B1+Sheet2!B2+B3+B4", "Sheet2!B1+Sheet2!B3+B3+B4", "Sheet2!B2+Sheet2!B4+B3+B4"},
|
||||
{"D1", "Sheet2!C1+Sheet2!C2+Sheet3!A3+Sheet3!A4", "Sheet2!C1+Sheet2!C3+Sheet3!A3+Sheet3!A4", "Sheet2!C2+Sheet2!C4+Sheet3!A3+Sheet3!A4"},
|
||||
{"E1", "SUM(Sheet2!D1:D2,Sheet1!A3:A4)", "SUM(Sheet2!D1:D3,Sheet1!A3:A4)", "SUM(Sheet2!D2:D4,Sheet1!A3:A4)"},
|
||||
{"F1", "SUM(Sheet2!E1:E2,A3:A4)", "SUM(Sheet2!E1:E3,A3:A4)", "SUM(Sheet2!E2:E4,A3:A4)"},
|
||||
{"G1", "SUM(Sheet2!F1:F2,Sheet3!A3:A4)", "SUM(Sheet2!F1:F3,Sheet3!A3:A4)", "SUM(Sheet2!F2:F4,Sheet3!A3:A4)"},
|
||||
}
|
||||
for _, preset := range tbl {
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
|
||||
}
|
||||
// Test adjust formula on insert row in the middle of the range
|
||||
assert.NoError(t, f.InsertRows("Sheet2", 2, 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[2], formula)
|
||||
}
|
||||
// Test adjust formula on insert row in the top of the range
|
||||
assert.NoError(t, f.InsertRows("Sheet2", 1, 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[3], formula)
|
||||
}
|
||||
})
|
||||
t.Run("for_cross_sheet_ref_with_cols_insert)", func(t *testing.T) {
|
||||
f := NewFile()
|
||||
_, err := f.NewSheet("Sheet2")
|
||||
assert.NoError(t, err)
|
||||
_, err = f.NewSheet("Sheet3")
|
||||
assert.NoError(t, err)
|
||||
// Tests formulas referencing Sheet2 should update but those referencing
|
||||
// the original sheet or Sheet 3 should not update
|
||||
tbl := [][]string{
|
||||
{"A1", "Sheet2!A1+Sheet2!B1+Sheet1!C1+Sheet1!D1", "Sheet2!A1+Sheet2!C1+Sheet1!C1+Sheet1!D1", "Sheet2!B1+Sheet2!D1+Sheet1!C1+Sheet1!D1"},
|
||||
{"A2", "Sheet2!A2+Sheet2!B2+C2+D2", "Sheet2!A2+Sheet2!C2+C2+D2", "Sheet2!B2+Sheet2!D2+C2+D2"},
|
||||
{"A3", "Sheet2!A3+Sheet2!B3+Sheet3!C3+Sheet3!D3", "Sheet2!A3+Sheet2!C3+Sheet3!C3+Sheet3!D3", "Sheet2!B3+Sheet2!D3+Sheet3!C3+Sheet3!D3"},
|
||||
{"A4", "SUM(Sheet2!A4:B4,Sheet1!C4:D4)", "SUM(Sheet2!A4:C4,Sheet1!C4:D4)", "SUM(Sheet2!B4:D4,Sheet1!C4:D4)"},
|
||||
{"A5", "SUM(Sheet2!A5:B5,C5:D5)", "SUM(Sheet2!A5:C5,C5:D5)", "SUM(Sheet2!B5:D5,C5:D5)"},
|
||||
{"A6", "SUM(Sheet2!A6:B6,Sheet3!C6:D6)", "SUM(Sheet2!A6:C6,Sheet3!C6:D6)", "SUM(Sheet2!B6:D6,Sheet3!C6:D6)"},
|
||||
}
|
||||
for _, preset := range tbl {
|
||||
assert.NoError(t, f.SetCellFormula("Sheet1", preset[0], preset[1]))
|
||||
}
|
||||
// Test adjust formula on insert row in the middle of the range
|
||||
assert.NoError(t, f.InsertCols("Sheet2", "B", 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[2], formula)
|
||||
}
|
||||
// Test adjust formula on insert row in the top of the range
|
||||
assert.NoError(t, f.InsertCols("Sheet2", "A", 1))
|
||||
for _, preset := range tbl {
|
||||
formula, err := f.GetCellFormula("Sheet1", preset[0])
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, preset[3], formula)
|
||||
}
|
||||
})
|
||||
t.Run("for_cross_sheet_ref_with_chart_sheet)", func(t *testing.T) {
|
||||
assert.NoError(t, f.AddChartSheet("Chart1", &Chart{Type: Line}))
|
||||
assert.NoError(t, f.InsertRows("Sheet1", 2, 1))
|
||||
assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
|
||||
})
|
||||
}
|
||||
|
|
2
rows.go
2
rows.go
|
@ -653,7 +653,7 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error {
|
|||
|
||||
rowCopy.C = append(make([]xlsxC, 0, len(rowCopy.C)), rowCopy.C...)
|
||||
rowCopy.adjustSingleRowDimensions(row2 - row)
|
||||
_ = f.adjustSingleRowFormulas(sheet, &rowCopy, row, row2-row, true)
|
||||
_ = f.adjustSingleRowFormulas(sheet, sheet, &rowCopy, row, row2-row, true)
|
||||
|
||||
if idx2 != -1 {
|
||||
ws.SheetData.Row[idx2] = rowCopy
|
||||
|
|
Loading…
Reference in New Issue