已验证 提交 48f19f60 编写于 作者: xurime's avatar xurime

support the row element without r attribute in the worksheet

上级 15fd5685
...@@ -95,6 +95,23 @@ func TestSetCellBool(t *testing.T) { ...@@ -95,6 +95,23 @@ func TestSetCellBool(t *testing.T) {
assert.EqualError(t, f.SetCellBool("Sheet1", "A", true), `cannot convert cell "A" to coordinates: invalid cell name "A"`) assert.EqualError(t, f.SetCellBool("Sheet1", "A", true), `cannot convert cell "A" to coordinates: invalid cell name "A"`)
} }
func TestGetCellValue(t *testing.T) {
// Test get cell value without r attribute of the row.
f := NewFile()
delete(f.Sheet, "xl/worksheets/sheet1.xml")
f.XLSX["xl/worksheets/sheet1.xml"] = []byte(`<worksheet xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><sheetData><row r="3"><c t="str"><v>A3</v></c></row><row><c t="str"><v>A4</v></c><c t="str"><v>B4</v></c></row><row r="7"><c t="str"><v>A7</v></c><c t="str"><v>B7</v></c></row><row><c t="str"><v>A8</v></c><c t="str"><v>B8</v></c></row></sheetData></worksheet>`)
f.checked = nil
cells := []string{"A3", "A4", "B4", "A7", "B7"}
rows, err := f.GetRows("Sheet1")
assert.Equal(t, [][]string{nil, nil, {"A3"}, {"A4", "B4"}, nil, nil, {"A7", "B7"}, {"A8", "B8"}}, rows)
assert.NoError(t, err)
for _, cell := range cells {
value, err := f.GetCellValue("Sheet1", cell)
assert.Equal(t, cell, value)
assert.NoError(t, err)
}
}
func TestGetCellFormula(t *testing.T) { func TestGetCellFormula(t *testing.T) {
// Test get cell formula on not exist worksheet. // Test get cell formula on not exist worksheet.
f := NewFile() f := NewFile()
......
...@@ -42,18 +42,14 @@ type Cols struct { ...@@ -42,18 +42,14 @@ type Cols struct {
// GetCols return all the columns in a sheet by given worksheet name (case // GetCols return all the columns in a sheet by given worksheet name (case
// sensitive). For example: // sensitive). For example:
// //
// cols, err := f.Cols("Sheet1") // cols, err := f.GetCols("Sheet1")
// if err != nil { // if err != nil {
// fmt.Println(err) // fmt.Println(err)
// return // return
// } // }
// for cols.Next() { // for _, col := range cols {
// col, err := cols.Rows() // for _, colCell := range col {
// if err != nil { // fmt.Println(colCell, "\t")
// fmt.Println(err)
// }
// for _, rowCell := range col {
// fmt.Print(rowCell, "\t")
// } // }
// fmt.Println() // fmt.Println()
// } // }
...@@ -71,13 +67,13 @@ func (f *File) GetCols(sheet string) ([][]string, error) { ...@@ -71,13 +67,13 @@ func (f *File) GetCols(sheet string) ([][]string, error) {
return results, nil return results, nil
} }
// Next will return true if the next col element is found. // Next will return true if the next column is found.
func (cols *Cols) Next() bool { func (cols *Cols) Next() bool {
cols.curCol++ cols.curCol++
return cols.curCol <= cols.totalCol return cols.curCol <= cols.totalCol
} }
// Error will return an error when the next col element is found. // Error will return an error when the error occurs.
func (cols *Cols) Error() error { func (cols *Cols) Error() error {
return cols.err return cols.err
} }
...@@ -127,7 +123,7 @@ func (cols *Cols) Rows() ([]string, error) { ...@@ -127,7 +123,7 @@ func (cols *Cols) Rows() ([]string, error) {
return rows, nil return rows, nil
} }
// Cols returns a columns iterator, used for streaming/reading data for a // Cols returns a columns iterator, used for streaming reading data for a
// worksheet with a large data. For example: // worksheet with a large data. For example:
// //
// cols, err := f.Cols("Sheet1") // cols, err := f.Cols("Sheet1")
......
...@@ -191,16 +191,25 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) { ...@@ -191,16 +191,25 @@ func (f *File) workSheetReader(sheet string) (xlsx *xlsxWorksheet, err error) {
// checkSheet provides a function to fill each row element and make that is // checkSheet provides a function to fill each row element and make that is
// continuous in a worksheet of XML. // continuous in a worksheet of XML.
func checkSheet(xlsx *xlsxWorksheet) { func checkSheet(xlsx *xlsxWorksheet) {
row := len(xlsx.SheetData.Row) var row int
if row >= 1 { for _, r := range xlsx.SheetData.Row {
lastRow := xlsx.SheetData.Row[row-1].R if r.R != 0 && r.R > row {
if lastRow >= row { row = r.R
row = lastRow continue
} }
row++
} }
sheetData := xlsxSheetData{Row: make([]xlsxRow, row)} sheetData := xlsxSheetData{Row: make([]xlsxRow, row)}
row = 0
for _, r := range xlsx.SheetData.Row { for _, r := range xlsx.SheetData.Row {
sheetData.Row[r.R-1] = r if r.R != 0 {
sheetData.Row[r.R-1] = r
row = r.R
continue
}
row++
r.R = row
sheetData.Row[row-1] = r
} }
for i := 1; i <= row; i++ { for i := 1; i <= row; i++ {
sheetData.Row[i-1].R = i sheetData.Row[i-1].R = i
......
...@@ -25,18 +25,14 @@ import ( ...@@ -25,18 +25,14 @@ import (
// GetRows return all the rows in a sheet by given worksheet name (case // GetRows return all the rows in a sheet by given worksheet name (case
// sensitive). For example: // sensitive). For example:
// //
// rows, err := f.Rows("Sheet1") // rows, err := f.GetRows("Sheet1")
// if err != nil { // if err != nil {
// fmt.Println(err) // fmt.Println(err)
// return // return
// } // }
// for rows.Next() { // for _, row := range rows {
// row, err := rows.Columns()
// if err != nil {
// fmt.Println(err)
// }
// for _, colCell := range row { // for _, colCell := range row {
// fmt.Print(colCell, "\t") // fmt.Println(colCell, "\t")
// } // }
// fmt.Println() // fmt.Println()
// } // }
...@@ -57,7 +53,7 @@ func (f *File) GetRows(sheet string) ([][]string, error) { ...@@ -57,7 +53,7 @@ func (f *File) GetRows(sheet string) ([][]string, error) {
return results, nil return results, nil
} }
// Rows defines an iterator to a sheet // Rows defines an iterator to a sheet.
type Rows struct { type Rows struct {
err error err error
curRow, totalRow, stashRow int curRow, totalRow, stashRow int
...@@ -73,12 +69,12 @@ func (rows *Rows) Next() bool { ...@@ -73,12 +69,12 @@ func (rows *Rows) Next() bool {
return rows.curRow <= rows.totalRow return rows.curRow <= rows.totalRow
} }
// Error will return the error when the find next row element // Error will return the error when the error occurs.
func (rows *Rows) Error() error { func (rows *Rows) Error() error {
return rows.err return rows.err
} }
// Columns return the current row's column values // Columns return the current row's column values.
func (rows *Rows) Columns() ([]string, error) { func (rows *Rows) Columns() ([]string, error) {
var ( var (
err error err error
...@@ -117,9 +113,13 @@ func (rows *Rows) Columns() ([]string, error) { ...@@ -117,9 +113,13 @@ func (rows *Rows) Columns() ([]string, error) {
if inElement == "c" { if inElement == "c" {
colCell := xlsxC{} colCell := xlsxC{}
_ = rows.decoder.DecodeElement(&colCell, &startElement) _ = rows.decoder.DecodeElement(&colCell, &startElement)
cellCol, _, err = CellNameToCoordinates(colCell.R) if colCell.R != "" {
if err != nil { cellCol, _, err = CellNameToCoordinates(colCell.R)
return columns, err if err != nil {
return columns, err
}
} else {
cellCol++
} }
blank := cellCol - len(columns) blank := cellCol - len(columns)
for i := 1; i < blank; i++ { for i := 1; i < blank; i++ {
...@@ -177,10 +177,10 @@ func (f *File) Rows(sheet string) (*Rows, error) { ...@@ -177,10 +177,10 @@ func (f *File) Rows(sheet string) (*Rows, error) {
f.saveFileList(name, replaceRelationshipsNameSpaceBytes(output)) f.saveFileList(name, replaceRelationshipsNameSpaceBytes(output))
} }
var ( var (
err error err error
inElement string inElement string
row int row, curRow int
rows Rows rows Rows
) )
decoder := f.xmlNewDecoder(bytes.NewReader(f.readXML(name))) decoder := f.xmlNewDecoder(bytes.NewReader(f.readXML(name)))
for { for {
...@@ -194,12 +194,16 @@ func (f *File) Rows(sheet string) (*Rows, error) { ...@@ -194,12 +194,16 @@ func (f *File) Rows(sheet string) (*Rows, error) {
if inElement == "row" { if inElement == "row" {
for _, attr := range startElement.Attr { for _, attr := range startElement.Attr {
if attr.Name.Local == "r" { if attr.Name.Local == "r" {
row, err = strconv.Atoi(attr.Value) curRow, err = strconv.Atoi(attr.Value)
if err != nil { if err != nil {
return &rows, err return &rows, err
} }
row = curRow
} }
} }
if len(startElement.Attr) == 0 {
row++
}
rows.totalRow = row rows.totalRow = row
} }
default: default:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册