未验证 提交 bf9a8355 编写于 作者: H Harris

Reduce allocations when writing

Fix #494

If a row is full, don't bother allocating a new one, just return it.

Use the last populated row as a hint for the size of new rows.

Simplify checkSheet to remove row map
上级 6abf8bf9
...@@ -155,20 +155,12 @@ func checkSheet(xlsx *xlsxWorksheet) { ...@@ -155,20 +155,12 @@ func checkSheet(xlsx *xlsxWorksheet) {
row = lastRow row = lastRow
} }
} }
sheetData := xlsxSheetData{} sheetData := xlsxSheetData{Row: make([]xlsxRow, row)}
existsRows := map[int]int{} for _, r := range xlsx.SheetData.Row {
for k := range xlsx.SheetData.Row { sheetData.Row[r.R-1] = r
existsRows[xlsx.SheetData.Row[k].R] = k
} }
for i := 0; i < row; i++ { for i := 1; i <= row; i++ {
_, ok := existsRows[i+1] sheetData.Row[i-1].R = i
if ok {
sheetData.Row = append(sheetData.Row, xlsx.SheetData.Row[existsRows[i+1]])
} else {
sheetData.Row = append(sheetData.Row, xlsxRow{
R: i + 1,
})
}
} }
xlsx.SheetData = sheetData xlsx.SheetData = sheetData
} }
......
package excelize
import (
"testing"
)
func BenchmarkWrite(b *testing.B) {
const s = "This is test data"
for i := 0; i < b.N; i++ {
f := NewFile()
for row := 1; row <= 10000; row++ {
for col := 1; col <= 20; col++ {
val, err := CoordinatesToCellName(col, row)
if err != nil {
panic(err)
}
f.SetCellDefault("Sheet1", val, s)
}
}
// Save xlsx file by the given path.
err := f.SaveAs("./test.xlsx")
if err != nil {
panic(err)
}
}
}
...@@ -117,12 +117,19 @@ func (f *File) workSheetWriter() { ...@@ -117,12 +117,19 @@ func (f *File) workSheetWriter() {
} }
} }
// trimCell provides a function to trim blank cells which created by completeCol. // trimCell provides a function to trim blank cells which created by fillColumns.
func trimCell(column []xlsxC) []xlsxC { func trimCell(column []xlsxC) []xlsxC {
rowFull := true
for i := range column {
rowFull = column[i].hasValue() && rowFull
}
if rowFull {
return column
}
col := make([]xlsxC, len(column)) col := make([]xlsxC, len(column))
i := 0 i := 0
for _, c := range column { for _, c := range column {
if c.S != 0 || c.V != "" || c.F != nil || c.T != "" { if c.hasValue() {
col[i] = c col[i] = c
i++ i++
} }
...@@ -1404,12 +1411,17 @@ func (f *File) relsReader(path string) *xlsxRelationships { ...@@ -1404,12 +1411,17 @@ func (f *File) relsReader(path string) *xlsxRelationships {
// fillSheetData ensures there are enough rows, and columns in the chosen // fillSheetData ensures there are enough rows, and columns in the chosen
// row to accept data. Missing rows are backfilled and given their row number // row to accept data. Missing rows are backfilled and given their row number
// Uses the last populated row as a hint for the size of the next row to add
func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) { func prepareSheetXML(xlsx *xlsxWorksheet, col int, row int) {
rowCount := len(xlsx.SheetData.Row) rowCount := len(xlsx.SheetData.Row)
sizeHint := 0
if rowCount > 0 {
sizeHint = len(xlsx.SheetData.Row[rowCount-1].C)
}
if rowCount < row { if rowCount < row {
// append missing rows // append missing rows
for rowIdx := rowCount; rowIdx < row; rowIdx++ { for rowIdx := rowCount; rowIdx < row; rowIdx++ {
xlsx.SheetData.Row = append(xlsx.SheetData.Row, xlsxRow{R: rowIdx + 1}) xlsx.SheetData.Row = append(xlsx.SheetData.Row, xlsxRow{R: rowIdx + 1, C: make([]xlsxC, 0, sizeHint)})
} }
} }
rowData := &xlsx.SheetData.Row[row-1] rowData := &xlsx.SheetData.Row[row-1]
......
...@@ -430,6 +430,10 @@ type xlsxC struct { ...@@ -430,6 +430,10 @@ type xlsxC struct {
XMLSpace xml.Attr `xml:"space,attr,omitempty"` XMLSpace xml.Attr `xml:"space,attr,omitempty"`
} }
func (c *xlsxC) hasValue() bool {
return c.S != 0 || c.V != "" || c.F != nil || c.T != ""
}
// xlsxF directly maps the f element in the namespace // xlsxF directly maps the f element in the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main - currently I have // http://schemas.openxmlformats.org/spreadsheetml/2006/main - currently I have
// not checked it for completeness - it does as much as I need. // not checked it for completeness - it does as much as I need.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册