Explorar o código

Duplicate row (#317)

* go mod tidy applied

* File.DuplicateRow() method added
Veniamin Albaev %!s(int64=7) %!d(string=hai) anos
pai
achega
7b7ca99f5d
Modificáronse 5 ficheiros con 132 adicións e 9 borrados
  1. 9 8
      excelize.go
  2. 67 0
      excelize_test.go
  3. 7 0
      go.mod
  4. 8 0
      go.sum
  5. 41 1
      rows.go

+ 9 - 8
excelize.go

@@ -238,18 +238,19 @@ func (f *File) adjustRowDimensions(xlsx *xlsxWorksheet, rowIndex, offset int) {
 	}
 	for i, r := range xlsx.SheetData.Row {
 		if r.R >= rowIndex {
-			xlsx.SheetData.Row[i].R += offset
-			for k, v := range xlsx.SheetData.Row[i].C {
-				axis := v.R
-				col := string(strings.Map(letterOnlyMapF, axis))
-				row, _ := strconv.Atoi(strings.Map(intOnlyMapF, axis))
-				xAxis := row + offset
-				xlsx.SheetData.Row[i].C[k].R = col + strconv.Itoa(xAxis)
-			}
+			f.ajustSingleRowDimensions(&xlsx.SheetData.Row[i], offset)
 		}
 	}
 }
 
+func (f *File) ajustSingleRowDimensions(r *xlsxRow, offset int) {
+	r.R += offset
+	for i, col := range r.C {
+		row, _ := strconv.Atoi(strings.Map(intOnlyMapF, col.R))
+		r.C[i].R = string(strings.Map(letterOnlyMapF, col.R)) + strconv.Itoa(row+offset)
+	}
+}
+
 // adjustHyperlinks provides a function to update hyperlinks when inserting or
 // deleting rows or columns.
 func (f *File) adjustHyperlinks(sheet string, column, rowIndex, offset int) {

+ 67 - 0
excelize_test.go

@@ -12,6 +12,8 @@ import (
 	"strings"
 	"testing"
 	"time"
+
+	"github.com/stretchr/testify/assert"
 )
 
 func TestOpenFile(t *testing.T) {
@@ -1029,6 +1031,71 @@ func TestInsertRow(t *testing.T) {
 	}
 }
 
+func TestDuplicateRow(t *testing.T) {
+	const (
+		file    = "./test/Book_DuplicateRow_%s.xlsx"
+		sheet   = "Sheet1"
+		a1      = "A1"
+		b1      = "B1"
+		a2      = "A2"
+		b2      = "B2"
+		a3      = "A3"
+		b3      = "B3"
+		a4      = "A4"
+		b4      = "B4"
+		a1Value = "A1 value"
+		a2Value = "A2 value"
+		a3Value = "A3 value"
+		bnValue = "Bn value"
+	)
+	xlsx := NewFile()
+	xlsx.SetCellStr(sheet, a1, a1Value)
+	xlsx.SetCellStr(sheet, b1, bnValue)
+
+	t.Run("FromSingleRow", func(t *testing.T) {
+		xlsx.DuplicateRow(sheet, 1)
+		xlsx.DuplicateRow(sheet, 2)
+
+		if assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(file, "SignleRow"))) {
+			assert.Equal(t, a1Value, xlsx.GetCellValue(sheet, a1))
+			assert.Equal(t, a1Value, xlsx.GetCellValue(sheet, a2))
+			assert.Equal(t, a1Value, xlsx.GetCellValue(sheet, a3))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b1))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b2))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b3))
+		}
+	})
+
+	t.Run("UpdateDuplicatedRows", func(t *testing.T) {
+		xlsx.SetCellStr(sheet, a2, a2Value)
+		xlsx.SetCellStr(sheet, a3, a3Value)
+
+		if assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(file, "Updated"))) {
+			assert.Equal(t, a1Value, xlsx.GetCellValue(sheet, a1))
+			assert.Equal(t, a2Value, xlsx.GetCellValue(sheet, a2))
+			assert.Equal(t, a3Value, xlsx.GetCellValue(sheet, a3))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b1))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b2))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b3))
+		}
+	})
+
+	t.Run("FromFirstOfMultipleRows", func(t *testing.T) {
+		xlsx.DuplicateRow(sheet, 1)
+
+		if assert.NoError(t, xlsx.SaveAs(fmt.Sprintf(file, "FirstOfMultipleRows"))) {
+			assert.Equal(t, a1Value, xlsx.GetCellValue(sheet, a1))
+			assert.Equal(t, a1Value, xlsx.GetCellValue(sheet, a2))
+			assert.Equal(t, a2Value, xlsx.GetCellValue(sheet, a3))
+			assert.Equal(t, a3Value, xlsx.GetCellValue(sheet, a4))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b1))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b2))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b3))
+			assert.Equal(t, bnValue, xlsx.GetCellValue(sheet, b4))
+		}
+	})
+}
+
 func TestSetPane(t *testing.T) {
 	xlsx := NewFile()
 	xlsx.SetPanes("Sheet1", `{"freeze":false,"split":false}`)

+ 7 - 0
go.mod

@@ -1 +1,8 @@
 module github.com/360EntSecGroup-Skylar/excelize
+
+require (
+	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826
+	github.com/pmezard/go-difflib v1.0.0 // indirect
+	github.com/stretchr/testify v1.2.2
+)

+ 8 - 0
go.sum

@@ -0,0 +1,8 @@
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
+github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

+ 41 - 1
rows.go

@@ -359,7 +359,7 @@ func (f *File) RemoveRow(sheet string, row int) {
 	}
 }
 
-// InsertRow provides a function to insert a new row before given row index.
+// InsertRow provides a function to insert a new row after given row index.
 // For example, create a new row before row 3 in Sheet1:
 //
 //    xlsx.InsertRow("Sheet1", 2)
@@ -372,6 +372,46 @@ func (f *File) InsertRow(sheet string, row int) {
 	f.adjustHelper(sheet, -1, row, 1)
 }
 
+// DuplicateRow inserts a copy of specified row below specified
+//
+//    xlsx.DuplicateRow("Sheet1", 2)
+//
+func (f *File) DuplicateRow(sheet string, row int) {
+	if row < 0 {
+		return
+	}
+	row2 := row + 1
+	f.adjustHelper(sheet, -1, row2, 1)
+
+	xlsx := f.workSheetReader(sheet)
+	idx := -1
+	idx2 := -1
+
+	for i, r := range xlsx.SheetData.Row {
+		if r.R == row {
+			idx = i
+		} else if r.R == row2 {
+			idx2 = i
+		}
+		if idx != -1 && idx2 != -1 {
+			break
+		}
+	}
+
+	if idx == -1 || (idx2 == -1 && len(xlsx.SheetData.Row) >= row2) {
+		return
+	}
+	rowData := xlsx.SheetData.Row[idx]
+	cols := make([]xlsxC, 0, len(rowData.C))
+	rowData.C = append(cols, rowData.C...)
+	f.ajustSingleRowDimensions(&rowData, 1)
+	if idx2 != -1 {
+		xlsx.SheetData.Row[idx2] = rowData
+	} else {
+		xlsx.SheetData.Row = append(xlsx.SheetData.Row, rowData)
+	}
+}
+
 // checkRow provides a function to check and fill each column element for all
 // rows and make that is continuous in a worksheet of XML. For example:
 //