diff --git a/adjust.go b/adjust.go index d264afd..bf3ad77 100644 --- a/adjust.go +++ b/adjust.go @@ -226,6 +226,7 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off i-- continue } + areaData.rect = []int{x1, y1, x2, y2} if areaData.Ref, err = f.coordinatesToAreaRef([]int{x1, y1, x2, y2}); err != nil { return err } diff --git a/adjust_test.go b/adjust_test.go index 98e7a82..b2ec3c4 100644 --- a/adjust_test.go +++ b/adjust_test.go @@ -48,22 +48,24 @@ func TestAdjustMergeCells(t *testing.T) { // testing adjustMergeCells var cases []struct { - label string - ws *xlsxWorksheet - dir adjustDirection - num int - offset int - expect string + label string + ws *xlsxWorksheet + dir adjustDirection + num int + offset int + expect string + expectRect []int } // testing insert cases = []struct { - label string - ws *xlsxWorksheet - dir adjustDirection - num int - offset int - expect string + label string + ws *xlsxWorksheet + dir adjustDirection + num int + offset int + expect string + expectRect []int }{ { label: "insert row on ref", @@ -71,15 +73,17 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: rows, - num: 2, - offset: 1, - expect: "A3:B4", + dir: rows, + num: 2, + offset: 1, + expect: "A3:B4", + expectRect: []int{1, 3, 2, 4}, }, { label: "insert row on bottom of ref", @@ -87,15 +91,17 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: rows, - num: 3, - offset: 1, - expect: "A2:B4", + dir: rows, + num: 3, + offset: 1, + expect: "A2:B4", + expectRect: []int{1, 2, 2, 4}, }, { label: "insert column on the left", @@ -103,30 +109,34 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: columns, - num: 1, - offset: 1, - expect: "B2:C3", + dir: columns, + num: 1, + offset: 1, + expect: "B2:C3", + expectRect: []int{2, 2, 3, 3}, }, } for _, c := range cases { assert.NoError(t, f.adjustMergeCells(c.ws, c.dir, c.num, 1)) assert.Equal(t, c.expect, c.ws.MergeCells.Cells[0].Ref, c.label) + assert.Equal(t, c.expectRect, c.ws.MergeCells.Cells[0].rect, c.label) } // testing delete cases = []struct { - label string - ws *xlsxWorksheet - dir adjustDirection - num int - offset int - expect string + label string + ws *xlsxWorksheet + dir adjustDirection + num int + offset int + expect string + expectRect []int }{ { label: "delete row on top of ref", @@ -134,15 +144,17 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: rows, - num: 2, - offset: -1, - expect: "A2:B2", + dir: rows, + num: 2, + offset: -1, + expect: "A2:B2", + expectRect: []int{1, 2, 2, 2}, }, { label: "delete row on bottom of ref", @@ -150,15 +162,17 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: rows, - num: 3, - offset: -1, - expect: "A2:B2", + dir: rows, + num: 3, + offset: -1, + expect: "A2:B2", + expectRect: []int{1, 2, 2, 2}, }, { label: "delete column on the ref left", @@ -166,15 +180,17 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: columns, - num: 1, - offset: -1, - expect: "A2:A3", + dir: columns, + num: 1, + offset: -1, + expect: "A2:A3", + expectRect: []int{1, 2, 1, 3}, }, { label: "delete column on the ref right", @@ -182,15 +198,17 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A2:B3", + Ref: "A2:B3", + rect: []int{1, 2, 2, 3}, }, }, }, }, - dir: columns, - num: 2, - offset: -1, - expect: "A2:A3", + dir: columns, + num: 2, + offset: -1, + expect: "A2:A3", + expectRect: []int{1, 2, 1, 3}, }, } for _, c := range cases { @@ -200,12 +218,13 @@ func TestAdjustMergeCells(t *testing.T) { // testing delete one row/column cases = []struct { - label string - ws *xlsxWorksheet - dir adjustDirection - num int - offset int - expect string + label string + ws *xlsxWorksheet + dir adjustDirection + num int + offset int + expect string + expectRect []int }{ { label: "delete one row ref", @@ -213,7 +232,8 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A1:B1", + Ref: "A1:B1", + rect: []int{1, 1, 2, 1}, }, }, }, @@ -228,7 +248,8 @@ func TestAdjustMergeCells(t *testing.T) { MergeCells: &xlsxMergeCells{ Cells: []*xlsxMergeCell{ { - Ref: "A1:A2", + Ref: "A1:A2", + rect: []int{1, 1, 1, 2}, }, }, }, diff --git a/rows.go b/rows.go index 56301dd..0ced386 100644 --- a/rows.go +++ b/rows.go @@ -661,7 +661,8 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error { if err != nil { return err } - if row > len(ws.SheetData.Row) || row2 < 1 || row == row2 { + + if row2 < 1 || row == row2 { return nil } @@ -675,14 +676,15 @@ func (f *File) DuplicateRowTo(sheet string, row, row2 int) error { break } } - if !ok { - return nil - } if err := f.adjustHelper(sheet, rows, row2, 1); err != nil { return err } + if !ok { + return nil + } + idx2 := -1 for i, r := range ws.SheetData.Row { if r.R == row2 { diff --git a/rows_test.go b/rows_test.go index 1c682e5..f6a3da4 100644 --- a/rows_test.go +++ b/rows_test.go @@ -669,6 +669,7 @@ func TestDuplicateRowInsertBefore(t *testing.T) { f := newFileWithDefaults() assert.NoError(t, f.DuplicateRowTo(sheet, 2, 1)) + assert.NoError(t, f.DuplicateRowTo(sheet, 10, 4)) if !assert.NoError(t, f.SaveAs(fmt.Sprintf(outFile, "InsertBefore"))) { t.FailNow() @@ -678,7 +679,7 @@ func TestDuplicateRowInsertBefore(t *testing.T) { "A1": cells["A2"], "B1": cells["B2"], "A2": cells["A1"], "B2": cells["B1"], "A3": cells["A2"], "B3": cells["B2"], - "A4": cells["A3"], "B4": cells["B3"], + "A5": cells["A3"], "B5": cells["B3"], } for cell, val := range expect { v, err := f.GetCellValue(sheet, cell) @@ -846,7 +847,18 @@ func TestDuplicateRowInvalidRowNum(t *testing.T) { } func TestDuplicateRowTo(t *testing.T) { - f := File{} + f, sheetName := NewFile(), "Sheet1" + // Test duplicate row with invalid target row number + assert.Equal(t, nil, f.DuplicateRowTo(sheetName, 1, 0)) + // Test duplicate row with equal source and target row number + assert.Equal(t, nil, f.DuplicateRowTo(sheetName, 1, 1)) + // Test duplicate row on the blank worksheet + assert.Equal(t, nil, f.DuplicateRowTo(sheetName, 1, 2)) + // Test duplicate row on the worksheet with illegal cell coordinates + f.Sheet.Store("xl/worksheets/sheet1.xml", &xlsxWorksheet{ + MergeCells: &xlsxMergeCells{Cells: []*xlsxMergeCell{{Ref: "A:B1"}}}}) + assert.EqualError(t, f.DuplicateRowTo(sheetName, 1, 2), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error()) + // Test duplicate row on not exists worksheet assert.EqualError(t, f.DuplicateRowTo("SheetN", 1, 2), "sheet SheetN is not exist") }