forked from p30928647/excelize
commit
451e6e384a
142
rows.go
142
rows.go
|
@ -10,10 +10,8 @@
|
||||||
package excelize
|
package excelize
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/xml"
|
"encoding/xml"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
@ -30,95 +28,35 @@ import (
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
func (f *File) GetRows(sheet string) ([][]string, error) {
|
func (f *File) GetRows(sheet string) ([][]string, error) {
|
||||||
name, ok := f.sheetMap[trimSheetName(sheet)]
|
rows, err := f.Rows(sheet)
|
||||||
if !ok {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
xlsx, err := f.workSheetReader(sheet)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if xlsx != nil {
|
results := make([][]string, 0, 64)
|
||||||
output, _ := xml.Marshal(f.Sheet[name])
|
for rows.Next() {
|
||||||
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
if rows.Error() != nil {
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch startElement := token.(type) {
|
row, err := rows.Columns()
|
||||||
case xml.StartElement:
|
if err != nil {
|
||||||
inElement = startElement.Name.Local
|
break
|
||||||
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:
|
|
||||||
}
|
}
|
||||||
|
results = append(results, row)
|
||||||
}
|
}
|
||||||
return rows[:row], nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Rows defines an iterator to a sheet
|
// Rows defines an iterator to a sheet
|
||||||
type Rows struct {
|
type Rows struct {
|
||||||
decoder *xml.Decoder
|
err error
|
||||||
token xml.Token
|
f *File
|
||||||
err error
|
rows []xlsxRow
|
||||||
f *File
|
curRow int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Next will return true if find the next row element.
|
// Next will return true if find the next row element.
|
||||||
func (rows *Rows) Next() bool {
|
func (rows *Rows) Next() bool {
|
||||||
for {
|
return rows.curRow < len(rows.rows)
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error will return the error when the find next row element
|
// 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
|
// Columns return the current row's column values
|
||||||
func (rows *Rows) Columns() ([]string, error) {
|
func (rows *Rows) Columns() ([]string, error) {
|
||||||
if rows.token == nil {
|
curRow := rows.rows[rows.curRow]
|
||||||
return []string{}, nil
|
rows.curRow++
|
||||||
}
|
|
||||||
startElement := rows.token.(xml.StartElement)
|
columns := make([]string, len(curRow.C))
|
||||||
r := xlsxRow{}
|
|
||||||
_ = rows.decoder.DecodeElement(&r, &startElement)
|
|
||||||
d := rows.f.sharedStringsReader()
|
d := rows.f.sharedStringsReader()
|
||||||
columns := make([]string, len(r.C))
|
for _, colCell := range curRow.C {
|
||||||
for _, colCell := range r.C {
|
|
||||||
col, _, err := CellNameToCoordinates(colCell.R)
|
col, _, err := CellNameToCoordinates(colCell.R)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return columns, err
|
return columns, err
|
||||||
|
@ -181,46 +116,11 @@ func (f *File) Rows(sheet string) (*Rows, error) {
|
||||||
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
f.saveFileList(name, replaceWorkSheetsRelationshipsNameSpaceBytes(output))
|
||||||
}
|
}
|
||||||
return &Rows{
|
return &Rows{
|
||||||
f: f,
|
f: f,
|
||||||
decoder: xml.NewDecoder(bytes.NewReader(f.readXML(name))),
|
rows: xlsx.SheetData.Row,
|
||||||
}, nil
|
}, 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
|
// SetRowHeight provides a function to set the height of a single row. For
|
||||||
// example, set the height of the first row in Sheet1:
|
// example, set the height of the first row in Sheet1:
|
||||||
//
|
//
|
||||||
|
|
18
rows_test.go
18
rows_test.go
|
@ -39,9 +39,6 @@ func TestRows(t *testing.T) {
|
||||||
if !assert.Equal(t, collectedRows, returnedRows) {
|
if !assert.Equal(t, collectedRows, returnedRows) {
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
|
|
||||||
r := Rows{}
|
|
||||||
r.Columns()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRowsError(t *testing.T) {
|
func TestRowsError(t *testing.T) {
|
||||||
|
@ -672,6 +669,21 @@ func TestDuplicateRowInvalidRownum(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkRows(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
f, _ := OpenFile(filepath.Join("test", "Book1.xlsx"))
|
||||||
|
rows, _ := f.Rows("Sheet2")
|
||||||
|
for rows.Next() {
|
||||||
|
row, _ := rows.Columns()
|
||||||
|
for i := range row {
|
||||||
|
if i >= 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func trimSliceSpace(s []string) []string {
|
func trimSliceSpace(s []string) []string {
|
||||||
for {
|
for {
|
||||||
if len(s) > 0 && s[len(s)-1] == "" {
|
if len(s) > 0 && s[len(s)-1] == "" {
|
||||||
|
|
Loading…
Reference in New Issue