【excelize】Go言語でExcelファイル(xlsx)を扱う

# 【excelize】Go言語でExcelファイル(xlsx)を扱う

今回は、Go言語でExcelファイルを扱う方法をまとめていきます。

## 便利なpackage

Go言語でExcelファイルから読み込む・作成するときには、

* tealeg/xlsx
     * https://github.com/tealeg/xlsx

* 360EntSecGroup-Skylar/excelize
    * https://github.com/360EntSecGroup-Skylar/excelize

をよく使っています。

個人的な主観は、`tealeg/xlsx` は書きやすく
`excelize` は細かいことできるっていうイメージです。

重たいファイルを扱うときは、
`excelize`の方が少し軽いかなっていう印象もあります。

今回は`excelize`を使って
xlsxファイルの読み込みとxlsxファイルの作成をやってみます。

## xlsxファイルの読み込み

まずはREADMEに書いてある内容を見てみましょう。

```go
package main

import (
    "fmt"

    "github.com/360EntSecGroup-Skylar/excelize"
)

func main() {
    f, err := excelize.OpenFile("./Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
    // Get value from cell by given worksheet name and axis.
    cell, err := f.GetCellValue("Sheet1", "B2")
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(cell)
    // Get all the rows in the Sheet1.
    rows, err := f.GetRows("Sheet1")
    for _, row := range rows {
        for _, colCell := range row {
            fmt.Print(colCell, "\t")
        }
        fmt.Println()
    }
}
```

### ファイルの読み込み

`excelize.OpenFile(ファイルパス)`な感じでファイルを開きます。

```go
    f, err := excelize.OpenFile("./Book1.xlsx")
    if err != nil {
        fmt.Println(err)
        return
    }
```

### セルの値を取得する

`GetCellValue(シート名、セル番地)`で取得できます。

```go
    cell, err := f.GetCellValue("Sheet1", "B2")
    if err != nil {
        fmt.Println(err)
        return
    }
```

ここで気づいた方もおられるかもしれませんが、
セル番地の指定が`A1`な形式なのです・・・。

R1C1な形式`row, col int`の方が、プログラムとしては処理しやすいと個人的には思います。

ということで
`A`(string) -> `1`(int)に変換するものを用意しないといけないのですが、、、
まぁ書くの面倒ですよね・・・。

そんなあなたに！
excelize には、ヘルパー関数が用意されているので使いましょう！

* "A" → 1 の形式に変換
    * `num, err := excelize.ColumnNameToNumber("A")`
        * `num`: 1

* 1 → "A" の形式に変換
    * `name, err := excelize.ColumnNumberToName(1)`
        * `name`: "A"

あとこんなのもありました。

* "A1" → "A", 1 に分割
    * `name, num, err := excelize.SplitCellName("A1")`
        * `name` : "A"
        * `num` : 1

* "A", 1 → "A1" に結合
    * `cellName, err := excelize.JoinCellName("A", 1)`
        * `cellName`: "A1"

* "A1" → (1, 1) に変換
    * `col, row := excelize.CellNameToCoordinates("A1")`
        * `col`(列): 1
        * `row`(行): 1

* (1, 1) → "A1" に変換
    * `cellName := excelize.CoordinatesToCellName(1, 1) // (col, row)`
        * `cellName`: "A1"

あるものは活用していきましょう！ｗ
※知らずに自分で実装していました、、、

### 行を取得する

`GetRows(シート名)`で取得できます。
あとはfor rangeで回すだけ、`colCell`に値(string)が入っています。

```go
    // Get all the rows in the Sheet1.
    rows, err := f.GetRows("Sheet1")
    for _, row := range rows {
        for _, colCell := range row {
            fmt.Print(colCell, "\t")
        }
        fmt.Println()
    }
```

## xlsxファイルの作成

続いてxlsxファイルの作成をしてみましょう。

```go
package main

import (
    "fmt"

    "github.com/360EntSecGroup-Skylar/excelize"
)

func main() {
    f := excelize.NewFile()
    // Create a new sheet.
    index := f.NewSheet("Sheet2")
    // Set value of a cell.
    f.SetCellValue("Sheet2", "A2", "Hello world.")
    f.SetCellValue("Sheet1", "B2", 100)
    // Set active sheet of the workbook.
    f.SetActiveSheet(index)
    // Save xlsx file by the given path.
    err := f.SaveAs("./Book1.xlsx")
    if err != nil {
        fmt.Println(err)
    }
}
```

### 準備

まずは、`f := excelize.NewFile()`で準備をします。
まだこの時点では、ファイルは作成されていません。

このあとは、作成した`f`に対して様々な関数を実行して内容を追加していきます。

```go
    f := excelize.NewFile()
```

### ワークシートを作成する

`f.NewSheet(ワークシート名)`で新しいワークシートを作成できます。
`NewFile()`した時点で`Sheet1`は、作成されています。

```go
    // Create a new sheet.
    index := f.NewSheet("Sheet2")
```

* ワークシートを削除する
    * `f.DeleteSheet(ワークシート名)`

### セルに値をいれる

`SetCellValue(シート名、セル番地、値)`でいれることができます。

```go
    // Set value of a cell.
    f.SetCellValue("Sheet2", "A2", "Hello world.")
    f.SetCellValue("Sheet1", "B2", 100)
```

### 表示するワークシートを変更する

`SetActiveSheet(index)`で開いたときに表示するワークシートを設定できます。

```go
    // Set active sheet of the workbook.
    f.SetActiveSheet(index)
```

この`index`は、先ほど`index := f.NewSheet("Sheet2")`で作ったものです。

シートに番号が振られているようですね。
あとから`index`を取得したいときは、`f.GetSheetIndex(シート名)`で取得できます。

### ファイルを作成する

`f.SaveAs(ファイルパス)`で指定したパスにファイルが作成されます。

```go
    // Save xlsx file by the given path.
    err := f.SaveAs("./Book1.xlsx")
    if err != nil {
        fmt.Println(err)
    }
```

## いろいろな設定

その他にもいろいろな設定があります。
最近使ったものをご紹介します。

### 列幅を設定する

`f.SetColWidth(シート名、開始列、終了列、列幅)`

```go
err := f.SetColWidth("Sheet1", "A", "B", 20)
````

### 枠線表示

デフォルトで表示されている枠線を非表示にするときは、以下のようにします。

```go
f.SetSheetViewOptions("Sheet1", 0, excelize.ShowGridLines(false))
```

### セルの書式設定

これがなかなか手強い。。。

書式設定は、jsonで定義してstyleIDを取得してセルに設定するという流れです。

複数の設定をしたいときは、組み合わせて使えます。

詳しくは、https://xuri.me/excelize/ja/style.html

#### 罫線

```go
// 枠線 (外枠)
style := `{"border":[
		{"type":"bottom","color":"000000","style":1},
		{"type":"top","color":"000000","style":1},
		{"type":"left","color":"000000","style":1},
		{"type":"right","color":"000000","style":1}
		]}`
styleID, err := f.NewStyle(style)
if err != nil {
	log.Fatal(err)
}
f.SetCellStyle("Sheet1", "A1", "A1", styleID)
```

* 太線 は `"style":5` にする 
    * `{"border":[{"type":"right","color":"000000","style":5}]}`
* `"type"` で向きを指定
    * `top`: 上 の設定
    * `bottom`: 下 の設定
    * `left`: 左 の設定
    * `right`: 右 の設定

#### セル内の文字位置

上下左右 中央揃えのときは、下記のようにします。

```
{"alignment":{"horizontal": "center", "vertical": "center"}}
```

* horizontal
    * 水平(左右)方向の設定
        * `left`: 左
        * `center`: 中央
        * `right`: 右

* vertical
    * 垂直(上下)方向の設定
        * `top`: 上
        * `center`: 中央
        * `bottom`: 下

#### 構造体から書式設定する (v2.20～)

```go
style := &excelize.Style{
    Alignment: &excelize.Alignment{
        WrapText: true,
    },
}
styleID, err := f.NewStyle(style)
```

`excelize.Style` については、下記あたりを参照。
[excelize/xmlStyles.go L362～](https://github.com/360EntSecGroup-Skylar/excelize/blob/882abb80988b7c50286dd2e6c6589fab10662db6/xmlStyles.go#L362) 

## リファレンス

その他詳しい使い方は、下記のページをご覧ください。

* excelize - GoDoc
    * https://godoc.org/github.com/360EntSecGroup-Skylar/excelize
        * 関数などの基本的な情報はこちら

* introduction - Excelize Document
    * https://xuri.me/excelize/en/
    * https://xuri.me/excelize/ja/ (日本語)
        * こちらのほうが詳しく書かれてあります

## まとめ

セルの書式設定は少々苦戦する?かもしれませんが、、。
便利な関数を用意してくれているおかげで、ファイルは簡単に作れるかとおもいます。

ぜひGo言語でxlsxファイルをいじってみてくださいね～！