概要 †xlsx を使用して Excel のデータ読み込みを行う。 目次 †パッケージのインストール †go get github.com/tealeg/xlsx ※ github.com/tealeg/xlsx/v3 v3.2.0 Excel作成 †利用しているパッケージの(xlsx)の特性上、数値の int or float の判別が正確にできない為、1行目に項目名、2行目にデータ型を入力する方式とした。 sample1.xlsx ソース作成 †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)
// }
//}
}
動作確認 †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 |