OSDN Git Service

This is a breaking change closes #1332 (#1333)
authorKostya Privezentsev <privezentsev@gmail.com>
Tue, 30 Aug 2022 16:02:48 +0000 (19:02 +0300)
committerGitHub <noreply@github.com>
Tue, 30 Aug 2022 16:02:48 +0000 (00:02 +0800)
This use `InsertRows` instead of `InsertRow`, and using `InsertCols` instead of `InsertCol`

adjust.go
adjust_test.go
col.go
col_test.go
rows.go
rows_test.go

index 99d2850..fd570bb 100644 (file)
--- a/adjust.go
+++ b/adjust.go
@@ -42,9 +42,12 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
        }
        sheetID := f.getSheetID(sheet)
        if dir == rows {
-               f.adjustRowDimensions(ws, num, offset)
+               err = f.adjustRowDimensions(ws, num, offset)
        } else {
-               f.adjustColDimensions(ws, num, offset)
+               err = f.adjustColDimensions(ws, num, offset)
+       }
+       if err != nil {
+               return err
        }
        f.adjustHyperlinks(ws, sheet, dir, num, offset)
        f.adjustTable(ws, sheet, dir, num, offset)
@@ -69,28 +72,36 @@ func (f *File) adjustHelper(sheet string, dir adjustDirection, num, offset int)
 
 // adjustColDimensions provides a function to update column dimensions when
 // inserting or deleting rows or columns.
-func (f *File) adjustColDimensions(ws *xlsxWorksheet, col, offset int) {
+func (f *File) adjustColDimensions(ws *xlsxWorksheet, col, offset int) error {
        for rowIdx := range ws.SheetData.Row {
                for colIdx, v := range ws.SheetData.Row[rowIdx].C {
                        cellCol, cellRow, _ := CellNameToCoordinates(v.R)
                        if col <= cellCol {
                                if newCol := cellCol + offset; newCol > 0 {
+                                       if newCol > MaxColumns {
+                                               return ErrColumnNumber
+                                       }
                                        ws.SheetData.Row[rowIdx].C[colIdx].R, _ = CoordinatesToCellName(newCol, cellRow)
                                }
                        }
                }
        }
+       return nil
 }
 
 // adjustRowDimensions provides a function to update row dimensions when
 // inserting or deleting rows or columns.
-func (f *File) adjustRowDimensions(ws *xlsxWorksheet, row, offset int) {
+func (f *File) adjustRowDimensions(ws *xlsxWorksheet, row, offset int) error {
        for i := range ws.SheetData.Row {
                r := &ws.SheetData.Row[i]
                if newRow := r.R + offset; r.R >= row && newRow > 0 {
+                       if newRow >= TotalRows {
+                               return ErrMaxRows
+                       }
                        f.adjustSingleRowDimensions(r, newRow)
                }
        }
+       return nil
 }
 
 // adjustSingleRowDimensions provides a function to adjust single row dimensions.
index c350101..aa374da 100644 (file)
@@ -349,11 +349,11 @@ func TestAdjustCalcChain(t *testing.T) {
                        {R: "B2", I: 2}, {R: "B2", I: 1},
                },
        }
-       assert.NoError(t, f.InsertCol("Sheet1", "A"))
-       assert.NoError(t, f.InsertRow("Sheet1", 1))
+       assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
+       assert.NoError(t, f.InsertRows("Sheet1", 1, 1))
 
        f.CalcChain.C[1].R = "invalid coordinates"
-       assert.EqualError(t, f.InsertCol("Sheet1", "A"), newCellNameToCoordinatesError("invalid coordinates", newInvalidCellNameError("invalid coordinates")).Error())
+       assert.EqualError(t, f.InsertCols("Sheet1", "A", 1), newCellNameToCoordinatesError("invalid coordinates", newInvalidCellNameError("invalid coordinates")).Error())
        f.CalcChain = nil
-       assert.NoError(t, f.InsertCol("Sheet1", "A"))
+       assert.NoError(t, f.InsertCols("Sheet1", "A", 1))
 }
diff --git a/col.go b/col.go
index 248e22c..f51336d 100644 (file)
--- a/col.go
+++ b/col.go
@@ -657,16 +657,25 @@ func (f *File) GetColWidth(sheet, col string) (float64, error) {
        return defaultColWidth, err
 }
 
-// InsertCol provides a function to insert a new column before given column
-// index. For example, create a new column before column C in Sheet1:
+// InsertCols provides a function to insert new columns before the given column
+// name and number of columns. For example, create two columns before column
+// C in Sheet1:
 //
-//     err := f.InsertCol("Sheet1", "C")
-func (f *File) InsertCol(sheet, col string) error {
+//     err := f.InsertCols("Sheet1", "C", 2)
+//
+// Use this method with caution, which will affect changes in references such
+// as formulas, charts, and so on. If there is any referenced value of the
+// worksheet, it will cause a file error when you open it. The excelize only
+// partially updates these references currently.
+func (f *File) InsertCols(sheet, col string, n int) error {
        num, err := ColumnNameToNumber(col)
        if err != nil {
                return err
        }
-       return f.adjustHelper(sheet, columns, num, 1)
+       if n < 1 || n > MaxColumns {
+               return ErrColumnNumber
+       }
+       return f.adjustHelper(sheet, columns, num, n)
 }
 
 // RemoveCol provides a function to remove single column by given worksheet
index eb97c12..b7d3823 100644 (file)
@@ -339,7 +339,7 @@ func TestColWidth(t *testing.T) {
        convertRowHeightToPixels(0)
 }
 
-func TestInsertCol(t *testing.T) {
+func TestInsertCols(t *testing.T) {
        f := NewFile()
        sheet1 := f.GetSheetName(0)
 
@@ -349,12 +349,16 @@ func TestInsertCol(t *testing.T) {
        assert.NoError(t, f.MergeCell(sheet1, "A1", "C3"))
 
        assert.NoError(t, f.AutoFilter(sheet1, "A2", "B2", `{"column":"B","expression":"x != blanks"}`))
-       assert.NoError(t, f.InsertCol(sheet1, "A"))
+       assert.NoError(t, f.InsertCols(sheet1, "A", 1))
 
        // Test insert column with illegal cell coordinates.
-       assert.EqualError(t, f.InsertCol("Sheet1", "*"), newInvalidColumnNameError("*").Error())
+       assert.EqualError(t, f.InsertCols(sheet1, "*", 1), newInvalidColumnNameError("*").Error())
 
-       assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertCol.xlsx")))
+       assert.EqualError(t, f.InsertCols(sheet1, "A", 0), ErrColumnNumber.Error())
+       assert.EqualError(t, f.InsertCols(sheet1, "A", MaxColumns), ErrColumnNumber.Error())
+       assert.EqualError(t, f.InsertCols(sheet1, "A", MaxColumns-10), ErrColumnNumber.Error())
+
+       assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertCols.xlsx")))
 }
 
 func TestRemoveCol(t *testing.T) {
diff --git a/rows.go b/rows.go
index 7e2d677..9269ac6 100644 (file)
--- a/rows.go
+++ b/rows.go
@@ -622,21 +622,27 @@ func (f *File) RemoveRow(sheet string, row int) error {
        return f.adjustHelper(sheet, rows, row, -1)
 }
 
-// InsertRow provides a function to insert a new row after given Excel row
-// number starting from 1. For example, create a new row before row 3 in
-// Sheet1:
+// InsertRows provides a function to insert new rows after the given Excel row
+// number starting from 1 and number of rows. For example, create two rows
+// before row 3 in Sheet1:
 //
-//     err := f.InsertRow("Sheet1", 3)
+//     err := f.InsertRows("Sheet1", 3, 2)
 //
 // Use this method with caution, which will affect changes in references such
 // as formulas, charts, and so on. If there is any referenced value of the
 // worksheet, it will cause a file error when you open it. The excelize only
 // partially updates these references currently.
-func (f *File) InsertRow(sheet string, row int) error {
+func (f *File) InsertRows(sheet string, row, n int) error {
        if row < 1 {
                return newInvalidRowNumberError(row)
        }
-       return f.adjustHelper(sheet, rows, row, 1)
+       if row >= TotalRows || n >= TotalRows {
+               return ErrMaxRows
+       }
+       if n < 1 {
+               return ErrParameterInvalid
+       }
+       return f.adjustHelper(sheet, rows, row, n)
 }
 
 // DuplicateRow inserts a copy of specified row (by its Excel row number) below
index cac142b..829a27a 100644 (file)
@@ -318,7 +318,7 @@ func TestRemoveRow(t *testing.T) {
        assert.EqualError(t, f.RemoveRow("SheetN", 1), `sheet SheetN does not exist`)
 }
 
-func TestInsertRow(t *testing.T) {
+func TestInsertRows(t *testing.T) {
        f := NewFile()
        sheet1 := f.GetSheetName(0)
        r, err := f.workSheetReader(sheet1)
@@ -331,36 +331,44 @@ func TestInsertRow(t *testing.T) {
 
        assert.NoError(t, f.SetCellHyperLink(sheet1, "A5", "https://github.com/xuri/excelize", "External"))
 
-       assert.EqualError(t, f.InsertRow(sheet1, -1), newInvalidRowNumberError(-1).Error())
-
-       assert.EqualError(t, f.InsertRow(sheet1, 0), newInvalidRowNumberError(0).Error())
-
-       assert.NoError(t, f.InsertRow(sheet1, 1))
+       assert.NoError(t, f.InsertRows(sheet1, 1, 1))
        if !assert.Len(t, r.SheetData.Row, rowCount+1) {
                t.FailNow()
        }
 
-       assert.NoError(t, f.InsertRow(sheet1, 4))
+       assert.NoError(t, f.InsertRows(sheet1, 4, 1))
        if !assert.Len(t, r.SheetData.Row, rowCount+2) {
                t.FailNow()
        }
 
-       assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRow.xlsx")))
+       assert.NoError(t, f.InsertRows(sheet1, 4, 2))
+       if !assert.Len(t, r.SheetData.Row, rowCount+4) {
+               t.FailNow()
+       }
+
+       assert.EqualError(t, f.InsertRows(sheet1, -1, 1), newInvalidRowNumberError(-1).Error())
+       assert.EqualError(t, f.InsertRows(sheet1, 0, 1), newInvalidRowNumberError(0).Error())
+       assert.EqualError(t, f.InsertRows(sheet1, 4, 0), ErrParameterInvalid.Error())
+       assert.EqualError(t, f.InsertRows(sheet1, 4, TotalRows), ErrMaxRows.Error())
+       assert.EqualError(t, f.InsertRows(sheet1, 4, TotalRows-5), ErrMaxRows.Error())
+       assert.EqualError(t, f.InsertRows(sheet1, TotalRows, 1), ErrMaxRows.Error())
+
+       assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRows.xlsx")))
 }
 
 // Test internal structure state after insert operations. It is important
 // for insert workflow to be constant to avoid side effect with functions
 // related to internal structure.
-func TestInsertRowInEmptyFile(t *testing.T) {
+func TestInsertRowsInEmptyFile(t *testing.T) {
        f := NewFile()
        sheet1 := f.GetSheetName(0)
        r, err := f.workSheetReader(sheet1)
        assert.NoError(t, err)
-       assert.NoError(t, f.InsertRow(sheet1, 1))
+       assert.NoError(t, f.InsertRows(sheet1, 1, 1))
        assert.Len(t, r.SheetData.Row, 0)
-       assert.NoError(t, f.InsertRow(sheet1, 2))
+       assert.NoError(t, f.InsertRows(sheet1, 2, 1))
        assert.Len(t, r.SheetData.Row, 0)
-       assert.NoError(t, f.InsertRow(sheet1, 99))
+       assert.NoError(t, f.InsertRows(sheet1, 99, 1))
        assert.Len(t, r.SheetData.Row, 0)
        assert.NoError(t, f.SaveAs(filepath.Join("test", "TestInsertRowInEmptyFile.xlsx")))
 }