Skip to content

Commit 0f9170a

Browse files
mlh758xuri
authored andcommitted
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
1 parent a88459d commit 0f9170a

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

cell_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,15 @@ func ExampleFile_SetCellFloat() {
8282
fmt.Println(val)
8383
// Output: 3.14
8484
}
85+
86+
func BenchmarkSetCellValue(b *testing.B) {
87+
values := []string{"First", "Second", "Third", "Fourth", "Fifth", "Sixth"}
88+
cols := []string{"A", "B", "C", "D", "E", "F"}
89+
f := NewFile()
90+
b.ResetTimer()
91+
for i := 0; i < b.N; i++ {
92+
for j := 0; j < len(values); j++ {
93+
f.SetCellValue("Sheet1", fmt.Sprint(cols[j], i), values[j])
94+
}
95+
}
96+
}

rows.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ func (f *File) InsertRow(sheet string, row int) error {
446446
return f.adjustHelper(sheet, rows, row, 1)
447447
}
448448

449-
// DuplicateRow inserts a copy of specified row (by it Excel row number) below
449+
// DuplicateRow inserts a copy of specified row (by its Excel row number) below
450450
//
451451
// err := xlsx.DuplicateRow("Sheet1", 2)
452452
//

sheet.go

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,8 +1072,8 @@ func (f *File) workSheetRelsWriter() {
10721072
}
10731073
}
10741074

1075-
// fillSheetData fill missing row and cell XML data to made it continuous from
1076-
// first cell [1, 1] to last cell [col, row]
1075+
// fillSheetData ensures there are enough rows, and columns in the chosen
1076+
// row to accept data. Missing rows are backfilled and given their row number
10771077
func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) {
10781078
rowCount := len(xlsx.SheetData.Row)
10791079
if rowCount < row {
@@ -1082,14 +1082,23 @@ func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) {
10821082
xlsx.SheetData.Row = append(xlsx.SheetData.Row, xlsxRow{R: rowIdx + 1})
10831083
}
10841084
}
1085-
for rowIdx := range xlsx.SheetData.Row {
1086-
rowData := &xlsx.SheetData.Row[rowIdx] // take reference
1087-
cellCount := len(rowData.C)
1088-
if cellCount < col {
1089-
for colIdx := cellCount; colIdx < col; colIdx++ {
1090-
cellName, _ := CoordinatesToCellName(colIdx+1, rowIdx+1)
1091-
rowData.C = append(rowData.C, xlsxC{R: cellName})
1092-
}
1085+
rowData := &xlsx.SheetData.Row[row-1]
1086+
fillColumns(rowData, col, row)
1087+
}
1088+
1089+
func fillColumns(rowData *xlsxRow, col, row int) {
1090+
cellCount := len(rowData.C)
1091+
if cellCount < col {
1092+
for colIdx := cellCount; colIdx < col; colIdx++ {
1093+
cellName, _ := CoordinatesToCellName(colIdx+1, row)
1094+
rowData.C = append(rowData.C, xlsxC{R: cellName})
10931095
}
10941096
}
10951097
}
1098+
1099+
func makeContiguousColumns(xlsx *xlsxWorksheet, fromRow, toRow, colCount int) {
1100+
for ; fromRow < toRow; fromRow++ {
1101+
rowData := &xlsx.SheetData.Row[fromRow-1]
1102+
fillColumns(rowData, colCount, fromRow)
1103+
}
1104+
}

styles.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2373,6 +2373,7 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
23732373
return err
23742374
}
23752375
prepareSheetXML(xlsx, vcol, vrow)
2376+
makeContiguousColumns(xlsx, hrow, vrow, vcol)
23762377

23772378
for r := hrowIdx; r <= vrowIdx; r++ {
23782379
for k := hcolIdx; k <= vcolIdx; k++ {

0 commit comments

Comments
 (0)