Help us understand the problem. What is going on with this article?

GoでGoogle Sheets APIを利用する【認証/セルの参照】

経緯

業務でGoogle Sheets APIを使用する機会があったので、Go言語での認証及び値の参照についてまとめてみました。
Go言語、Google Sheets APIは学習途中なので間違った記述、非推奨なコードの書き方があった場合、ご指摘いただければ幸いです。

事前準備

事前準備として下記の作業を実施します。
実行環境で下記のコマンドを実行し、パッケージをインストールします。

go get -u golang.org/x/net/context
go get -u golang.org/x/oauth2
go get -u google.golang.org/api/sheets/v4

以下の作業は詳細を割愛し、作業の流れのみ記載させていただきます。

  1. GCPにログイン
  2. 任意のプロジェクトを作成
  3. 作成したプロジェクトでGoogle Sheets API を有効化
  4. サービスアカウントを作成(ロールは選択しなくて大丈夫です)
  5. JSON形式で秘密鍵をダウンロード
  6. 使用するスプレッドシートをサービスアカウントと共有する

サービスアカウントでの認証

サンプルコード

下記のコードで認証を行います。
サンプルコードでは、エラーハンドリングを省略しております。

pakage main

import (
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "golang.org/x/oauth2/jwt"
    "google.golang.org/api/sheets/v4"
)

func main() {
    conf := &jwt.Config{
        // サービスアカウントのEメールアドレス
        Email:        "",
        // サービスアカウントのプライベート鍵
        PrivateKey:   []byte(""),
        TokenURL:     google.JWTTokenURL,
        Scopes: []string{
            "https://www.googleapis.com/auth/spreadsheets.readonly",
        },
    }

    client := conf.Client(oauth2.NoContext)
    sheetsSrv, _ := sheets.New(client)
}

jtw.Config

上記コードを実行する際は、事前準備でダウンロードしたJSONファイルに記載されているclient_emailprivate_keyjwt.Configの値をEmailPrivateKeyに追記します。
jwt.ConfigScopesではスプレッドシートに対する権限を指定しています。

URL 権限
https://www.googleapis.com/auth/spreadsheets.readonly 読み取り専用でのアクセスを許可
https://www.googleapis.com/auth/spreadsheets 読み取り/書き込みでのアクセスを許可

補足

動作確認ではなく実運用では、コードに秘密鍵やメールアドレスを埋め込むのではなく下記のようにダウンロードしたJSONファイルを同じパスに配置し読み込むなどで実装したほうが望ましいと思います。

package main

import (
    "encoding/json"
    "io/ioutil"

    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "golang.org/x/oauth2/jwt"
    "google.golang.org/api/sheets/v4"
)

type credJson struct {
    Email      string `json:"client_email"`
    PrivateKey string `json:"private_key"`
}

func main() {
    // ダウンロードしたJSONファイルの名前はcredentials.jsonとしています。
    // 必要に応じて任意のファイル名に変更してください。
    bytes, _ := ioutil.ReadFile("credentials.json")
    var cred credJson
    json.Unmarshal(bytes, &cred)

    conf := &jwt.Config{
        Email:      cred.Email,
        PrivateKey: []byte(cred.PrivateKey),
        TokenURL:   google.JWTTokenURL,
        Scopes: []string{
            "https://www.googleapis.com/auth/spreadsheets.readonly",
        },
    }

    client := conf.Client(oauth2.NoContext)
    sheetsSrv, _ := sheets.New(client)
}

セルの値を参照

サンプルコード

参照するスプレッドシートは下記のように書き込んでおります。

A B
1 hoge1 hogehoge1
2 hoge2 hogehoge2
3 hoge3 hogehoge3

参照する際は、Spreadsheets.Values.Get()を使用します。
実装する際は下記のコードのような形で実装します。
サンプルコードでは、エラーハンドリングを省略しております。

package main

import (
    "fmt"

    "golang.org/x/net/context"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "golang.org/x/oauth2/jwt"
    "google.golang.org/api/sheets/v4"
)

func main() {
    conf := &jwt.Config{
        // サービスアカウントのEメールアドレス
        Email:        "",
        // サービスアカウントのプライベート鍵
        PrivateKey:   []byte(""),
        TokenURL:     google.JWTTokenURL,
        Scopes: []string{
            "https://www.googleapis.com/auth/spreadsheets.readonly",
        },
    }

    client := conf.Client(oauth2.NoContext)
    sheetsSrv, _ := sheets.New(client)

    // スプレッドシートの指定
    spreadsheetId := ""
    // 参照範囲を指定
    valueRange := "Sheet1!A1:B3"

    ctx := context.Background()

    // セルの値を参照
    resp, _ := sheetsSrv.Spreadsheets.Values.Get(spreadsheetId, valueRange).Context(ctx).Do()

    for _, row := range resp.Values {
        fmt.Printf("%s, %s\n", row[0], row[1])
    }
}

実行結果

hoge1, hogehoge1
hoge2, hogehoge2
hoge3, hogehoge3

スプレッドシートID

Spreadsheets.Values.Get("スプレッドシートID", "範囲")で指定するスプレッドシートIDは使用するスプレッドシートのURLから取得することができます。

https://docs.google.com/spreadsheets/d/hogehoge/edit#gid=0

上記のhogehogeの部分がスプレッドシートIDとなります。
なお、#gid=以降の部分は各シートのIDとなります。

参照する範囲

Spreadsheets.Values.Get("スプレッドシートID", "範囲")で参照する範囲は下記のような記述ができます。

  • "シート名":シート全体を範囲とします。
  • "シート名!A1:B3":シートのA1からB3までを参照する範囲とします。

クエリパラメータ

Spreadsheets.Values.Get()のクエリパラメータは下記の3つあります。

  • majorDimension
  • valueRenderOption
  • dateTimeRenderOption

majorDimension

このクエリパラメータでは、行で参照するか列で参照するかを指定できます。
デフォルトはROWSです。

設定値 説明
ROWS 行から参照します。
COLUMNS 列から参照します。

サンプルコードでmajorDimensionを使用する場合は下記のように修正します。

// 35行目
resp, _ := sheetsSrv.Spreadsheets.Values.Get(spreadsheetId, valueRange).MajorDimension("COLUMNS").Context(ctx).Do()

実行結果

hoge1, hoge2
hogehoge1, hogehoge2

valueRenderOption

このクエリパラメータでは、数式が記述されているセルの値について指定することができます。
デフォルトはFORMATTED_VALUEです。

設定値 説明
FORMATTED_VALUE セルの値は数式の計算結果になります。加えてセルの表示形式が反映されます。
取得した値はstring型となります。
UNFORMATTED_VALUE セルの値は数式の計算結果になります。セルの表示形式は反映されません。
取得した値は数値の場合はfloat64型、文字列はstring型となります。
FORMULA セルの値は数式のままとなります。セルの表示形式は反映されません。
取得した値は数値の場合はfloat64型、数式と文字列はstring型となります。

サンプルコードでvalueRenderOptionを使用する場合は下記のように修正します。(ここでは設定値としてUNFORMATTED_VALUEを指定します。)

// 35行目
resp, _ := sheetsSrv.Spreadsheets.Values.Get(spreadsheetId, valueRange).ValueRenderOption("UNFORMATTED_VALUE").Context(ctx).Do()
// 38行目
fmt.Printf("%f, %f\n", row[0], row[1])

スプレッドシートを下記に変更します。(A1の表示形式は通貨に設定します。)

A B
1 12.3 =A1

実行結果

12.300000, 12.300000

dateTimeRenderOption

このクエリパラメータでは、表示形式が日付や時刻になっているセルの値について指定できます。
注意事項としてvalueRenderOptionがFORMATTED_VALUEの場合はこのクエリパラメータは無視されます。
デフォルトはSERIAL_NUMBERです。

設定値 説明
SERIAL_NUMBER 日付や時刻の値をシリアル番号で取得します。シリアル番号とは1899年12月30日から日時をカウントした値です。整数は日数を表し、小数点は余りの時間を表しています。
この設定値を指定して取得した日付や時刻の値はfloat64型となります。
FORMATTED_STRING 日付や時刻の値を表示形式の値で取得します。
この設定値を指定して取得した日付や時刻の値はstring型となります。

サンプルコードでdateTimeRenderOptionを使用する場合は下記のように修正します。(ここでは設定値としてSERIAL_NUMBERを指定します。)

// 35行目
resp, _ := sheetsSrv.Spreadsheets.Values.Get(spreadsheetId, valueRange).ValueRenderOption("UNFORMATTED_VALUE").DateTimeRenderOption("SERIAL_NUMBER").Context(ctx).Do()
// 38行目(SERIAL_NUMBERのみ)
fmt.Printf("%f, %f\n", row[0], row[1])

スプレッドシートを下記に変更します。(表示形式はA1が日付、B1を時間に設定します。)

A B
1 1899/12/31 14:59:32

実行結果

1.000000, 0.624676

参考資料

サービスアカウントでの認証

package google

セルの値を参照

Go Quickstart

Method: spreadsheets.values.get

Dimension

ValueRenderOption

DateTimeRenderOption

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした