Skip to content

Commit ed91cdd

Browse files
This closes qax-os#1296, add new function GetRowOpts for stream reader (qax-os#1297)
- Support get rows properties by `GetRowOpts` function - New exported constant `MaxCellStyles`
1 parent b8ceaf7 commit ed91cdd

File tree

6 files changed

+103
-0
lines changed

6 files changed

+103
-0
lines changed

rows.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ type Rows struct {
8080
sst *xlsxSST
8181
decoder *xml.Decoder
8282
token xml.Token
83+
curRowOpts, seekRowOpts RowOpts
8384
}
8485

8586
// Next will return true if find the next row element.
8687
func (rows *Rows) Next() bool {
8788
rows.seekRow++
8889
if rows.curRow >= rows.seekRow {
90+
rows.curRowOpts = rows.seekRowOpts
8991
return true
9092
}
9193
for {
@@ -101,6 +103,7 @@ func (rows *Rows) Next() bool {
101103
rows.curRow = rowNum
102104
}
103105
rows.token = token
106+
rows.curRowOpts = extractRowOpts(xmlElement.Attr)
104107
return true
105108
}
106109
case xml.EndElement:
@@ -111,6 +114,11 @@ func (rows *Rows) Next() bool {
111114
}
112115
}
113116

117+
// GetRowOpts will return the RowOpts of the current row.
118+
func (rows *Rows) GetRowOpts() RowOpts {
119+
return rows.curRowOpts
120+
}
121+
114122
// Error will return the error when the error occurs.
115123
func (rows *Rows) Error() error {
116124
return rows.err
@@ -151,6 +159,8 @@ func (rows *Rows) Columns(opts ...Options) ([]string, error) {
151159
} else if rows.token == nil {
152160
rows.curRow++
153161
}
162+
rows.token = token
163+
rows.seekRowOpts = extractRowOpts(xmlElement.Attr)
154164
if rows.curRow > rows.seekRow {
155165
rows.token = nil
156166
return rowIterator.columns, rowIterator.err
@@ -170,6 +180,20 @@ func (rows *Rows) Columns(opts ...Options) ([]string, error) {
170180
return rowIterator.columns, rowIterator.err
171181
}
172182

183+
func extractRowOpts(attrs []xml.Attr) RowOpts {
184+
rowOpts := RowOpts{Height: defaultRowHeight}
185+
if styleID, err := attrValToInt("s", attrs); err == nil && styleID > 0 && styleID < MaxCellStyles {
186+
rowOpts.StyleID = styleID
187+
}
188+
if hidden, err := attrValToBool("hidden", attrs); err == nil {
189+
rowOpts.Hidden = hidden
190+
}
191+
if height, err := attrValToFloat("ht", attrs); err == nil {
192+
rowOpts.Height = height
193+
}
194+
return rowOpts
195+
}
196+
173197
// appendSpace append blank characters to slice by given length and source slice.
174198
func appendSpace(l int, s []string) []string {
175199
for i := 1; i < l; i++ {

rows_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,30 @@ func TestRowsIterator(t *testing.T) {
9696
assert.Equal(t, expectedNumRow, rowCount)
9797
}
9898

99+
func TestRowsGetRowOpts(t *testing.T) {
100+
sheetName := "Sheet2"
101+
expectedRowStyleID1 := RowOpts{Height: 17.0, Hidden: false, StyleID: 1}
102+
expectedRowStyleID2 := RowOpts{Height: 17.0, Hidden: false, StyleID: 0}
103+
expectedRowStyleID3 := RowOpts{Height: 17.0, Hidden: false, StyleID: 2}
104+
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
105+
require.NoError(t, err)
106+
107+
rows, err := f.Rows(sheetName)
108+
require.NoError(t, err)
109+
110+
rows.Next()
111+
rows.Columns() // Columns() may change the XML iterator, so better check with and without calling it
112+
got := rows.GetRowOpts()
113+
assert.Equal(t, expectedRowStyleID1, got)
114+
rows.Next()
115+
got = rows.GetRowOpts()
116+
assert.Equal(t, expectedRowStyleID2, got)
117+
rows.Next()
118+
rows.Columns()
119+
got = rows.GetRowOpts()
120+
assert.Equal(t, expectedRowStyleID3, got)
121+
}
122+
99123
func TestRowsError(t *testing.T) {
100124
f, err := OpenFile(filepath.Join("test", "Book1.xlsx"))
101125
if !assert.NoError(t, err) {

sheet.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,34 @@ func attrValToInt(name string, attrs []xml.Attr) (val int, err error) {
928928
return
929929
}
930930

931+
// attrValToFloat provides a function to convert the local names to a float64
932+
// by given XML attributes and specified names.
933+
func attrValToFloat(name string, attrs []xml.Attr) (val float64, err error) {
934+
for _, attr := range attrs {
935+
if attr.Name.Local == name {
936+
val, err = strconv.ParseFloat(attr.Value, 64)
937+
if err != nil {
938+
return
939+
}
940+
}
941+
}
942+
return
943+
}
944+
945+
// attrValToBool provides a function to convert the local names to a boolean
946+
// by given XML attributes and specified names.
947+
func attrValToBool(name string, attrs []xml.Attr) (val bool, err error) {
948+
for _, attr := range attrs {
949+
if attr.Name.Local == name {
950+
val, err = strconv.ParseBool(attr.Value)
951+
if err != nil {
952+
return
953+
}
954+
}
955+
}
956+
return
957+
}
958+
931959
// SetHeaderFooter provides a function to set headers and footers by given
932960
// worksheet name and the control characters.
933961
//

sheet_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -505,3 +505,29 @@ func newSheetWithSave() {
505505
}
506506
_ = file.Save()
507507
}
508+
509+
func TestAttrValToBool(t *testing.T) {
510+
_, err := attrValToBool("hidden", []xml.Attr{
511+
{Name: xml.Name{Local: "hidden"}},
512+
})
513+
assert.EqualError(t, err, `strconv.ParseBool: parsing "": invalid syntax`)
514+
515+
got, err := attrValToBool("hidden", []xml.Attr{
516+
{Name: xml.Name{Local: "hidden"}, Value: "1"},
517+
})
518+
assert.NoError(t, err)
519+
assert.Equal(t, true, got)
520+
}
521+
522+
func TestAttrValToFloat(t *testing.T) {
523+
_, err := attrValToFloat("ht", []xml.Attr{
524+
{Name: xml.Name{Local: "ht"}},
525+
})
526+
assert.EqualError(t, err, `strconv.ParseFloat: parsing "": invalid syntax`)
527+
528+
got, err := attrValToFloat("ht", []xml.Attr{
529+
{Name: xml.Name{Local: "ht"}, Value: "42.1"},
530+
})
531+
assert.NoError(t, err)
532+
assert.Equal(t, 42.1, got)
533+
}

test/Book1.xlsx

-287 Bytes
Binary file not shown.

xmlDrawing.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ const (
107107
MaxFieldLength = 255
108108
MaxColumnWidth = 255
109109
MaxRowHeight = 409
110+
MaxCellStyles = 64000
110111
MinFontSize = 1
111112
TotalRows = 1048576
112113
MinColumns = 1

0 commit comments

Comments
 (0)