@@ -78,60 +78,48 @@ func (rows *Rows) Error() error {
7878
7979// Columns return the current row's column values.
8080func (rows * Rows ) Columns () ([]string , error ) {
81- var (
82- err error
83- inElement string
84- attrR , cellCol , row int
85- columns []string
86- )
87-
81+ var rowIterator rowXMLIterator
8882 if rows .stashRow >= rows .curRow {
89- return columns , err
83+ return rowIterator . columns , rowIterator . err
9084 }
91-
92- d : = rows .f .sharedStringsReader ()
85+ rowIterator . rows = rows
86+ rowIterator . d = rows .f .sharedStringsReader ()
9387 for {
9488 token , _ := rows .decoder .Token ()
9589 if token == nil {
9690 break
9791 }
98- switch startElement := token .(type ) {
92+ switch xmlElement := token .(type ) {
9993 case xml.StartElement :
100- inElement = startElement .Name .Local
101- if inElement == "row" {
102- row ++
103- if attrR , err = attrValToInt ("r" , startElement .Attr ); attrR != 0 {
104- row = attrR
94+ rowIterator . inElement = xmlElement .Name .Local
95+ if rowIterator . inElement == "row" {
96+ rowIterator . row ++
97+ if rowIterator . attrR , rowIterator . err = attrValToInt ("r" , xmlElement .Attr ); rowIterator . attrR != 0 {
98+ rowIterator . row = rowIterator . attrR
10599 }
106- if row > rows .curRow {
107- rows .stashRow = row - 1
108- return columns , err
100+ if rowIterator . row > rowIterator . rows .curRow {
101+ rowIterator . rows .stashRow = rowIterator . row - 1
102+ return rowIterator . columns , rowIterator . err
109103 }
110104 }
111- if inElement == "c" {
112- cellCol ++
113- colCell := xlsxC {}
114- _ = rows .decoder .DecodeElement (& colCell , & startElement )
115- if colCell .R != "" {
116- if cellCol , _ , err = CellNameToCoordinates (colCell .R ); err != nil {
117- return columns , err
118- }
119- }
120- blank := cellCol - len (columns )
121- val , _ := colCell .getValueFrom (rows .f , d )
122- columns = append (appendSpace (blank , columns ), val )
105+ rowXMLHandler (& rowIterator , & xmlElement )
106+ if rowIterator .err != nil {
107+ return rowIterator .columns , rowIterator .err
123108 }
124109 case xml.EndElement :
125- inElement = startElement .Name .Local
126- if row == 0 {
127- row = rows .curRow
110+ rowIterator . inElement = xmlElement .Name .Local
111+ if rowIterator . row == 0 {
112+ rowIterator . row = rowIterator . rows .curRow
128113 }
129- if inElement == "row" && row + 1 < rows .curRow {
130- return columns , err
114+ if rowIterator .inElement == "row" && rowIterator .row + 1 < rowIterator .rows .curRow {
115+ return rowIterator .columns , rowIterator .err
116+ }
117+ if rowIterator .inElement == "sheetData" {
118+ return rowIterator .columns , rowIterator .err
131119 }
132120 }
133121 }
134- return columns , err
122+ return rowIterator . columns , rowIterator . err
135123}
136124
137125// appendSpace append blank characters to slice by given length and source slice.
@@ -151,6 +139,35 @@ func (err ErrSheetNotExist) Error() string {
151139 return fmt .Sprintf ("sheet %s is not exist" , string (err .SheetName ))
152140}
153141
142+ // rowXMLIterator defined runtime use field for the worksheet row SAX parser.
143+ type rowXMLIterator struct {
144+ err error
145+ inElement string
146+ attrR , cellCol , row int
147+ columns []string
148+ rows * Rows
149+ d * xlsxSST
150+ }
151+
152+ // rowXMLHandler parse the row XML element of the worksheet.
153+ func rowXMLHandler (rowIterator * rowXMLIterator , xmlElement * xml.StartElement ) {
154+ rowIterator .err = nil
155+ if rowIterator .inElement == "c" {
156+ rowIterator .cellCol ++
157+ colCell := xlsxC {}
158+ _ = rowIterator .rows .decoder .DecodeElement (& colCell , xmlElement )
159+ if colCell .R != "" {
160+ if rowIterator .cellCol , _ , rowIterator .err = CellNameToCoordinates (colCell .R ); rowIterator .err != nil {
161+ return
162+ }
163+ }
164+ blank := rowIterator .cellCol - len (rowIterator .columns )
165+ val , _ := colCell .getValueFrom (rowIterator .rows .f , rowIterator .d )
166+ rowIterator .columns = append (appendSpace (blank , rowIterator .columns ), val )
167+ }
168+ return
169+ }
170+
154171// Rows returns a rows iterator, used for streaming reading data for a
155172// worksheet with a large data. For example:
156173//
@@ -192,12 +209,12 @@ func (f *File) Rows(sheet string) (*Rows, error) {
192209 if token == nil {
193210 break
194211 }
195- switch startElement := token .(type ) {
212+ switch xmlElement := token .(type ) {
196213 case xml.StartElement :
197- inElement = startElement .Name .Local
214+ inElement = xmlElement .Name .Local
198215 if inElement == "row" {
199216 row ++
200- for _ , attr := range startElement .Attr {
217+ for _ , attr := range xmlElement .Attr {
201218 if attr .Name .Local == "r" {
202219 row , err = strconv .Atoi (attr .Value )
203220 if err != nil {
@@ -207,12 +224,16 @@ func (f *File) Rows(sheet string) (*Rows, error) {
207224 }
208225 rows .totalRow = row
209226 }
227+ case xml.EndElement :
228+ if xmlElement .Name .Local == "sheetData" {
229+ rows .f = f
230+ rows .sheet = name
231+ rows .decoder = f .xmlNewDecoder (bytes .NewReader (f .readXML (name )))
232+ return & rows , nil
233+ }
210234 default :
211235 }
212236 }
213- rows .f = f
214- rows .sheet = name
215- rows .decoder = f .xmlNewDecoder (bytes .NewReader (f .readXML (name )))
216237 return & rows , nil
217238}
218239
0 commit comments