LoginSignup
1
0

More than 3 years have passed since last update.

Go xlsファイルを読み取る

Last updated at Posted at 2020-06-01

Go xlsファイルを読み取る

今回は、Goで Excel の xlsファイル(Excel 97 ~ Excel 2003 ブック) を読み取る方法を考えてみます。

xlsxファイルの場合は、 excelize がオススメです。

ライブラリ

簡単に読み取りを行うなら、下記のライブラリを使うとよいです。

GitHub - extrame/xls: Pure Golang xls library
https://github.com/extrame/xls

↓ Example を参考に書いてみるとこんな感じ

package main

import (
    "fmt"
    "log"

    "github.com/extrame/xls"
)

func main() {
    xlFile, err := xls.Open("input.xls", "utf-8")
    if err != nil {
        log.Fatal(err)
    }

    sheet1 := xlFile.GetSheet(0)
    if sheet1 != nil {
        fmt.Printf("Total Lines : %d (%s)\n", sheet1.MaxRow, sheet1.Name)
        for row := 0; row < int(sheet1.MaxRow); row++ {
            // sheet から 行 を取り出す
            r := sheet1.Row(row)
            for col := r.FirstCol(); col < r.LastCol(); col++ {
                // 行(row) と 列(col) を指定すると 値 が返ってくる
                value := sheet1.Row(row).Col(col)
                // 下記でもよい
                // value := r.Col(col)

                fmt.Printf("(%d, %d) = %s\n", row, col, value)
            }
        }
    }
}

詳しくは、下記をご覧ください。

xls - GoDoc
https://godoc.org/github.com/extrame/xls

2020/06/01 時点では、うまく読み込めないものがあります。

うまく読み込めないもの

数式の含まれたファイル

例えば 参照セル =A2 というような数式となっていると、紹介したライブラリでは読めなさそう?
※数式の入ったセルの値が空文字となる

パスワードがかかったもの

パスワードかかったファイルの読み込みには対応していない

なんとかして読み込む

そんなファイルたちをOLEで読み込んでみましょう。

Object Linking and Embedding - Wikipedia
https://ja.wikipedia.org/wiki/Object_Linking_and_Embedding

ただOLEを使う場合、デメリットもあります。

  • 動作速度が遅い
    • 命令を送ってアプリケーションを操作してというような処理なのであまり早くはならない
  • サーバーサイドで使いにくい
    • Excelを直接動かすため、サーバーサイドでは使いにくいですね
  • メモリやパワーがいる
    • 裏でExcelが立ち上がって、なんやかんやするのでそれなりに負荷はあります

実装

ただ値を取りたいだけなのですが、かなりめんどくさい処理になってます。
※いい方法があったら教えてください

単にちょっとだけ情報取りたいだけなら
OLEで完結させてもいいかもしれません。
※OLE経由でセル情報を取得することができる

すべてのセルを見たい場合は、
別の扱いやすいファイルに直したほうが早いかなと思ったので
以下の方法を考えてみました。

  1. テンポラリファイルパスを作る (ioutil.TempFile)
  2. Excelを立ち上げる (OLE)
  3. xlsファイルを開く (OLE)
  4. csvファイル(テンポラリ)へ保存する (OLE)
  5. csvファイル(テンポラリ)を開く (encoding/csv)

別にcsvファイルでなくてもよいのですが、
公式packageにcsv読み込めるものがあるので利用しました。

出来上がったソースが、以下です。
※エラーとかあまり考慮してない

$ go build & xxx.exe xxx.xls な感じで読み込みできます。

実行には、Excelが必要です。

ソース
package main

import (
    "encoding/csv"
    "fmt"
    "io/ioutil"
    "log"
    "os"
    "path/filepath"

    "github.com/mattn/go-ole"
    "github.com/tanaton/go-ole-msoffice/excel"
    "golang.org/x/text/encoding/japanese"
    "golang.org/x/text/transform"
)

func main() {
    args := os.Args

    rows, err := getXlsData(args[1])
    if err != nil {
        log.Fatal(err)
    }
    fmt.Printf("%#v", rows)
}

func getXlsData(path string) ([][]string, error) {
    var rows [][]string

    // テンポラリファイルパス作成
    dist, err := ioutil.TempFile("", "*.csv")
    if err != nil {
        return rows, err
    }
    dist.Close()
    os.Remove(dist.Name())
    // 処理後削除
    defer os.Remove(dist.Name())

    // OLE
    ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE)
    defer ole.CoUninitialize()

    // Excelを取得する
    e := excel.ThisApplication()
    if e == nil {
        return rows, nil
    }

    // Excel設定: アラートの表示(true: する、false: しない)
    e.SetDisplayAlerts(false)
    // Excel設定: Excel自体の表示(true: する、false: しない)
    e.SetVisible(false)

    workbooks := e.GetWorkbooks()

    // 必ず絶対パスにする
    absPath := path
    if !filepath.IsAbs(absPath) {
        absPath, err = filepath.Abs(path)
        if err != nil {
            return rows, err
        }
    }

    // Excelファイルを開く
    book := workbooks.Open(absPath)

    // csvファイルとして保存する
    book.SaveAs(dist.Name(), excel.XlCSV)

    // ファイルとExcelを閉じる
    book.Close()
    e.Quit()
    e.Release()

    // csvファイルを開いて読み込む
    f, err := os.Open(dist.Name())
    if err != nil {
        return rows, err
    }
    defer f.Close()

    r := csv.NewReader(transform.NewReader(f, japanese.ShiftJIS.NewDecoder()))
    return r.ReadAll()
}

パスワード付きを読み込む場合

下記のようにすれば、パスワードがかかったものも読めます。

// Open(FileName, UpdateLinks, ReadOnly, Format, Password)
book := workbooks.Open(src, 0, true, 5, password)

Open メソッド (Excel) | Microsoft Docs
https://docs.microsoft.com/ja-jp/office/vba/api/excel.workbooks.open

まとめ

OLEを使って xlsファイルの読み込みをやってみました。
OLEを使うことによって、いろんなことができると思うので試してみてくださいね。
xlsファイルだけじゃなくてExcelで扱えるファイルは、OLE経由で読めるはず。

あと いい方法・いいpackageあったら教えてください (o*。_。)o

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0