|
|
@@ -10,10 +10,8 @@
|
|
|
package excelize
|
|
|
|
|
|
import (
|
|
|
- "bytes"
|
|
|
"encoding/xml"
|
|
|
"fmt"
|
|
|
- "io"
|
|
|
"math"
|
|
|
"strconv"
|
|
|
)
|
|
|
@@ -30,95 +28,35 @@ import (
|
|
|
// }
|
|
|
//
|
|
|
func (f *File) GetRows(sheet string) ([][]string, error) {
|
|
|
- name, ok := f.sheetMap[trimSheetName(sheet)]
|
|
|
- if !ok {
|
|
|
- return nil, nil
|
|
|
- }
|
|
|
-
|
|
|
- xlsx, err := f.workSheetReader(sheet)
|
|
|
+ rows, err := f.Rows(sheet)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
|
- if xlsx != nil {
|
|
|
- output, _ := xml.Marshal(f.Sheet[name])
|
|
|
- f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
|
|
- }
|
|
|
-
|
|
|
- xml.NewDecoder(bytes.NewReader(f.readXML(name)))
|
|
|
- d := f.sharedStringsReader()
|
|
|
- var (
|
|
|
- inElement string
|
|
|
- rowData xlsxRow
|
|
|
- )
|
|
|
-
|
|
|
- rowCount, colCount, err := f.getTotalRowsCols(name)
|
|
|
- if err != nil {
|
|
|
- return nil, nil
|
|
|
- }
|
|
|
- rows := make([][]string, rowCount)
|
|
|
- for i := range rows {
|
|
|
- rows[i] = make([]string, colCount)
|
|
|
- }
|
|
|
-
|
|
|
- var row int
|
|
|
- decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
|
|
|
- for {
|
|
|
- token, _ := decoder.Token()
|
|
|
- if token == nil {
|
|
|
+ results := make([][]string, 0, 64)
|
|
|
+ for rows.Next() {
|
|
|
+ if rows.Error() != nil {
|
|
|
break
|
|
|
}
|
|
|
- switch startElement := token.(type) {
|
|
|
- case xml.StartElement:
|
|
|
- inElement = startElement.Name.Local
|
|
|
- if inElement == "row" {
|
|
|
- rowData = xlsxRow{}
|
|
|
- _ = decoder.DecodeElement(&rowData, &startElement)
|
|
|
- cr := rowData.R - 1
|
|
|
- for _, colCell := range rowData.C {
|
|
|
- col, _, err := CellNameToCoordinates(colCell.R)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- val, _ := colCell.getValueFrom(f, d)
|
|
|
- rows[cr][col-1] = val
|
|
|
- if val != "" {
|
|
|
- row = rowData.R
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- default:
|
|
|
+ row, err := rows.Columns()
|
|
|
+ if err != nil {
|
|
|
+ break
|
|
|
}
|
|
|
+ results = append(results, row)
|
|
|
}
|
|
|
- return rows[:row], nil
|
|
|
+ return results, nil
|
|
|
}
|
|
|
|
|
|
// Rows defines an iterator to a sheet
|
|
|
type Rows struct {
|
|
|
- decoder *xml.Decoder
|
|
|
- token xml.Token
|
|
|
- err error
|
|
|
- f *File
|
|
|
+ err error
|
|
|
+ f *File
|
|
|
+ rows []xlsxRow
|
|
|
+ curRow int
|
|
|
}
|
|
|
|
|
|
// Next will return true if find the next row element.
|
|
|
func (rows *Rows) Next() bool {
|
|
|
- for {
|
|
|
- rows.token, rows.err = rows.decoder.Token()
|
|
|
- if rows.err == io.EOF {
|
|
|
- rows.err = nil
|
|
|
- }
|
|
|
- if rows.token == nil {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
- switch startElement := rows.token.(type) {
|
|
|
- case xml.StartElement:
|
|
|
- inElement := startElement.Name.Local
|
|
|
- if inElement == "row" {
|
|
|
- return true
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
+ return rows.curRow < len(rows.rows)
|
|
|
}
|
|
|
|
|
|
// Error will return the error when the find next row element
|
|
|
@@ -128,15 +66,12 @@ func (rows *Rows) Error() error {
|
|
|
|
|
|
// Columns return the current row's column values
|
|
|
func (rows *Rows) Columns() ([]string, error) {
|
|
|
- if rows.token == nil {
|
|
|
- return []string{}, nil
|
|
|
- }
|
|
|
- startElement := rows.token.(xml.StartElement)
|
|
|
- r := xlsxRow{}
|
|
|
- _ = rows.decoder.DecodeElement(&r, &startElement)
|
|
|
+ curRow := rows.rows[rows.curRow]
|
|
|
+ rows.curRow++
|
|
|
+
|
|
|
+ columns := make([]string, len(curRow.C))
|
|
|
d := rows.f.sharedStringsReader()
|
|
|
- columns := make([]string, len(r.C))
|
|
|
- for _, colCell := range r.C {
|
|
|
+ for _, colCell := range curRow.C {
|
|
|
col, _, err := CellNameToCoordinates(colCell.R)
|
|
|
if err != nil {
|
|
|
return columns, err
|
|
|
@@ -181,46 +116,11 @@ func (f *File) Rows(sheet string) (*Rows, error) {
|
|
|
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
|
|
}
|
|
|
return &Rows{
|
|
|
- f: f,
|
|
|
- decoder: xml.NewDecoder(bytes.NewReader(f.readXML(name))),
|
|
|
+ f: f,
|
|
|
+ rows: xlsx.SheetData.Row,
|
|
|
}, nil
|
|
|
}
|
|
|
|
|
|
-// getTotalRowsCols provides a function to get total columns and rows in a
|
|
|
-// worksheet.
|
|
|
-func (f *File) getTotalRowsCols(name string) (int, int, error) {
|
|
|
- decoder := xml.NewDecoder(bytes.NewReader(f.readXML(name)))
|
|
|
- var inElement string
|
|
|
- var r xlsxRow
|
|
|
- var tr, tc int
|
|
|
- for {
|
|
|
- token, _ := decoder.Token()
|
|
|
- if token == nil {
|
|
|
- break
|
|
|
- }
|
|
|
- switch startElement := token.(type) {
|
|
|
- case xml.StartElement:
|
|
|
- inElement = startElement.Name.Local
|
|
|
- if inElement == "row" {
|
|
|
- r = xlsxRow{}
|
|
|
- _ = decoder.DecodeElement(&r, &startElement)
|
|
|
- tr = r.R
|
|
|
- for _, colCell := range r.C {
|
|
|
- col, _, err := CellNameToCoordinates(colCell.R)
|
|
|
- if err != nil {
|
|
|
- return tr, tc, err
|
|
|
- }
|
|
|
- if col > tc {
|
|
|
- tc = col
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- default:
|
|
|
- }
|
|
|
- }
|
|
|
- return tr, tc, nil
|
|
|
-}
|
|
|
-
|
|
|
// SetRowHeight provides a function to set the height of a single row. For
|
|
|
// example, set the height of the first row in Sheet1:
|
|
|
//
|