Skip to content

Commit

Permalink
support using int as sheetNamer to find the i'th sheet.
Browse files Browse the repository at this point in the history
  • Loading branch information
szyhf committed Jul 13, 2018
1 parent faad135 commit 44eec79
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 8 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ func defaultUsage(){

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down
13 changes: 9 additions & 4 deletions connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ type connect struct {
workbookRelsIDMap map[string]string
// xl/workbook.xml
workbookFile *zip.File
// map["sheet_id"]"sheet_name"
worksheetIDToNameMap map[string]string
// "xl/worksheets/sheet*.xml"
// map["xl/path/to/sheet*.xml"]*zip.File
worksheetFileMap map[string]*zip.File
Expand Down Expand Up @@ -99,8 +101,9 @@ func (conn *connect) Close() error {

// NewReader generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
func (conn *connect) NewReader(sheetNamer interface{}) (Reader, error) {
return conn.NewReaderByConfig(&Config{Sheet: sheetNamer})
}
Expand All @@ -119,7 +122,7 @@ func (conn *connect) NewReaderByConfig(config *Config) (Reader, error) {
if conn.zipReader == nil {
return nil, ErrConnectNotOpened
}
sheet := parseSheetName(config.Sheet)
sheet := conn.parseSheetName(config.Sheet)
sheet = config.Prefix + sheet + config.Suffix
workSheetFile, ok := conn.worksheetNameFileMap[sheet]
if !ok {
Expand Down Expand Up @@ -246,7 +249,8 @@ func (conn *connect) readWorkbook() error {
if conn.sheets == nil {
conn.sheets = make([]string, 0, len(wb.Sheets.Sheet))
}
conn.worksheetNameFileMap = make(map[string]*zip.File)
conn.worksheetNameFileMap = make(map[string]*zip.File, len(wb.Sheets.Sheet))
conn.worksheetIDToNameMap = make(map[string]string, len(wb.Sheets.Sheet))
for _, sheet := range wb.Sheets.Sheet {
conn.sheets = append(conn.sheets, sheet.Name)
// record the sheet name to *zip.File
Expand All @@ -261,6 +265,7 @@ func (conn *connect) readWorkbook() error {
}
// log.Println(sheet.Name)
conn.worksheetNameFileMap[sheet.Name] = file
conn.worksheetIDToNameMap[sheet.SheetID] = sheet.Name
}
rc.Close()
return nil
Expand Down
7 changes: 7 additions & 0 deletions standard_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func ExampleReader_readStruct() {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -78,6 +79,7 @@ func ExampleReader_readAllSliceStruct() {
var stdList []Standard
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -131,6 +133,7 @@ func ExampleReader_readAllSlicePtr() {
var stdList []*Standard
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -174,6 +177,7 @@ func ExampleReader_readBinaryAllSlicePtr() {
var stdList []*Standard
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -210,6 +214,7 @@ func ExampleReader_readMap() {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -252,6 +257,7 @@ func ExampleReader_readAllSliceMap() {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -290,6 +296,7 @@ func ExampleReader_readAllSliceMapOtherValueType() {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down
40 changes: 40 additions & 0 deletions standard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ func TestReadStandard(t *testing.T) {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will use sheet as sheet name.
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand All @@ -209,6 +210,40 @@ func TestReadStandard(t *testing.T) {
}
}

func TestReadStandardIndex(t *testing.T) {
conn := excel.NewConnecter()
err := conn.Open(filePath)
if err != nil {
t.Error(err)
return
}
defer conn.Close()

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will use sheet as sheet name.
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
rd, err := conn.NewReader(2)
if err != nil {
t.Error(err)
return
}
defer rd.Close()

idx := 0
for rd.Next() {
var s Standard
rd.Read(&s)
expectStd := expectStandardList[idx]
if !reflect.DeepEqual(s, expectStd) {
t.Errorf("unexpect std at %d = \n%s", idx, convert.MustJsonPrettyString(expectStd))
}
idx++
}
}

func TestReadStandardAll(t *testing.T) {
conn := excel.NewConnecter()
err := conn.Open(filePath)
Expand All @@ -221,6 +256,7 @@ func TestReadStandardAll(t *testing.T) {
var stdList []Standard
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -265,6 +301,7 @@ func TestReadStandardPtrAll(t *testing.T) {
var stdList []*Standard
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -303,6 +340,7 @@ func TestReadBinaryStandardPtrAll(t *testing.T) {
var stdList []*Standard
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -334,6 +372,7 @@ func TestReadStandardMap(t *testing.T) {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down Expand Up @@ -368,6 +407,7 @@ func TestReadStandardSliceMap(t *testing.T) {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down
2 changes: 2 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,14 @@ type Connecter interface {

// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
NewReader(sheetNamer interface{}) (Reader, error)
// Generate an new reader of a sheet
// sheetNamer: if sheetNamer is string, will use sheet as sheet name.
// if sheetNamer is int, will i'th sheet in the workbook, be careful the hidden sheet is counted. i ∈ [1,+inf]
// if sheetNamer is a object implements `GetXLSXSheetName()string`, the return value will be used.
// otherwise, will use sheetNamer as struct and reflect for it's name.
// if sheetNamer is a slice, the type of element will be used to infer like before.
Expand Down
10 changes: 8 additions & 2 deletions utils.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
package excel

import (
"fmt"
"reflect"
)

func parseSheetName(i interface{}) string {
func (conn *connect) parseSheetName(i interface{}) string {
switch s := i.(type) {
case string:
return s
case int, int8, int32, int64, uint, uint8, uint16, uint32, uint64:
if name, ok := conn.worksheetIDToNameMap[fmt.Sprintf("%d", s)]; ok {
return name
}
return ""
case interface {
GetXLSXSheetName() string
}:
Expand All @@ -21,7 +27,7 @@ func parseSheetName(i interface{}) string {
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
return parseSheetName(reflect.New(typ).Elem().Interface())
return conn.parseSheetName(reflect.New(typ).Elem().Interface())
default:
return typ.Name()
}
Expand Down
5 changes: 3 additions & 2 deletions xml_workbook.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ type xlsxSheets struct {
// xlsxSheet directly maps the sheet element from the namespace
// http://schemas.openxmlformats.org/spreadsheetml/2006/main
type xlsxSheet struct {
Name string `xml:"name,attr,omitempty"`
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
Name string `xml:"name,attr,omitempty"`
SheetID string `xml:"sheetId,attr,omitempty"`
RID string `xml:"http://schemas.openxmlformats.org/officeDocument/2006/relationships id,attr,omitempty"`
}

0 comments on commit 44eec79

Please sign in to comment.