mirror of
https://github.com/unidoc/unioffice.git
synced 2025-04-25 13:48:53 +08:00
spreadsheet: add fast paths for appending rows/cells
This commit is contained in:
parent
382c157c11
commit
9b89ae1f12
@ -61,20 +61,34 @@ func (r Row) SetHidden(hidden bool) {
|
||||
|
||||
// AddCell adds a cell to a spreadsheet.
|
||||
func (r Row) AddCell() Cell {
|
||||
c := spreadsheetml.NewCT_Cell()
|
||||
c.TAttr = spreadsheetml.ST_CellTypeN
|
||||
|
||||
r.x.C = append(r.x.C, c)
|
||||
nextIdx := uint32(0)
|
||||
for _, c := range r.x.C {
|
||||
if c.RAttr != nil {
|
||||
col, _, _ := ParseCellReference(*c.RAttr)
|
||||
if col := ColumnToIndex(col); col >= nextIdx {
|
||||
nextIdx = col + 1
|
||||
}
|
||||
numCells := uint32(len(r.x.C))
|
||||
var nextCellID *string
|
||||
if numCells > 0 {
|
||||
prevCellName := gooxml.Stringf("%s%d", IndexToColumn(numCells-1), r.RowNumber())
|
||||
// previous cell has an expected name
|
||||
if r.x.C[numCells-1].RAttr != nil && *r.x.C[numCells-1].RAttr == *prevCellName {
|
||||
nextCellID = gooxml.Stringf("%s%d", IndexToColumn(numCells), r.RowNumber())
|
||||
}
|
||||
}
|
||||
c.RAttr = gooxml.Stringf("%s%d", IndexToColumn(nextIdx), r.RowNumber())
|
||||
|
||||
c := spreadsheetml.NewCT_Cell()
|
||||
c.TAttr = spreadsheetml.ST_CellTypeN
|
||||
r.x.C = append(r.x.C, c)
|
||||
|
||||
// fast path failed, so find the last cell and add another
|
||||
if nextCellID == nil {
|
||||
nextIdx := uint32(0)
|
||||
for _, c := range r.x.C {
|
||||
if c.RAttr != nil {
|
||||
col, _, _ := ParseCellReference(*c.RAttr)
|
||||
if col := ColumnToIndex(col); col >= nextIdx {
|
||||
nextIdx = col + 1
|
||||
}
|
||||
}
|
||||
}
|
||||
nextCellID = gooxml.Stringf("%s%d", IndexToColumn(nextIdx), r.RowNumber())
|
||||
}
|
||||
c.RAttr = nextCellID
|
||||
return Cell{r.w, r.s, r.x, c}
|
||||
}
|
||||
|
||||
|
@ -80,11 +80,27 @@ func (s Sheet) AddNumberedRow(rowNum uint32) Row {
|
||||
return Row{s.w, s.x, r}
|
||||
}
|
||||
|
||||
// addNumberedRowFast is a fast path that can be used when adding consecutive
|
||||
// rows and not skipping any.
|
||||
func (s Sheet) addNumberedRowFast(rowNum uint32) Row {
|
||||
r := sml.NewCT_Row()
|
||||
r.RAttr = gooxml.Uint32(rowNum)
|
||||
s.x.SheetData.Row = append(s.x.SheetData.Row, r)
|
||||
return Row{s.w, s.x, r}
|
||||
}
|
||||
|
||||
// AddRow adds a new row to a sheet. You can mix this with numbered rows,
|
||||
// however it will get confusing. You should prefer to use either automatically
|
||||
// numbered rows with AddRow or manually numbered rows with Row/AddNumberedRow
|
||||
func (s Sheet) AddRow() Row {
|
||||
maxRowID := uint32(0)
|
||||
|
||||
numRows := uint32(len(s.x.SheetData.Row))
|
||||
// fast path, adding consecutive rows
|
||||
if numRows > 0 && s.x.SheetData.Row[numRows-1].RAttr != nil && *s.x.SheetData.Row[numRows-1].RAttr == numRows {
|
||||
return s.addNumberedRowFast(numRows + 1)
|
||||
}
|
||||
|
||||
// find the max row number
|
||||
for _, r := range s.x.SheetData.Row {
|
||||
if r.RAttr != nil && *r.RAttr > maxRowID {
|
||||
|
25
spreadsheet/sheet_bench_test.go
Normal file
25
spreadsheet/sheet_bench_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
package spreadsheet_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"baliance.com/gooxml/spreadsheet"
|
||||
)
|
||||
|
||||
func BenchmarkAddRow(b *testing.B) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
for r := 0; r < b.N; r++ {
|
||||
sheet.AddRow()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAddCell(b *testing.B) {
|
||||
ss := spreadsheet.New()
|
||||
sheet := ss.AddSheet()
|
||||
row := sheet.AddRow()
|
||||
|
||||
for c := 0; c < b.N; c++ {
|
||||
row.AddCell()
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user