#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>)


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS