Fix #551, handle empty rows in streaming reading

This commit is contained in:
xuri 2019-12-31 01:01:16 +08:00
parent 09485b3f9f
commit 5f5ec76740
No known key found for this signature in database
GPG Key ID: BA5E5BB1C948EDF7
8 changed files with 85 additions and 82 deletions

View File

@ -495,11 +495,7 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
//
// package main
//
// import (
// "fmt"
//
// "github.com/360EntSecGroup-Skylar/excelize"
// )
// import "github.com/360EntSecGroup-Skylar/excelize"
//
// func main() {
// categories := map[string]string{"A2": "Small", "A3": "Normal", "A4": "Large", "B1": "Apple", "C1": "Orange", "D1": "Pear"}
@ -511,15 +507,13 @@ func parseFormatChartSet(formatSet string) (*formatChart, error) {
// for k, v := range values {
// f.SetCellValue("Sheet1", k, v)
// }
// err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","dimension":{"width":640,"height":480},"series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Clustered Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","x_axis":{"reverse_order":true},"y_axis":{"maximum":7.5,"minimum":0.5}}`)
// if err != nil {
// fmt.Println(err)
// if err := f.AddChart("Sheet1", "E1", `{"type":"col3DClustered","dimension":{"width":640,"height":480},"series":[{"name":"Sheet1!$A$2","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$2:$D$2"},{"name":"Sheet1!$A$3","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$3:$D$3"},{"name":"Sheet1!$A$4","categories":"Sheet1!$B$1:$D$1","values":"Sheet1!$B$4:$D$4"}],"format":{"x_scale":1.0,"y_scale":1.0,"x_offset":15,"y_offset":10,"print_obj":true,"lock_aspect_ratio":false,"locked":false},"legend":{"position":"bottom","show_legend_key":false},"title":{"name":"Fruit 3D Clustered Column Chart"},"plotarea":{"show_bubble_size":true,"show_cat_name":false,"show_leader_lines":false,"show_percent":true,"show_series_name":true,"show_val":true},"show_blanks_as":"zero","x_axis":{"reverse_order":true},"y_axis":{"maximum":7.5,"minimum":0.5}}`); err != nil {
// println(err.Error())
// return
// }
// // Save xlsx file by the given path.
// err = xlsx.SaveAs("./Book1.xlsx")
// if err != nil {
// fmt.Println(err)
// if err := xlsx.SaveAs("Book1.xlsx"); err != nil {
// println(err.Error())
// }
// }
//

View File

@ -293,17 +293,14 @@ func (f *File) UpdateLinkedValue() error {
// AddVBAProject provides the method to add vbaProject.bin file which contains
// functions and/or macros. The file extension should be .xlsm. For example:
//
// err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1"))
// if err != nil {
// fmt.Println(err)
// if err := f.SetSheetPrOptions("Sheet1", excelize.CodeName("Sheet1")); err != nil {
// println(err.Error())
// }
// err = f.AddVBAProject("vbaProject.bin")
// if err != nil {
// fmt.Println(err)
// if err := f.AddVBAProject("vbaProject.bin"); err != nil {
// println(err.Error())
// }
// err = f.SaveAs("macros.xlsm")
// if err != nil {
// fmt.Println(err)
// if err := f.SaveAs("macros.xlsm"); err != nil {
// println(err.Error())
// }
//
func (f *File) AddVBAProject(bin string) error {

View File

@ -48,7 +48,6 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
// package main
//
// import (
// "fmt"
// _ "image/gif"
// _ "image/jpeg"
// _ "image/png"
@ -59,23 +58,19 @@ func parseFormatPictureSet(formatSet string) (*formatPicture, error) {
// func main() {
// f := excelize.NewFile()
// // Insert a picture.
// err := f.AddPicture("Sheet1", "A2", "./image1.jpg", "")
// if err != nil {
// fmt.Println(err)
// if err := f.AddPicture("Sheet1", "A2", "image.jpg", ""); err != nil {
// println(err.Error())
// }
// // Insert a picture scaling in the cell with location hyperlink.
// err = f.AddPicture("Sheet1", "D2", "./image1.png", `{"x_scale": 0.5, "y_scale": 0.5, "hyperlink": "#Sheet2!D8", "hyperlink_type": "Location"}`)
// if err != nil {
// fmt.Println(err)
// if err := f.AddPicture("Sheet1", "D2", "image.png", `{"x_scale": 0.5, "y_scale": 0.5, "hyperlink": "#Sheet2!D8", "hyperlink_type": "Location"}`); err != nil {
// println(err.Error())
// }
// // Insert a picture offset in the cell with external hyperlink, printing and positioning support.
// err = f.AddPicture("Sheet1", "H2", "./image3.gif", `{"x_offset": 15, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "print_obj": true, "lock_aspect_ratio": false, "locked": false, "positioning": "oneCell"}`)
// if err != nil {
// fmt.Println(err)
// if err := f.AddPicture("Sheet1", "H2", "image.gif", `{"x_offset": 15, "y_offset": 10, "hyperlink": "https://github.com/360EntSecGroup-Skylar/excelize", "hyperlink_type": "External", "print_obj": true, "lock_aspect_ratio": false, "locked": false, "positioning": "oneCell"}`); err != nil {
// println(err.Error())
// }
// err = f.SaveAs("./Book1.xlsx")
// if err != nil {
// fmt.Println(err)
// if err := f.SaveAs("Book1.xlsx"); err != nil {
// println(err.Error())
// }
// }
//
@ -109,7 +104,6 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
// package main
//
// import (
// "fmt"
// _ "image/jpeg"
// "io/ioutil"
//
@ -119,17 +113,15 @@ func (f *File) AddPicture(sheet, cell, picture, format string) error {
// func main() {
// f := excelize.NewFile()
//
// file, err := ioutil.ReadFile("./image1.jpg")
// file, err := ioutil.ReadFile("image.jpg")
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.AddPictureFromBytes("Sheet1", "A2", "", "Excel Logo", ".jpg", file)
// if err != nil {
// fmt.Println(err)
// if err := f.AddPictureFromBytes("Sheet1", "A2", "", "Excel Logo", ".jpg", file); err != nil {
// println(err.Error())
// }
// err = f.SaveAs("./Book1.xlsx")
// if err != nil {
// fmt.Println(err)
// if err := f.SaveAs("Book1.xlsx"); err != nil {
// println(err.Error())
// }
// }
//
@ -430,19 +422,18 @@ func (f *File) getSheetRelationshipsTargetByID(sheet, rID string) string {
// embed in XLSX by given worksheet and cell name. This function returns the
// file name in XLSX and file contents as []byte data types. For example:
//
// f, err := excelize.OpenFile("./Book1.xlsx")
// f, err := excelize.OpenFile("Book1.xlsx")
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// return
// }
// file, raw, err := f.GetPicture("Sheet1", "A2")
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// return
// }
// err = ioutil.WriteFile(file, raw, 0644)
// if err != nil {
// fmt.Println(err)
// if err := ioutil.WriteFile(file, raw, 0644); err != nil {
// println(err.Error())
// }
//
func (f *File) GetPicture(sheet, cell string) (string, []byte, error) {

View File

@ -56,19 +56,17 @@ type PivotTableOption struct {
// f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i+2), rand.Intn(5000))
// f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i+2), region[rand.Intn(4)])
// }
// err := f.AddPivotTable(&excelize.PivotTableOption{
// if err := f.AddPivotTable(&excelize.PivotTableOption{
// DataRange: "Sheet1!$A$1:$E$31",
// PivotTableRange: "Sheet1!$G$2:$M$34",
// Rows: []string{"Month", "Year"},
// Columns: []string{"Type"},
// Data: []string{"Sales"},
// })
// if err != nil {
// fmt.Println(err)
// }); err != nil {
// println(err.Error())
// }
// err = f.SaveAs("Book1.xlsx")
// if err != nil {
// fmt.Println(err)
// if err := f.SaveAs("Book1.xlsx"); err != nil {
// println(err.Error())
// }
// }
//

40
rows.go
View File

@ -23,12 +23,20 @@ import (
// GetRows return all the rows in a sheet by given worksheet name (case
// sensitive). For example:
//
// rows, err := f.GetRows("Sheet1")
// for _, row := range rows {
// for _, colCell := range row {
// fmt.Print(colCell, "\t")
// rows, err := f.Rows("Sheet1")
// if err != nil {
// println(err.Error())
// return
// }
// for rows.Next() {
// row, err := rows.Columns()
// if err != nil {
// println(err.Error())
// }
// fmt.Println()
// for _, colCell := range row {
// print(colCell, "\t")
// }
// println()
// }
//
func (f *File) GetRows(sheet string) ([][]string, error) {
@ -52,13 +60,13 @@ func (f *File) GetRows(sheet string) ([][]string, error) {
// Rows defines an iterator to a sheet
type Rows struct {
err error
f *File
rows []xlsxRow
sheet string
curRow int
totalRow int
decoder *xml.Decoder
err error
curRow, totalRow, stashRow int
sheet string
stashColumn []string
rows []xlsxRow
f *File
decoder *xml.Decoder
}
// Next will return true if find the next row element.
@ -80,6 +88,11 @@ func (rows *Rows) Columns() ([]string, error) {
row, cellCol int
columns []string
)
if rows.stashRow >= rows.curRow {
return columns, err
}
d := rows.f.sharedStringsReader()
for {
token, _ := rows.decoder.Token()
@ -97,6 +110,8 @@ func (rows *Rows) Columns() ([]string, error) {
return columns, err
}
if row > rows.curRow {
rows.stashRow = row - 1
rows.stashColumn = columns
return columns, err
}
}
@ -121,7 +136,6 @@ func (rows *Rows) Columns() ([]string, error) {
if inElement == "row" {
return columns, err
}
default:
}
}
return columns, err

View File

@ -136,7 +136,16 @@ func TestColumns(t *testing.T) {
f := NewFile()
rows, err := f.Rows("Sheet1")
assert.NoError(t, err)
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="2"><c r="A1" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
_, err = rows.Columns()
assert.NoError(t, err)
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="2"><c r="A1" t="s"><v>1</v></c></row></sheetData></worksheet>`)))
rows.curRow = 1
_, err = rows.Columns()
rows.decoder = f.xmlNewDecoder(bytes.NewReader([]byte(`<worksheet><sheetData><row r="A"><c r="A1" t="s"><v>1</v></c></row><row r="A"><c r="2" t="str"><v>B</v></c></row></sheetData></worksheet>`)))
rows.stashRow, rows.curRow = 0, 1
_, err = rows.Columns()
assert.EqualError(t, err, `strconv.Atoi: parsing "A": invalid syntax`)

View File

@ -41,14 +41,14 @@ type StreamWriter struct {
// file := excelize.NewFile()
// streamWriter, err := file.NewStreamWriter("Sheet1")
// if err != nil {
// panic(err)
// println(err.Error())
// }
// styleID, err := file.NewStyle(`{"font":{"color":"#777777"}}`)
// if err != nil {
// panic(err)
// println(err.Error())
// }
// if err := streamWriter.SetRow("A1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Data"}}); err != nil {
// panic(err)
// println(err.Error())
// }
// for rowID := 2; rowID <= 102400; rowID++ {
// row := make([]interface{}, 50)
@ -57,14 +57,14 @@ type StreamWriter struct {
// }
// cell, _ := excelize.CoordinatesToCellName(1, rowID)
// if err := streamWriter.SetRow(cell, row); err != nil {
// panic(err)
// println(err.Error())
// }
// }
// if err := streamWriter.Flush(); err != nil {
// panic(err)
// println(err.Error())
// }
// if err := file.SaveAs("Book1.xlsx"); err != nil {
// panic(err)
// println(err.Error())
// }
//
func (f *File) NewStreamWriter(sheet string) (*StreamWriter, error) {

View File

@ -2321,7 +2321,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// style, err := f.NewStyle(`{"border":[{"type":"left","color":"0000FF","style":3},{"type":"top","color":"00FF00","style":4},{"type":"bottom","color":"FFFF00","style":5},{"type":"right","color":"FF0000","style":6},{"type":"diagonalDown","color":"A020F0","style":7},{"type":"diagonalUp","color":"A020F0","style":8}]}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2330,7 +2330,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// style, err := f.NewStyle(`{"fill":{"type":"gradient","color":["#FFFFFF","#E0EBF5"],"shading":1}}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2338,7 +2338,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// style, err := f.NewStyle(`{"fill":{"type":"pattern","color":["#E0EBF5"],"pattern":1}}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2346,7 +2346,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// style, err := f.NewStyle(`{"alignment":{"horizontal":"center","ident":1,"justify_last_line":true,"reading_order":0,"relative_indent":1,"shrink_to_fit":true,"text_rotation":45,"vertical":"","wrap_text":true}}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2357,7 +2357,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
// f.SetCellValue("Sheet1", "H9", 42920.5)
// style, err := f.NewStyle(`{"number_format": 22}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2365,7 +2365,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// style, err := f.NewStyle(`{"font":{"bold":true,"italic":true,"family":"Times New Roman","size":36,"color":"#777777"}}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2373,7 +2373,7 @@ func (f *File) GetCellStyle(sheet, axis string) (int, error) {
//
// style, err := f.NewStyle(`{"protection":{"hidden":true, "locked":true}}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// err = f.SetCellStyle("Sheet1", "H9", "H9", style)
//
@ -2507,7 +2507,7 @@ func (f *File) SetCellStyle(sheet, hcell, vcell string, styleID int) error {
//
// format, err = f.NewConditionalStyle(`{"font":{"color":"#9A0511"},"fill":{"type":"pattern","color":["#FEC7CE"],"pattern":1}}`)
// if err != nil {
// fmt.Println(err)
// println(err.Error())
// }
// f.SetConditionalFormat("Sheet1", "A1:A10", fmt.Sprintf(`[{"type":"cell","criteria":">","format":%d,"value":"6"}]`, format))
//