浏览代码

Fix #551, handle empty rows in streaming reading

xuri 6 年之前
父节点
当前提交
5f5ec76740
共有 8 个文件被更改,包括 84 次插入81 次删除
  1. 5 11
      chart.go
  2. 6 9
      excelize.go
  3. 19 28
      picture.go
  4. 5 7
      pivotTable.go
  5. 26 12
      rows.go
  6. 9 0
      rows_test.go
  7. 6 6
      stream.go
  8. 8 8
      styles.go

+ 5 - 11
chart.go

@@ -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())
 //        }
 //    }
 //

+ 6 - 9
excelize.go

@@ -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 {

+ 19 - 28
picture.go

@@ -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) {

+ 5 - 7
pivotTable.go

@@ -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())
 //        }
 //    }
 //

+ 26 - 12
rows.go

@@ -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 {
+//    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())
+//        }
 //        for _, colCell := range row {
-//            fmt.Print(colCell, "\t")
+//            print(colCell, "\t")
 //        }
-//        fmt.Println()
+//        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

+ 9 - 0
rows_test.go

@@ -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`)
 

+ 6 - 6
stream.go

@@ -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) {

+ 8 - 8
styles.go

@@ -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))
 //