#mynavi(Go言語) #setlinebreak(on); * 概要 [#de109c52] #html(<div class="pl10">) xlsx を使用して Excel のデータ読み込みを行う。 https://github.com/tealeg/xlsx #html(</div>) * 目次 [#g4f66403] #contents * パッケージのインストール [#t1b7468c] #html(<div class="pl10">) #myterm2(){{ go get github.com/tealeg/xlsx }} ※ github.com/tealeg/xlsx/v3 v3.2.0 #html(</div>) * Excel作成 [#fd62442d] #html(<div class="pl10">) 利用しているパッケージの(xlsx)の特性上、数値の int or float の判別が正確にできない為、1行目に項目名、2行目にデータ型を入力する方式とした。 sample1.xlsx #html(){{ <div id="tabs1"> <ul> <li><a href="#tabs1-1">Sheet1</a></li> <li><a href="#tabs1-2">Sheet2</a></li> </ul> }} #html(<div id="tabs1-1">) | col1 | col2 | col2 | col3 |h |float | int | string | formula | |1.23 | 1 | abc | abc1.23 | |4.56 | 2 | def | def4.56 | |7.89 | 3 | ghi | ghi7.89 | #html(</div>) #html(<div id="tabs1-2">) | field1 | field2 | field3 | field4 |h | int | int | float | float | | 1 | 4 | 1.2 | 5.6 | | 2 | 5 | 2.3 | 7.8 | | 3 | 6 | 3.4 | 8.9 | #html(</div>) #html(</div>) #html(<script>$(function() { $("#tabs1").tabs(); });</script>) #html(</div>) * ソース作成 [#f9683538] #html(<div class="pl10">) #mycode2(){{ package main import ( "fmt" "errors" "github.com/tealeg/xlsx/v3" ) func ReadSheets(filePath string) (map[string][]map[string]interface{}, error){ data := make(map[string][]map[string]interface{}) wb, err := xlsx.OpenFile(filePath) if err != nil { return data, err } // シート名の一覧 for _, sh := range wb.Sheets { //sh.Close() sheetData, err := ReadSheet(filePath, sh.Name) if err != nil { return data, nil } data[sh.Name] = sheetData } return data, nil } func ReadSheet(filePath string, sheetName string) ([]map[string]interface{}, error){ rows := make([]map[string]interface{}, 0) wb, err := xlsx.OpenFile(filePath) if err != nil { return rows, err } sh, ok := wb.Sheet[sheetName] if !ok { return rows, errors.New(fmt.Sprintf("Sheet %s does not exist", sheetName)) } defer sh.Close() colNames := make([]string, 0) getColNames := func(c *xlsx.Cell) error { value, err := c.FormattedValue() if err != nil { return err } colNames = append(colNames, value) return nil } typeNames := make([]string, 0) getTypeNames := func(c *xlsx.Cell) error { value, err := c.FormattedValue() if err != nil { return err } typeNames = append(typeNames, value) return nil } getValues := func(c *xlsx.Cell) error { value, err := c.FormattedValue() if err != nil { return err } cellNo, rowNo := c.GetCoordinates() rowNo = rowNo - 2 if len(rows) < rowNo + 1 { rec := make(map[string]interface{}) rows = append(rows, rec) } colname := colNames[cellNo] rec := &(rows[rowNo]) if typeNames[cellNo] == "int" { intVal, _ := c.Int64() (*rec)[colname] = intVal } else if typeNames[cellNo] == "float" { floatVal, _ := c.Float() (*rec)[colname] = floatVal } else { (*rec)[colname] = value } return nil } for i := 0; i < sh.MaxRow; i++ { r, err := sh.Row(i) if err != nil { break } if i == 0 { r.ForEachCell(getColNames) } else if i == 1 { r.ForEachCell(getTypeNames) } else { r.ForEachCell(getValues) } } return rows, nil } func main(){ filePath := "/path/to/sample1.xlsx" data, err := ReadSheets(filePath) if err != nil { fmt.Printf("Error! %v", err) panic(err) } // 全シート読み込み for sheetName, rows := range data { fmt.Printf("### %s ###\n", sheetName) for i, rec := range rows { for colname, colvalue := range rec { fmt.Printf("%d, %v: %v\n", i, colname, colvalue) } } } // シート名を指定して読み込み //rows, err := ReadSheet(filePath, sheetName) //for i, rec := range rows { // for colname, colvalue := range rec { // fmt.Printf("%d, %v: %v\n", i, colname, colvalue) // } //} } }} #html(</div>) * 動作確認 [#sffa5857] #html(<div class="pl10">) #myterm2(){{ go run main.go ### Sheet1 ### 0, col2: abc 0, col3: abc1.23 0, col1: 1.23 1, col1: 4.56 1, col2: def 1, col3: def4.56 2, col1: 7.89 2, col2: ghi 2, col3: ghi7.89 ### Sheet2 ### 0, field1: 1 0, field2: 4 0, field3: 1.2 0, field4: 5.6 1, field4: 7.8 1, field1: 2 1, field2: 5 1, field3: 2.3 2, field3: 3.4 2, field4: 8.9 2, field1: 3 2, field2: 6 }} #html(</div>)