Excel も CSV みたいに扱いたい
半年ほど前に
という記事を書いたのだが,その後色々あって Excel や LibreOffice Calc のファイルも同じように扱いたいと思い,拙作の github.com/goark/csvdata パッケージを改造することにした。取るに足らないパッケージでも残しておくものである(笑)
前の記事と比べてみると,以前は
rc := csvdata.New(strings.NewReader(planets), true)
としていたのを
rc := csvdata.NewRows(csvdata.New(strings.NewReader(planets)), true)
と New() 関数を2段階に分けた。
外側の csvdata.NewRows() 関数の引数を
//RowsReader is interface type for reading columns in a row.
type RowsReader interface {
Read() ([]string, error)
Close() error
}
func NewRows(rr RowsReader, headerFlag bool) *Rows { ... }
と interface 型にすることによって CSV 形式以外のファイルも受け入れるようにしようというわけ。いわゆる依存の注入(dependency injection)ですな。 Go では継承関係とか考えなくても interface 型を間に差し込むことで簡単に依存の注入を設計・実装できる。
まぁ,破壊的変更になるんだけど,私以外使ってる気配はないし,ええじゃろう(笑)
Excel ファイルの場合は
package exceldata_test
import (
"fmt"
"github.com/goark/csvdata"
"github.com/goark/csvdata/exceldata"
)
func ExampleNew() {
xlsx, err := exceldata.OpenFile("testdata/sample.xlsx", "")
if err != nil {
fmt.Println(err)
return
}
r, err := exceldata.New(xlsx, "")
if err != nil {
fmt.Println(err)
return
}
rc := csvdata.NewRows(r, true)
defer rc.Close() //dummy
if err := rc.Next(); err != nil {
fmt.Println(err)
return
}
fmt.Println(rc.Column("name"))
// Output:
// Mercury
}
exceldata.OpenFile() 関数の引数で Excel ファイルへのパスとパスワードを指定し(パスワードロックされていなければ空文字列でOK), exceldata.New() 関数の引数で Excel データインスタンスとシート名を指定する(シート名が空文字列なら最初のシート)。あとは CSV と同じ手順でデータにアクセスできる。
LibreOffice Calc ファイルも同様に
package calcdata_test
import (
"fmt"
"github.com/goark/csvdata"
"github.com/goark/csvdata/calcdata"
)
func ExampleNew() {
ods, err := calcdata.OpenFile("testdata/sample.ods")
if err != nil {
fmt.Println(err)
return
}
r, err := calcdata.New(ods, "")
if err != nil {
fmt.Println(err)
return
}
rc := csvdata.NewRows(r, true)
defer rc.Close() //dummy
if err := rc.Next(); err != nil {
fmt.Println(err)
return
}
fmt.Println(rc.Column("name"))
// Output:
// Mercury
}
という感じ。 Calc ファイルの場合はパスワードロックやデータの暗号化には対応していない。ごめんペコン。
更に言うと Excel や Calc ファイルへのアクセスには以下の外部パッケージを利用しているが
どちらも中身を全てヒープ上に展開してしまうようなので,数十万行とか大きなファイルは扱えないと思う。こちらもあしからずご了承の程を。
これで CSV にいちいち変換しなくても直接扱えるようになったよ。めでたし
Discussion