diff options
Diffstat (limited to 'rows.go')
-rw-r--r-- | rows.go | 156 |
1 files changed, 65 insertions, 91 deletions
@@ -68,29 +68,49 @@ func (f *File) GetRows(sheet string, opts ...Options) ([][]string, error) { // Rows defines an iterator to a sheet. type Rows struct { - err error - curRow, totalRows, stashRow int - rawCellValue bool - sheet string - f *File - tempFile *os.File - decoder *xml.Decoder + err error + curRow, seekRow int + needClose, rawCellValue bool + sheet string + f *File + tempFile *os.File + sst *xlsxSST + decoder *xml.Decoder + token xml.Token } // CurrentRow returns the row number that represents the current row. func (rows *Rows) CurrentRow() int { - return rows.curRow -} - -// TotalRows returns the total rows count in the worksheet. -func (rows *Rows) TotalRows() int { - return rows.totalRows + return rows.seekRow } // Next will return true if find the next row element. func (rows *Rows) Next() bool { - rows.curRow++ - return rows.curRow <= rows.totalRows + rows.seekRow++ + if rows.curRow >= rows.seekRow { + return true + } + for { + token, _ := rows.decoder.Token() + if token == nil { + return false + } + switch xmlElement := token.(type) { + case xml.StartElement: + if xmlElement.Name.Local == "row" { + rows.curRow++ + if rowNum, _ := attrValToInt("r", xmlElement.Attr); rowNum != 0 { + rows.curRow = rowNum + } + rows.token = token + return true + } + case xml.EndElement: + if xmlElement.Name.Local == "sheetData" { + return false + } + } + } } // Error will return the error when the error occurs. @@ -109,44 +129,40 @@ func (rows *Rows) Close() error { // Columns return the current row's column values. func (rows *Rows) Columns(opts ...Options) ([]string, error) { - var rowIterator rowXMLIterator - if rows.stashRow >= rows.curRow { - return rowIterator.columns, rowIterator.err + if rows.curRow > rows.seekRow { + return nil, nil } - rows.rawCellValue = parseOptions(opts...).RawCellValue - rowIterator.rows = rows - rowIterator.d = rows.f.sharedStringsReader() + var rowIterator rowXMLIterator + var token xml.Token + rows.rawCellValue, rows.sst = parseOptions(opts...).RawCellValue, rows.f.sharedStringsReader() for { - token, _ := rows.decoder.Token() - if token == nil { + if rows.token != nil { + token = rows.token + } else if token, _ = rows.decoder.Token(); token == nil { break } switch xmlElement := token.(type) { case xml.StartElement: rowIterator.inElement = xmlElement.Name.Local if rowIterator.inElement == "row" { - rowIterator.row++ - if rowIterator.attrR, rowIterator.err = attrValToInt("r", xmlElement.Attr); rowIterator.attrR != 0 { - rowIterator.row = rowIterator.attrR + rowNum := 0 + if rowNum, rowIterator.err = attrValToInt("r", xmlElement.Attr); rowNum != 0 { + rows.curRow = rowNum + } else if rows.token == nil { + rows.curRow++ } - if rowIterator.row > rowIterator.rows.curRow { - rowIterator.rows.stashRow = rowIterator.row - 1 + if rows.curRow > rows.seekRow { + rows.token = nil return rowIterator.columns, rowIterator.err } } - rowXMLHandler(&rowIterator, &xmlElement, rows.rawCellValue) - if rowIterator.err != nil { + if rows.rowXMLHandler(&rowIterator, &xmlElement, rows.rawCellValue); rowIterator.err != nil { + rows.token = nil return rowIterator.columns, rowIterator.err } + rows.token = nil case xml.EndElement: - rowIterator.inElement = xmlElement.Name.Local - if rowIterator.row == 0 && rowIterator.rows.curRow > 1 { - rowIterator.row = rowIterator.rows.curRow - } - if rowIterator.inElement == "row" && rowIterator.row+1 < rowIterator.rows.curRow { - return rowIterator.columns, rowIterator.err - } - if rowIterator.inElement == "sheetData" { + if xmlElement.Name.Local == "sheetData" { return rowIterator.columns, rowIterator.err } } @@ -173,29 +189,25 @@ func (err ErrSheetNotExist) Error() string { // rowXMLIterator defined runtime use field for the worksheet row SAX parser. type rowXMLIterator struct { - err error - inElement string - attrR, cellCol, row int - columns []string - rows *Rows - d *xlsxSST + err error + inElement string + cellCol int + columns []string } // rowXMLHandler parse the row XML element of the worksheet. -func rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.StartElement, raw bool) { - rowIterator.err = nil +func (rows *Rows) rowXMLHandler(rowIterator *rowXMLIterator, xmlElement *xml.StartElement, raw bool) { if rowIterator.inElement == "c" { rowIterator.cellCol++ colCell := xlsxC{} - _ = rowIterator.rows.decoder.DecodeElement(&colCell, xmlElement) + _ = rows.decoder.DecodeElement(&colCell, xmlElement) if colCell.R != "" { if rowIterator.cellCol, _, rowIterator.err = CellNameToCoordinates(colCell.R); rowIterator.err != nil { return } } blank := rowIterator.cellCol - len(rowIterator.columns) - val, _ := colCell.getValueFrom(rowIterator.rows.f, rowIterator.d, raw) - if val != "" || colCell.F != nil { + if val, _ := colCell.getValueFrom(rows.f, rows.sst, raw); val != "" || colCell.F != nil { rowIterator.columns = append(appendSpace(blank, rowIterator.columns), val) } } @@ -236,48 +248,10 @@ func (f *File) Rows(sheet string) (*Rows, error) { output, _ := xml.Marshal(worksheet) f.saveFileList(name, f.replaceNameSpaceBytes(name, output)) } - var ( - err error - inElement string - row int - rows Rows - needClose bool - decoder *xml.Decoder - tempFile *os.File - ) - if needClose, decoder, tempFile, err = f.xmlDecoder(name); needClose && err == nil { - defer tempFile.Close() - } - for { - token, _ := decoder.Token() - if token == nil { - break - } - switch xmlElement := token.(type) { - case xml.StartElement: - inElement = xmlElement.Name.Local - if inElement == "row" { - row++ - for _, attr := range xmlElement.Attr { - if attr.Name.Local == "r" { - row, err = strconv.Atoi(attr.Value) - if err != nil { - return &rows, err - } - } - } - rows.totalRows = row - } - case xml.EndElement: - if xmlElement.Name.Local == "sheetData" { - rows.f = f - rows.sheet = name - _, rows.decoder, rows.tempFile, err = f.xmlDecoder(name) - return &rows, err - } - } - } - return &rows, nil + var err error + rows := Rows{f: f, sheet: name} + rows.needClose, rows.decoder, rows.tempFile, err = f.xmlDecoder(name) + return &rows, err } // getFromStringItem build shared string item offset list from system temporary |