From adf9d37d82edd3dbc365fece76a031a92e2220d6 Mon Sep 17 00:00:00 2001 From: xuri Date: Wed, 26 Oct 2022 00:04:23 +0800 Subject: [PATCH] This closes #1379, cleanup stream writer temporary files by the `Close` function - Fix error on inserting columns or rows on the worksheet which contains one cell merged cell range - Fix getting incomplete rich text cell value in some cases - Unit tests updated --- adjust.go | 6 +++++- adjust_test.go | 9 +++++++++ cell.go | 20 ++++++++++---------- file.go | 4 +++- stream.go | 5 +++++ stream_test.go | 35 ++++++++++++++++++++++++++++++++++- 6 files changed, 66 insertions(+), 13 deletions(-) diff --git a/adjust.go b/adjust.go index 92efcd0..65e82fc 100644 --- a/adjust.go +++ b/adjust.go @@ -278,7 +278,11 @@ func (f *File) adjustMergeCells(ws *xlsxWorksheet, dir adjustDirection, num, off for i := 0; i < len(ws.MergeCells.Cells); i++ { mergedCells := ws.MergeCells.Cells[i] - coordinates, err := rangeRefToCoordinates(mergedCells.Ref) + mergedCellsRef := mergedCells.Ref + if !strings.Contains(mergedCellsRef, ":") { + mergedCellsRef += ":" + mergedCellsRef + } + coordinates, err := rangeRefToCoordinates(mergedCellsRef) if err != nil { return err } diff --git a/adjust_test.go b/adjust_test.go index a3e73ab..010955c 100644 --- a/adjust_test.go +++ b/adjust_test.go @@ -47,6 +47,15 @@ func TestAdjustMergeCells(t *testing.T) { }, }, }, columns, 1, -1)) + assert.NoError(t, f.adjustMergeCells(&xlsxWorksheet{ + MergeCells: &xlsxMergeCells{ + Cells: []*xlsxMergeCell{ + { + Ref: "A2", + }, + }, + }, + }, columns, 1, -1)) // testing adjustMergeCells var cases []struct { diff --git a/cell.go b/cell.go index 6ed7f48..fbc84b7 100644 --- a/cell.go +++ b/cell.go @@ -152,19 +152,19 @@ func (f *File) SetCellValue(sheet, cell string, value interface{}) error { // String extracts characters from a string item. func (x xlsxSI) String() string { - if len(x.R) > 0 { - var rows strings.Builder - for _, s := range x.R { - if s.T != nil { - rows.WriteString(s.T.Val) - } + var value strings.Builder + if x.T != nil { + value.WriteString(x.T.Val) + } + for _, s := range x.R { + if s.T != nil { + value.WriteString(s.T.Val) } - return bstrUnmarshal(rows.String()) } - if x.T != nil { - return bstrUnmarshal(x.T.Val) + if value.Len() == 0 { + return "" } - return "" + return bstrUnmarshal(value.String()) } // hasValue determine if cell non-blank value. diff --git a/file.go b/file.go index 43a37dd..1469af0 100644 --- a/file.go +++ b/file.go @@ -97,6 +97,9 @@ func (f *File) Close() error { } return true }) + for _, stream := range f.streams { + _ = stream.rawData.Close() + } return err } @@ -195,7 +198,6 @@ func (f *File) writeToZip(zw *zip.Writer) error { if err != nil { return err } - _ = stream.rawData.Close() } var err error f.Pkg.Range(func(path, content interface{}) bool { diff --git a/stream.go b/stream.go index fa78d8b..766e83a 100644 --- a/stream.go +++ b/stream.go @@ -48,6 +48,11 @@ type StreamWriter struct { // with numbers and style: // // file := excelize.NewFile() +// defer func() { +// if err := file.Close(); err != nil { +// fmt.Println(err) +// } +// }() // streamWriter, err := file.NewStreamWriter("Sheet1") // if err != nil { // fmt.Println(err) diff --git a/stream_test.go b/stream_test.go index 4e83626..040eee0 100644 --- a/stream_test.go +++ b/stream_test.go @@ -15,7 +15,11 @@ import ( func BenchmarkStreamWriter(b *testing.B) { file := NewFile() - + defer func() { + if err := file.Close(); err != nil { + b.Error(err) + } + }() row := make([]interface{}, 10) for colID := 0; colID < 10; colID++ { row[colID] = colID @@ -78,6 +82,7 @@ func TestStreamWriter(t *testing.T) { // Test set cell column overflow. assert.ErrorIs(t, streamWriter.SetRow("XFD51201", []interface{}{"A", "B", "C"}), ErrColumnNumber) + assert.NoError(t, file.Close()) // Test close temporary file error. file = NewFile() @@ -107,6 +112,7 @@ func TestStreamWriter(t *testing.T) { file.Pkg.Store("xl/worksheets/sheet1.xml", MacintoshCyrillicCharset) _, err = file.NewStreamWriter("Sheet1") assert.EqualError(t, err, "xml decode error: XML syntax error on line 1: invalid UTF-8") + assert.NoError(t, file.Close()) // Test read cell. file = NewFile() @@ -138,6 +144,9 @@ func TestStreamWriter(t *testing.T) { func TestStreamSetColWidth(t *testing.T) { file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() streamWriter, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) assert.NoError(t, streamWriter.SetColWidth(3, 2, 20)) @@ -150,6 +159,9 @@ func TestStreamSetColWidth(t *testing.T) { func TestStreamSetPanes(t *testing.T) { file, paneOpts := NewFile(), `{"freeze":true,"split":false,"x_split":1,"y_split":0,"top_left_cell":"B1","active_pane":"topRight","panes":[{"sqref":"K16","active_cell":"K16","pane":"topRight"}]}` + defer func() { + assert.NoError(t, file.Close()) + }() streamWriter, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) assert.NoError(t, streamWriter.SetPanes(paneOpts)) @@ -160,6 +172,9 @@ func TestStreamSetPanes(t *testing.T) { func TestStreamTable(t *testing.T) { file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() streamWriter, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) @@ -194,6 +209,9 @@ func TestStreamTable(t *testing.T) { func TestStreamMergeCells(t *testing.T) { file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() streamWriter, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) assert.NoError(t, streamWriter.MergeCell("A1", "D1")) @@ -207,6 +225,9 @@ func TestStreamMergeCells(t *testing.T) { func TestNewStreamWriter(t *testing.T) { // Test error exceptions file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() _, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) _, err = file.NewStreamWriter("SheetN") @@ -223,6 +244,9 @@ func TestStreamMarshalAttrs(t *testing.T) { func TestStreamSetRow(t *testing.T) { // Test error exceptions file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() streamWriter, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) assert.EqualError(t, streamWriter.SetRow("A", []interface{}{}), newCellNameToCoordinatesError("A", newInvalidCellNameError("A")).Error()) @@ -233,6 +257,9 @@ func TestStreamSetRow(t *testing.T) { func TestStreamSetRowNilValues(t *testing.T) { file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() streamWriter, err := file.NewStreamWriter("Sheet1") assert.NoError(t, err) assert.NoError(t, streamWriter.SetRow("A1", []interface{}{nil, nil, Cell{Value: "foo"}})) @@ -244,6 +271,9 @@ func TestStreamSetRowNilValues(t *testing.T) { func TestStreamSetRowWithStyle(t *testing.T) { file := NewFile() + defer func() { + assert.NoError(t, file.Close()) + }() zeroStyleID := 0 grayStyleID, err := file.NewStyle(&Style{Font: &Font{Color: "#777777"}}) assert.NoError(t, err) @@ -273,6 +303,9 @@ func TestStreamSetRowWithStyle(t *testing.T) { func TestStreamSetCellValFunc(t *testing.T) { f := NewFile() + defer func() { + assert.NoError(t, f.Close()) + }() sw, err := f.NewStreamWriter("Sheet1") assert.NoError(t, err) c := &xlsxC{}