From fe505d663197c11619ab36c9dc352a42646a7dbb Mon Sep 17 00:00:00 2001 From: tom twinkle Date: Fri, 19 Aug 2022 18:24:38 +0900 Subject: [PATCH 1/3] add async method draft --- excelizeam.go | 66 +++++++++++++++++++++++ excelizeam_test.go | 130 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 195 insertions(+), 1 deletion(-) diff --git a/excelizeam.go b/excelizeam.go index 9332dd4..b710d38 100644 --- a/excelizeam.go +++ b/excelizeam.go @@ -33,12 +33,23 @@ type Excelizeam interface { // SetCellValue Set value and style to cell SetCellValue(colIndex, rowIndex int, value interface{}, style *excelize.Style, override bool) error + // SetCellValueAsync Set value and style to cell asynchronously + SetCellValueAsync(colIndex, rowIndex int, value interface{}, style *excelize.Style) + // SetStyleCell Set style to cell SetStyleCell(colIndex, rowIndex int, style excelize.Style, override bool) error + // SetStyleCellAsync Set style to cell asynchronously + SetStyleCellAsync(colIndex, rowIndex int, style excelize.Style) + // SetStyleCellRange Set style to cell with range SetStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style, override bool) error + // SetStyleCellRangeAsync Set style to cell with range asynchronously + SetStyleCellRangeAsync(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style) + // SetBorderRange Set border around cell range SetBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange, override bool) error + // SetBorderRangeAsync Set border around cell range asynchronously + SetBorderRangeAsync(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange) // Write StreamWriter Write(w io.Writer) error @@ -157,7 +168,20 @@ func (e *excelizeam) MergeCell(startColIndex, startRowIndex, endColIndex, endRow return e.sw.MergeCell(startCell, endCell) } +func (e *excelizeam) SetCellValueAsync(colIndex, rowIndex int, value interface{}, style *excelize.Style) { + e.eg.Go(func() error { + return e.setCellValue(colIndex, rowIndex, value, style, false) + }) +} + func (e *excelizeam) SetCellValue(colIndex, rowIndex int, value interface{}, style *excelize.Style, override bool) error { + if err := e.eg.Wait(); err != nil { + return err + } + return e.setCellValue(colIndex, rowIndex, value, style, override) +} + +func (e *excelizeam) setCellValue(colIndex, rowIndex int, value interface{}, style *excelize.Style, override bool) error { if e.maxCol < colIndex { e.maxCol = colIndex } @@ -214,7 +238,20 @@ func (e *excelizeam) SetCellValue(colIndex, rowIndex int, value interface{}, sty return nil } +func (e *excelizeam) SetStyleCellAsync(colIndex, rowIndex int, style excelize.Style) { + e.eg.Go(func() error { + return e.setStyleCell(colIndex, rowIndex, style, false) + }) +} + func (e *excelizeam) SetStyleCell(colIndex, rowIndex int, style excelize.Style, override bool) error { + if err := e.eg.Wait(); err != nil { + return err + } + return e.setStyleCell(colIndex, rowIndex, style, override) +} + +func (e *excelizeam) setStyleCell(colIndex, rowIndex int, style excelize.Style, override bool) error { if e.maxCol < colIndex { e.maxCol = colIndex } @@ -263,7 +300,20 @@ func (e *excelizeam) SetStyleCell(colIndex, rowIndex int, style excelize.Style, return nil } +func (e *excelizeam) SetStyleCellRangeAsync(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style) { + e.eg.Go(func() error { + return e.setStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex, style, false) + }) +} + func (e *excelizeam) SetStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style, override bool) error { + if err := e.eg.Wait(); err != nil { + return err + } + return e.setStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex, style, override) +} + +func (e *excelizeam) setStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style, override bool) error { if e.maxCol < endColIndex { e.maxCol = endColIndex } @@ -316,7 +366,20 @@ func (e *excelizeam) SetStyleCellRange(startColIndex, startRowIndex, endColIndex return nil } +func (e *excelizeam) SetBorderRangeAsync(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange) { + e.eg.Go(func() error { + return e.setBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex, borderRange, false) + }) +} + func (e *excelizeam) SetBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange, override bool) error { + if err := e.eg.Wait(); err != nil { + return err + } + return e.setBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex, borderRange, override) +} + +func (e *excelizeam) setBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange, override bool) error { if e.maxCol < endColIndex { e.maxCol = endColIndex } @@ -666,6 +729,9 @@ func (e *excelizeam) Write(w io.Writer) error { } func (e *excelizeam) writeStream() error { + if err := e.eg.Wait(); err != nil { + return err + } defaultStyleCells := make([]interface{}, e.maxCol) if e.defaultBorder != nil { for i := 0; i < e.maxCol; i++ { diff --git a/excelizeam_test.go b/excelizeam_test.go index bd5b4a5..34fcedb 100644 --- a/excelizeam_test.go +++ b/excelizeam_test.go @@ -15,7 +15,7 @@ import ( "github.com/xuri/excelize/v2" ) -func TestExcelizeam_Write(t *testing.T) { +func TestExcelizeam_Sync(t *testing.T) { tests := map[string]struct { testFunc func(w excelizeam.Excelizeam) error wantErr error @@ -276,6 +276,134 @@ func TestExcelizeam_Write(t *testing.T) { } } +func TestExcelizeam_Async(t *testing.T) { + tests := map[string]struct { + testFunc func(w excelizeam.Excelizeam) + wantErr error + }{ + "SetCellValue-with_not_style": { + testFunc: func(w excelizeam.Excelizeam) { + w.SetCellValueAsync(1, 1, "test", nil) + }, + }, + "SetCellValue-with_not_style_override_error": { + testFunc: func(w excelizeam.Excelizeam) { + w.SetCellValue(1, 1, "test1", nil, false) + // can override value + w.SetCellValueAsync(1, 1, "test2", nil) + }, + wantErr: excelizeam.ErrOverrideCellValue, + }, + "SetCellValue-with_not_style_multiple_rows_cols_no_sort": { + testFunc: func(w excelizeam.Excelizeam) { + for rowIdx := 1; rowIdx <= 10; rowIdx++ { + for colIdx := 1; colIdx <= 10; colIdx++ { + w.SetCellValueAsync(colIdx, rowIdx, fmt.Sprintf("test%d-%d", rowIdx, colIdx), nil) + } + } + }, + }, + "SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd": { + testFunc: func(w excelizeam.Excelizeam) { + for rowIdx := 1; rowIdx <= 10; rowIdx++ { + if rowIdx%2 == 0 { + continue + } + for colIdx := 1; colIdx <= 10; colIdx++ { + if colIdx%2 == 0 { + continue + } + w.SetCellValueAsync(colIdx, rowIdx, fmt.Sprintf("test%d-%d", rowIdx, colIdx), nil) + } + } + }, + }, + "SetCellValue-with_not_style_multiple_rows_cols_sort": { + testFunc: func(w excelizeam.Excelizeam) { + for colIdx := 1; colIdx <= 10; colIdx++ { + for rowIdx := 1; rowIdx <= 10; rowIdx++ { + w.SetCellValueAsync(colIdx, rowIdx, fmt.Sprintf("test%d-%d", rowIdx, colIdx), nil) + } + } + }, + }, + "SetCellValue-with_style_border_fill_font_alignment": { + testFunc: func(w excelizeam.Excelizeam) { + w.SetCellValueAsync(2, 2, "test", &excelize.Style{ + Border: excelizestyle.BorderAround(excelizestyle.BorderStyleContinuous2, excelizestyle.BorderColorBlack), + Fill: excelizestyle.Fill(excelizestyle.FillPatternSolid, "#315D3C"), + Font: &excelize.Font{ + Bold: true, + Size: 8, + Color: "#718DDC", + }, + Alignment: excelizestyle.Alignment(excelizestyle.AlignmentHorizontalCenter, excelizestyle.AlignmentVerticalCenter, true), + }) + }, + }, + "SetCellValue-with_style_border_fill_font_alignment_override_value_error": { + testFunc: func(w excelizeam.Excelizeam) { + w.SetCellValue(2, 2, "test1", &excelize.Style{ + Border: excelizestyle.BorderAround(excelizestyle.BorderStyleContinuous2, excelizestyle.BorderColorBlack), + }, false) + w.SetCellValueAsync(2, 2, "", &excelize.Style{ + Border: []excelize.Border{ + excelizestyle.Border(excelizestyle.BorderPositionRight, excelizestyle.BorderStyleDash2, excelizestyle.BorderColorBlack), + }, + }) + }, + wantErr: excelizeam.ErrOverrideCellValue, + }, + "SetCellValue-with_style_border_fill_font_alignment_override_style_error": { + testFunc: func(w excelizeam.Excelizeam) { + w.SetCellValue(2, 2, "test1", &excelize.Style{ + Border: excelizestyle.BorderAround(excelizestyle.BorderStyleContinuous2, excelizestyle.BorderColorBlack), + }, false) + w.SetCellValueAsync(2, 2, nil, &excelize.Style{ + Border: []excelize.Border{ + excelizestyle.Border(excelizestyle.BorderPositionRight, excelizestyle.BorderStyleDash2, excelizestyle.BorderColorBlack), + }, + }) + }, + wantErr: excelizeam.ErrOverrideCellStyle, + }, + } + + for n, v := range tests { + name := n + tt := v + t.Run(name, func(t *testing.T) { + w, err := excelizeam.New("test") + assert.NoError(t, err) + tt.testFunc(w) + var buf bytes.Buffer + err = w.Write(&buf) + if tt.wantErr != nil { + assert.ErrorIs(t, err, tt.wantErr) + return + } + if !assert.NoError(t, err) { + return + } + + //f, err := os.Create("testdata/" + name + ".xlsx") + //assert.NoError(t, err) + //_, err = f.Write(buf.Bytes()) + //assert.NoError(t, err) + + expected, err := excelize.OpenFile("testdata/" + name + ".xlsx") + if !assert.NoError(t, err) { + return + } + actual, err := excelize.OpenReader(&buf) + if !assert.NoError(t, err) { + return + } + Assert(t, expected, actual) + }) + } +} + func BenchmarkExcelizeam(b *testing.B) { b.Run("Excelize", func(b *testing.B) { var buf bytes.Buffer From 5420fea3361683d052c3bbd64c3ab9284aa8692a Mon Sep 17 00:00:00 2001 From: tom twinkle Date: Mon, 22 Aug 2022 13:20:54 +0900 Subject: [PATCH 2/3] Change to cell-based caching instead of row-based caching --- excelizeam.go | 400 ++++++++++++++++++++++---------------------------- 1 file changed, 175 insertions(+), 225 deletions(-) diff --git a/excelizeam.go b/excelizeam.go index b710d38..9040dd6 100644 --- a/excelizeam.go +++ b/excelizeam.go @@ -2,6 +2,7 @@ package excelizeam import ( "errors" + "fmt" "io" "sync" @@ -60,11 +61,13 @@ type excelizeam struct { eg errgroup.Group - maxRow int - maxCol int + mu sync.Mutex + maxRow int + maxCol int + defaultBorder *DefaultBorders styleStore sync.Map - rowStore sync.Map + cellStore sync.Map } type DefaultBorders struct { @@ -94,15 +97,6 @@ type StoredStyle struct { Style *excelize.Style } -type StoredRow struct { - Row - Cols sync.Map -} - -type Row struct { - Index int -} - type Cell struct { StyleID int Value interface{} @@ -182,65 +176,59 @@ func (e *excelizeam) SetCellValue(colIndex, rowIndex int, value interface{}, sty } func (e *excelizeam) setCellValue(colIndex, rowIndex int, value interface{}, style *excelize.Style, override bool) error { - if e.maxCol < colIndex { - e.maxCol = colIndex - } - if e.maxRow < rowIndex { - e.maxRow = rowIndex - } - if _, ok := e.rowStore.Load(rowIndex); !ok { - e.rowStore.Store(rowIndex, &StoredRow{ - Row: Row{ - Index: rowIndex, - }, - }) - } - if cacherow, ok := e.rowStore.Load(rowIndex); ok { - r := cacherow.(*StoredRow) - if cachec, ok := r.Cols.Load(colIndex); ok { - c := cachec.(*Cell) - if c.Value != nil && value != nil && !override { - return ErrOverrideCellValue - } - if value != nil { - c.Value = value - } + e.checkMaxIndex(colIndex, rowIndex) + key := e.getCacheKey(colIndex, rowIndex) - if style != nil { - if c.StyleID > 0 { - if !override { - return ErrOverrideCellStyle - } - styleID, err := e.overrideStyle(c.StyleID, *style) - if err != nil { - return err - } - c.StyleID = styleID - } else { - styleID, err := e.getStyleID(style) - if err != nil { - return err - } - c.StyleID = styleID + if cached, ok := e.cellStore.Load(key); ok { + cell := cached.(*Cell) + if cell.Value != nil && value != nil && !override { + return ErrOverrideCellValue + } + if value != nil { + cell.Value = value + } + + if style != nil { + if cell.StyleID > 0 { + if !override { + return ErrOverrideCellStyle + } + styleID, err := e.overrideStyle(cell.StyleID, *style) + if err != nil { + return err } + cell.StyleID = styleID + } else { + styleID, err := e.getStyleID(style) + if err != nil { + return err + } + cell.StyleID = styleID } - return nil } styleID, err := e.getStyleID(style) if err != nil { return err } - r.Cols.Store(colIndex, &Cell{ - StyleID: styleID, - Value: value, - }) + cell.StyleID = styleID + return nil + } + + styleID, err := e.getStyleID(style) + if err != nil { + return err } + e.cellStore.Store(key, &Cell{ + StyleID: styleID, + Value: value, + }) return nil } func (e *excelizeam) SetStyleCellAsync(colIndex, rowIndex int, style excelize.Style) { e.eg.Go(func() error { - return e.setStyleCell(colIndex, rowIndex, style, false) + err := e.setStyleCell(colIndex, rowIndex, style, false) + return err }) } @@ -252,57 +240,37 @@ func (e *excelizeam) SetStyleCell(colIndex, rowIndex int, style excelize.Style, } func (e *excelizeam) setStyleCell(colIndex, rowIndex int, style excelize.Style, override bool) error { - if e.maxCol < colIndex { - e.maxCol = colIndex - } - if e.maxRow < rowIndex { - e.maxRow = rowIndex - } - - if _, ok := e.rowStore.Load(rowIndex); !ok { - e.rowStore.Store(rowIndex, &StoredRow{ - Row: Row{ - Index: rowIndex, - }, - }) - } - if cacherow, ok := e.rowStore.Load(rowIndex); ok { - r := cacherow.(*StoredRow) - if cachec, ok := r.Cols.Load(colIndex); ok { - c := cachec.(*Cell) - if c.StyleID > 0 { - if !override { - return ErrOverrideCellStyle - } - styleID, err := e.overrideStyle(c.StyleID, style) - if err != nil { - return err - } - c.StyleID = styleID - } else { - styleID, err := e.getStyleID(&style) - if err != nil { - return err - } - c.StyleID = styleID + e.checkMaxIndex(colIndex, rowIndex) + key := e.getCacheKey(colIndex, rowIndex) + if cached, ok := e.cellStore.Load(key); ok { + c := cached.(*Cell) + if c.StyleID > 0 { + if !override { + return ErrOverrideCellStyle } - return nil - } - styleID, err := e.getStyleID(&style) - if err != nil { - return err + styleID, err := e.overrideStyle(c.StyleID, style) + if err != nil { + return err + } + c.StyleID = styleID } - r.Cols.Store(colIndex, &Cell{ - StyleID: styleID, - Value: nil, - }) } + + styleID, err := e.getStyleID(&style) + if err != nil { + return err + } + e.cellStore.Store(key, &Cell{ + StyleID: styleID, + Value: nil, + }) return nil } func (e *excelizeam) SetStyleCellRangeAsync(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style) { e.eg.Go(func() error { - return e.setStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex, style, false) + err := e.setStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex, style, false) + return err }) } @@ -314,53 +282,38 @@ func (e *excelizeam) SetStyleCellRange(startColIndex, startRowIndex, endColIndex } func (e *excelizeam) setStyleCellRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, style excelize.Style, override bool) error { - if e.maxCol < endColIndex { - e.maxCol = endColIndex - } - if e.maxRow < endRowIndex { - e.maxRow = endRowIndex - } - + e.checkMaxIndex(endColIndex, endRowIndex) for rowIdx := startRowIndex; rowIdx <= endRowIndex; rowIdx++ { for colIdx := startColIndex; colIdx <= endColIndex; colIdx++ { - if _, ok := e.rowStore.Load(rowIdx); !ok { - e.rowStore.Store(rowIdx, &StoredRow{ - Row: Row{ - Index: rowIdx, - }, - }) - } - if cacherow, ok := e.rowStore.Load(rowIdx); ok { - r := cacherow.(*StoredRow) - if cachec, ok := r.Cols.Load(colIdx); ok { - c := cachec.(*Cell) - if c.StyleID > 0 { - if !override { - return ErrOverrideCellStyle - } - styleID, err := e.overrideStyle(c.StyleID, style) - if err != nil { - return err - } - c.StyleID = styleID - } else { - styleID, err := e.getStyleID(&style) - if err != nil { - return err - } - c.StyleID = styleID + key := e.getCacheKey(colIdx, rowIdx) + if cached, ok := e.cellStore.Load(key); ok { + c := cached.(*Cell) + if c.StyleID > 0 { + if !override { + return ErrOverrideCellStyle } - return nil - } - styleID, err := e.getStyleID(&style) - if err != nil { - return err + styleID, err := e.overrideStyle(c.StyleID, style) + if err != nil { + return err + } + c.StyleID = styleID + } else { + styleID, err := e.getStyleID(&style) + if err != nil { + return err + } + c.StyleID = styleID } - r.Cols.Store(colIdx, &Cell{ - StyleID: styleID, - Value: nil, - }) + return nil } + styleID, err := e.getStyleID(&style) + if err != nil { + return err + } + e.cellStore.Store(key, &Cell{ + StyleID: styleID, + Value: nil, + }) } } return nil @@ -368,7 +321,8 @@ func (e *excelizeam) setStyleCellRange(startColIndex, startRowIndex, endColIndex func (e *excelizeam) SetBorderRangeAsync(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange) { e.eg.Go(func() error { - return e.setBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex, borderRange, false) + err := e.setBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex, borderRange, false) + return err }) } @@ -380,15 +334,10 @@ func (e *excelizeam) SetBorderRange(startColIndex, startRowIndex, endColIndex, e } func (e *excelizeam) setBorderRange(startColIndex, startRowIndex, endColIndex, endRowIndex int, borderRange BorderRange, override bool) error { - if e.maxCol < endColIndex { - e.maxCol = endColIndex - } - if e.maxRow < endRowIndex { - e.maxRow = endRowIndex - } - + e.checkMaxIndex(startColIndex, startRowIndex) for rowIdx := startRowIndex; rowIdx <= endRowIndex; rowIdx++ { for colIdx := startColIndex; colIdx <= endColIndex; colIdx++ { + key := e.getCacheKey(colIdx, rowIdx) borderStyles := make([]excelize.Border, 0, 4) switch { case rowIdx == startRowIndex && colIdx == startColIndex: // TopLeft @@ -548,44 +497,34 @@ func (e *excelizeam) setBorderRange(startColIndex, startRowIndex, endColIndex, e } style := excelize.Style{Border: borderStyles} - if _, ok := e.rowStore.Load(rowIdx); !ok { - e.rowStore.Store(rowIdx, &StoredRow{ - Row: Row{ - Index: rowIdx, - }, - }) - } - if cacherow, ok := e.rowStore.Load(rowIdx); ok { - r := cacherow.(*StoredRow) - if cachec, ok := r.Cols.Load(colIdx); ok { - c := cachec.(*Cell) - if c.StyleID > 0 { - if !override { - return ErrOverrideCellStyle - } - styleID, err := e.overrideStyle(c.StyleID, style) - if err != nil { - return err - } - c.StyleID = styleID - } else { - styleID, err := e.getStyleID(&style) - if err != nil { - return err - } - c.StyleID = styleID + if cached, ok := e.cellStore.Load(key); ok { + c := cached.(*Cell) + if c.StyleID > 0 { + if !override { + return ErrOverrideCellStyle } - continue - } - styleID, err := e.getStyleID(&style) - if err != nil { - return err + styleID, err := e.overrideStyle(c.StyleID, style) + if err != nil { + return err + } + c.StyleID = styleID + } else { + styleID, err := e.getStyleID(&style) + if err != nil { + return err + } + c.StyleID = styleID } - r.Cols.Store(colIdx, &Cell{ - StyleID: styleID, - Value: nil, - }) + continue + } + styleID, err := e.getStyleID(&style) + if err != nil { + return err } + e.cellStore.Store(colIdx, &Cell{ + StyleID: styleID, + Value: nil, + }) } } return nil @@ -715,6 +654,21 @@ func (e *excelizeam) overrideStyle(originStyleID int, overrideStyle excelize.Sty return e.getStyleID(style) } +func (e *excelizeam) getCacheKey(colIndex, rowIndex int) string { + return fmt.Sprintf("%d-%d", rowIndex, colIndex) +} + +func (e *excelizeam) checkMaxIndex(colIndex, rowIndex int) { + e.mu.Lock() + defer e.mu.Unlock() + if e.maxCol < colIndex { + e.maxCol = colIndex + } + if e.maxRow < rowIndex { + e.maxRow = rowIndex + } +} + func (e *excelizeam) Write(w io.Writer) error { if err := e.writeStream(); err != nil { return err @@ -739,51 +693,47 @@ func (e *excelizeam) writeStream() error { } } - for rowIdx := 1; rowIdx <= e.maxRow; rowIdx++ { - cacherow, rowOK := e.rowStore.Load(rowIdx) - if !rowOK { - // Value/Styleのない行はデフォルトStyleのみ設定 - if e.defaultBorder != nil { - cell, err := excelize.CoordinatesToCellName(1, rowIdx) - if err != nil { - return err - } - if err := e.sw.SetRow( - cell, - defaultStyleCells, - ); err != nil { - return err - } + type writeCols struct { + Cols []interface{} + CanWrite bool + } + + writeRows := make([]writeCols, e.maxRow) + for i := 0; i < e.maxRow; i++ { + rowIdx := i + 1 + writeRows[i] = writeCols{ + Cols: make([]interface{}, e.maxCol), + } + if e.defaultBorder != nil { + copy(writeRows[i].Cols, defaultStyleCells) + writeRows[i].CanWrite = true + } + for ii := 0; ii < e.maxCol; ii++ { + colIdx := ii + 1 + cached, ok := e.cellStore.Load(e.getCacheKey(colIdx, rowIdx)) + if !ok { + continue } - continue + c := cached.(*Cell) + writeRows[i].Cols[ii] = excelize.Cell{StyleID: c.StyleID, Value: c.Value} + writeRows[i].CanWrite = true } + } - r := cacherow.(*StoredRow) - canWrite := false - cellValues := make([]interface{}, e.maxCol) - if e.defaultBorder != nil { - canWrite = true - copy(cellValues, defaultStyleCells) + for i, row := range writeRows { + if !row.CanWrite { + continue } - r.Cols.Range(func(key, cachec any) bool { - colIdx := key.(int) - c := cachec.(*Cell) - cellValues[colIdx-1] = excelize.Cell{StyleID: c.StyleID, Value: c.Value} - canWrite = true - return true - }) - if canWrite { - cell, err := excelize.CoordinatesToCellName(1, rowIdx) - if err != nil { - return err - } - if err := e.sw.SetRow( - cell, - cellValues, - ); err != nil { - return err - } + cell, err := excelize.CoordinatesToCellName(1, i+1) + if err != nil { + return err + } + if err := e.sw.SetRow( + cell, + row.Cols, + ); err != nil { + return err } } return nil From 658e8465b604c2e54f1b906da50125410a1d68ef Mon Sep 17 00:00:00 2001 From: tom twinkle Date: Mon, 22 Aug 2022 13:27:54 +0900 Subject: [PATCH 3/3] add async style test --- excelizeam_test.go | 32 +++++++++++++++--- .../async/SetCellValue-with_not_style.xlsx | Bin 0 -> 6361 bytes ..._not_style_multiple_rows_cols_no_sort.xlsx | Bin 0 -> 6800 bytes ..._style_multiple_rows_cols_no_sort_odd.xlsx | Bin 0 -> 6547 bytes ...ith_not_style_multiple_rows_cols_sort.xlsx | Bin 0 -> 6800 bytes ...with_style_border_fill_font_alignment.xlsx | Bin 0 -> 6527 bytes ...le_border_fill_font_alignment_odd_row.xlsx | Bin 0 -> 6708 bytes .../SetCellValue-with_not_style.xlsx | Bin ..._not_style_multiple_rows_cols_no_sort.xlsx | Bin ..._style_multiple_rows_cols_no_sort_odd.xlsx | Bin ...ith_not_style_multiple_rows_cols_sort.xlsx | Bin .../SetCellValue-with_not_style_override.xlsx | Bin ...with_style_border_fill_font_alignment.xlsx | Bin ...font_alignment_override_border_bottom.xlsx | Bin ...l_font_alignment_override_border_left.xlsx | Bin ..._font_alignment_override_border_right.xlsx | Bin ...ll_font_alignment_override_border_top.xlsx | Bin 17 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 testdata/async/SetCellValue-with_not_style.xlsx create mode 100644 testdata/async/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx create mode 100644 testdata/async/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx create mode 100644 testdata/async/SetCellValue-with_not_style_multiple_rows_cols_sort.xlsx create mode 100644 testdata/async/SetCellValue-with_style_border_fill_font_alignment.xlsx create mode 100644 testdata/async/SetCellValue-with_style_border_fill_font_alignment_odd_row.xlsx rename testdata/{ => sync}/SetCellValue-with_not_style.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_not_style_multiple_rows_cols_sort.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_not_style_override.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_style_border_fill_font_alignment.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_style_border_fill_font_alignment_override_border_bottom.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_style_border_fill_font_alignment_override_border_left.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_style_border_fill_font_alignment_override_border_right.xlsx (100%) rename testdata/{ => sync}/SetCellValue-with_style_border_fill_font_alignment_override_border_top.xlsx (100%) diff --git a/excelizeam_test.go b/excelizeam_test.go index 34fcedb..f34c743 100644 --- a/excelizeam_test.go +++ b/excelizeam_test.go @@ -258,12 +258,12 @@ func TestExcelizeam_Sync(t *testing.T) { return } - //f, err := os.Create("testdata/" + name + ".xlsx") + //f, err := os.Create("testdata/sync/" + name + ".xlsx") //assert.NoError(t, err) //_, err = f.Write(buf.Bytes()) //assert.NoError(t, err) - expected, err := excelize.OpenFile("testdata/" + name + ".xlsx") + expected, err := excelize.OpenFile("testdata/sync/" + name + ".xlsx") if !assert.NoError(t, err) { return } @@ -341,6 +341,30 @@ func TestExcelizeam_Async(t *testing.T) { }) }, }, + "SetCellValue-with_style_border_fill_font_alignment_odd_row": { + testFunc: func(w excelizeam.Excelizeam) { + for rowIdx := 1; rowIdx <= 10; rowIdx++ { + if rowIdx%2 == 0 { + continue + } + for colIdx := 1; colIdx <= 10; colIdx++ { + if colIdx%2 == 0 { + continue + } + w.SetCellValueAsync(colIdx, rowIdx, fmt.Sprintf("%d-%d", rowIdx, colIdx), &excelize.Style{ + Border: excelizestyle.BorderAround(excelizestyle.BorderStyleContinuous2, excelizestyle.BorderColorBlack), + Fill: excelizestyle.Fill(excelizestyle.FillPatternSolid, "#315D3C"), + Font: &excelize.Font{ + Bold: true, + Size: 8, + Color: "#718DDC", + }, + Alignment: excelizestyle.Alignment(excelizestyle.AlignmentHorizontalCenter, excelizestyle.AlignmentVerticalCenter, true), + }) + } + } + }, + }, "SetCellValue-with_style_border_fill_font_alignment_override_value_error": { testFunc: func(w excelizeam.Excelizeam) { w.SetCellValue(2, 2, "test1", &excelize.Style{ @@ -386,12 +410,12 @@ func TestExcelizeam_Async(t *testing.T) { return } - //f, err := os.Create("testdata/" + name + ".xlsx") + //f, err := os.Create("testdata/async/" + name + ".xlsx") //assert.NoError(t, err) //_, err = f.Write(buf.Bytes()) //assert.NoError(t, err) - expected, err := excelize.OpenFile("testdata/" + name + ".xlsx") + expected, err := excelize.OpenFile("testdata/async/" + name + ".xlsx") if !assert.NoError(t, err) { return } diff --git a/testdata/async/SetCellValue-with_not_style.xlsx b/testdata/async/SetCellValue-with_not_style.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..a406f1e2928adab5cba86df061c8373b3b6a1639 GIT binary patch literal 6361 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 literal 0 HcmV?d00001 diff --git a/testdata/async/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx b/testdata/async/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..59aadccdc14821e4ea7c095096052e1021cc395b GIT binary patch literal 6800 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 ALI3~& literal 0 HcmV?d00001 diff --git a/testdata/async/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx b/testdata/async/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..77ed100136c351a48e287f1fd1b39b63b2b8e75b GIT binary patch literal 6547 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 C_uei5 literal 0 HcmV?d00001 diff --git a/testdata/async/SetCellValue-with_style_border_fill_font_alignment.xlsx b/testdata/async/SetCellValue-with_style_border_fill_font_alignment.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..ed8817e14bebfb2d09ceed7432635a291f39eb38 GIT binary patch literal 6527 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 F{{YD-D6Rki literal 0 HcmV?d00001 diff --git a/testdata/async/SetCellValue-with_style_border_fill_font_alignment_odd_row.xlsx b/testdata/async/SetCellValue-with_style_border_fill_font_alignment_odd_row.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..20e1ec6112b9615e8197c1424ff74d69b872bca1 GIT binary patch literal 6708 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 A*#H0l literal 0 HcmV?d00001 diff --git a/testdata/SetCellValue-with_not_style.xlsx b/testdata/sync/SetCellValue-with_not_style.xlsx similarity index 100% rename from testdata/SetCellValue-with_not_style.xlsx rename to testdata/sync/SetCellValue-with_not_style.xlsx diff --git a/testdata/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx b/testdata/sync/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx similarity index 100% rename from testdata/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx rename to testdata/sync/SetCellValue-with_not_style_multiple_rows_cols_no_sort.xlsx diff --git a/testdata/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx b/testdata/sync/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx similarity index 100% rename from testdata/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx rename to testdata/sync/SetCellValue-with_not_style_multiple_rows_cols_no_sort_odd.xlsx diff --git a/testdata/SetCellValue-with_not_style_multiple_rows_cols_sort.xlsx b/testdata/sync/SetCellValue-with_not_style_multiple_rows_cols_sort.xlsx similarity index 100% rename from testdata/SetCellValue-with_not_style_multiple_rows_cols_sort.xlsx rename to testdata/sync/SetCellValue-with_not_style_multiple_rows_cols_sort.xlsx diff --git a/testdata/SetCellValue-with_not_style_override.xlsx b/testdata/sync/SetCellValue-with_not_style_override.xlsx similarity index 100% rename from testdata/SetCellValue-with_not_style_override.xlsx rename to testdata/sync/SetCellValue-with_not_style_override.xlsx diff --git a/testdata/SetCellValue-with_style_border_fill_font_alignment.xlsx b/testdata/sync/SetCellValue-with_style_border_fill_font_alignment.xlsx similarity index 100% rename from testdata/SetCellValue-with_style_border_fill_font_alignment.xlsx rename to testdata/sync/SetCellValue-with_style_border_fill_font_alignment.xlsx diff --git a/testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_bottom.xlsx b/testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_bottom.xlsx similarity index 100% rename from testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_bottom.xlsx rename to testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_bottom.xlsx diff --git a/testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_left.xlsx b/testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_left.xlsx similarity index 100% rename from testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_left.xlsx rename to testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_left.xlsx diff --git a/testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_right.xlsx b/testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_right.xlsx similarity index 100% rename from testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_right.xlsx rename to testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_right.xlsx diff --git a/testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_top.xlsx b/testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_top.xlsx similarity index 100% rename from testdata/SetCellValue-with_style_border_fill_font_alignment_override_border_top.xlsx rename to testdata/sync/SetCellValue-with_style_border_fill_font_alignment_override_border_top.xlsx