summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael <osiris2918@gmail.com>2019-04-16 01:50:16 -0500
committerxuri <xuri.me@gmail.com>2019-04-16 14:50:16 +0800
commit0f9170a03b9fe19c1c22687fba8bcbdfd69a6347 (patch)
treebc7e73c690d274548530199de14c4d668d45c118
parenta88459d5f1e83006ba421f334a1513d1c231eb6b (diff)
Resolve #382, rewrite prepareSheetXML to scale linearly (#383)
* Rewrite prepareSheetXML to scale linearly We don't need to backfill columns into every row for most purposes Provided makeContiguousColumns for setting styles where we do need it for a specific region. Added a benchmark to monitor progress. For 50,000 rows this went from about 11 seconds to 1 second. The improvements are more dramatic as the row/column count increases. * Assigning that row value was redundant
-rw-r--r--cell_test.go12
-rw-r--r--rows.go2
-rw-r--r--sheet.go29
-rw-r--r--styles.go1
4 files changed, 33 insertions, 11 deletions
diff --git a/cell_test.go b/cell_test.go
index 7b1381f..d4a5b02 100644
--- a/cell_test.go
+++ b/cell_test.go
@@ -82,3 +82,15 @@ func ExampleFile_SetCellFloat() {
fmt.Println(val)
// Output: 3.14
}
+
+func BenchmarkSetCellValue(b *testing.B) {
+ values := []string{"First", "Second", "Third", "Fourth", "Fifth", "Sixth"}
+ cols := []string{"A", "B", "C", "D", "E", "F"}
+ f := NewFile()
+ b.ResetTimer()
+ for i := 0; i < b.N; i++ {
+ for j := 0; j < len(values); j++ {
+ f.SetCellValue("Sheet1", fmt.Sprint(cols[j], i), values[j])
+ }
+ }
+}
diff --git a/rows.go b/rows.go
index 7de18d3..ff268cf 100644
--- a/rows.go
+++ b/rows.go
@@ -446,7 +446,7 @@ func (f *File) InsertRow(sheet string, row int) error {
return f.adjustHelper(sheet, rows, row, 1)
}
-// DuplicateRow inserts a copy of specified row (by it Excel row number) below
+// DuplicateRow inserts a copy of specified row (by its Excel row number) below
//
// err := xlsx.DuplicateRow("Sheet1", 2)
//
diff --git a/sheet.go b/sheet.go
index 72d8921..5c681d2 100644
--- a/sheet.go
+++ b/sheet.go
@@ -1072,8 +1072,8 @@ func (f *File) workSheetRelsWriter() {
}
}
-// fillSheetData fill missing row and cell XML data to made it continuous from
-// first cell [1, 1] to last cell [col, row]
+// fillSheetData ensures there are enough rows, and columns in the chosen
+// row to accept data. Missing rows are backfilled and given their row number
func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) {
rowCount := len(xlsx.SheetData.Row)
if rowCount < row {
@@ -1082,14 +1082,23 @@ func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) {
xlsx.SheetData.Row = append(xlsx.SheetData.Row, xlsxRow{R: rowIdx + 1})
}
}
- for rowIdx := range xlsx.SheetData.Row {
- rowData := &xlsx.SheetData.Row[rowIdx] // take reference
- cellCount := len(rowData.C)
- if cellCount < col {
- for colIdx := cellCount; colIdx < col; colIdx++ {
- cellName, _ := CoordinatesToCellName(colIdx+1, rowIdx+1)
- rowData.C = append(rowData.C, xlsxC{R: cellName})
- }
+ rowData := &xlsx.SheetData.Row[row-1]
+ fillColumns(rowData, col, row)
+}
+
+func fillColumns(rowData *xlsxRow, col, row int) {
+ cellCount := len(rowData.C)
+ if cellCount < col {
+ for colIdx := cellCount; colIdx < col; colIdx++ {
+ cellName, _ := CoordinatesToCellName(colIdx+1, row)
+ rowData.C = append(rowData.C, xlsxC{R: cellName})
}
}
}
+
+func makeContiguousColumns(xlsx *xlsxWorksheet, fromRow, toRow, colCount int) {
+ for ; fromRow < toRow; fromRow++ {
+ rowData := &xlsx.SheetData.Row[fromRow-1]
+ fillColumns(rowData, colCount, fromRow)
+ }
+}
diff --git a/styles.go b/styles.go
index a515756..81d03be 100644
--- a/styles.go
+++ b/styles.go
@@ -2373,6 +2373,7 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
return err
}
prepareSheetXML(xlsx, vcol, vrow)
+ makeContiguousColumns(xlsx, hrow, vrow, vcol)
for r := hrowIdx; r <= vrowIdx; r++ {
for k := hcolIdx; k <= vcolIdx; k++ {