Golden Road

信じた道なら行けばいい

スプレッドシートのデータを取得する

slack botスプレッドシートからデータ取得する場面があったので調査して検証がてらgolangで実装してみた。
気をつける所とかメモ的に書いておく。

作ったのはスプレッドシートで重み付け抽選を行うアプリ。

github.com

認証

認証方法はAPIキー、OAuth、サービスアカウントの3つがある。

f:id:i178inaba:20190313020229p:plain

いずれもGCPの『APIとサービス』から取得できる。

APIキー

公開されたスプレッドシートしか読み込めないようだったので今回はパス。

OAuthクライアントID

一度ユーザがブラウザを開いて認証する必要がある。
bot用には使えないなーと思ったのでパス。

サービスアカウント

新しくGoogleアカウントを発行するイメージ。
スプレッドシートに招待して使う。

招待してしまえばずっと使えるためbotには合っていると思い、今回はサービスアカウントを使用することにした。

使用方法

発行したjsonキーファイルの中から client_email を取り出す。

$ cat /path/to/key.json | jq -r .client_email
test@quickstart-1551059800000.iam.gserviceaccount.com

データを取得したいスプレッドシートに移動して右上の共有ボタンをクリック。
『他のユーザと共有』ダイアログを開き、先程取得した client_email を追加する。

f:id:i178inaba:20190313022722p:plain

実装

実装側の認証には google.JWTConfigFromJSON を使う。
キーjsonファイルの中身とスコープ(今回は取得なのでreadonly)を渡す。

conf, err := google.JWTConfigFromJSON(
    jsonKeyBytes, 
    "https://www.googleapis.com/auth/spreadsheets.readonly"
)

返ってきた conf からhttpクライアントを取得し、 sheets.New に渡して Service を取得する。

srv, err := sheets.New(conf.Client(ctx))

あとは取得したサービスを使ってGetすればいい。
スプレッドシートIDと取得するデータのレンジ(下記の例では A2:B )を指定する。
( A2:B はA2セルからB列の最後のセルまでという意味)

resp, err := srv.Spreadsheets.Values.Get(spreadsheetID, "A2:B").Context(ctx).Do()

var items []lotteryItem
for _, row := range resp.Values {
    name := row[0].(string)
    weight, err := strconv.Atoi(row[1].(string))

    items = append(items, lotteryItem{name: name, weight: weight})
}

※エラーハンドリングは省略してあります。

列方向への取得

デフォルトでは行方向の取得になるが、列方向に取得したい場合は MajorDimensionCOLUMNS を指定すればよい。

resp, err := srv.Spreadsheets.Values.Get(spreadsheetID, "A2:B").Context(ctx).MajorDimension("COLUMNS").Do()

参考

developers.google.com godoc.org