Go言語からGoogle Sheets API v4でスプレッドシートを新規作成する方法

## 概要
Google Sheets API v4 のGo言語用クライアントを利用して新規にスプレッドシートを作成する方法を調べてみました。

とりあえずやってみたかった事は以下の通りです。

1. プログラムからスプレッドシートを新規作成。
2. 作成したスプレッドシートのセルに値を書き込む。
3. 書き込んだセルに枠線を付ける。

Googleの公式ドキュメントを見ると、最初の例として載っているのは既存のスプレッドシートを読み込んで出力する物でした。
https://developers.google.com/sheets/api/quickstart/go

新規作成を行うAPIの説明にもサンプルコードがあったのですが、読んで見るとコードにTODOと書かれている状態なのでそのまま利用はできません。
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/create

というわけで探り探りAPIとGoのクライアントライブラリからの操作方法を調べてみた次第です。
基本的には以下のリファレンスドキュメントを行ったり来たりしながらの作業でした。

Google Sheets API v4のリファレンス
https://developers.google.com/sheets/api/reference/rest/

Go言語用クライアントライブラリのリファレンス
https://godoc.org/google.golang.org/api/sheets/v4

その結果を[Go Quickstartページ](https://developers.google.com/sheets/api/quickstart/go)の手順に則ってまとめてみました。

## 事前準備
[Go Quickstartページ](https://developers.google.com/sheets/api/quickstart/go)の **"Prerequisites"** の項には以下のようにあります。

- Goの最新バージョンを推奨します。
	- 本投稿の例では1.9.2を利用しました。
- Gitの最新バージョンを推奨します。
	- 本投稿の例では2.15.1を利用しました。
- インターネットとWebブラウザにアクセスできる事。
- Googleアカウントを持っている事。
	- これらは当然ですね。

## Google APIを利用できるようにする方法
[Go Quickstartページ](https://developers.google.com/sheets/api/quickstart/go)の **"Step 1: Turn on the Google Sheets API"** の項を和訳して注釈を入れたものを載せておきます。

a. [このウィザード](https://console.developers.google.com/start/api?id=sheets.googleapis.com)を使用してGoogle APIコンソールでプロジェクトを作成または選択し、APIを有効にします。

b．[プロジェクトに資格情報を追加]ページで、[キャンセル]ボタンをクリックします。

b-ex. ファイルの新規作成には **"Sheets API"** だけではなく **"Drive API"** も必要になるのでこのタイミングで有効にします。

1. [ダッシュボード]ページにある[APIとサービスの有効化]リンクをクリックします。
2. **"新しい API ライブラリへようこそ"** と書かれたページに遷移するのでここで **"Google Drive API"** を検索して選択し、開かれたページで[有効にする]ボタンをクリックします。
3. [認証情報]のページに戻り、後続のステップを続けます。

c. [認証情報]ページの上部にある[OAuth 同意画面]タブを選択します。メールアドレスを選択し、まだ設定されていない場合は[ユーザーに表示するサービス名]を入力し、[保存]ボタンをクリックします。

d. [認証情報]タブを選択し、[認証情報の作成]ボタンをクリックして、[OAuth クライアント ID]を選択します。

e. アプリケーションの種類から[その他]を選択し、[Google Sheets API Quickstart]という名前を入力して[作成]ボタンをクリックします。

- アプリケーションの名前は任意の物で大丈夫です。

f. [OK]をクリックしてダイアログを終了します。

g. クライアントIDの右側にある↓（JSONのダウンロード）ボタンをクリックします。

h. このファイルを作業ディレクトリに移動し、名前を"client_secret.json"に変更します。

- 作業ディレクトリとはこれから作成するソースコードと同じディレクトリを指します。

## Go言語用のGoogle APIクライアントとOAuth2パッケージをインストール
[Go Quickstartページ](https://developers.google.com/sheets/api/quickstart/go)の **"Step 2: Prepare the workspace"** の項にある通りです。
ここは短い作業であり、このページを見れば迷う事は無いと思うので省略します。

## サンプルコード
[Go Quickstartページ](https://developers.google.com/sheets/api/quickstart/go)の **"Step 3: Set up the sample"** の項にあるソースコードのmain関数だけ以下で書き換え、認証の処理などはそのまま利用させてもらいました。

``` GO
func main() {
	// コンテキストを生成
	ctx := context.Background()

	// OAuth 2.0 Clint ID JSONファイルを読み込む
	b, err := ioutil.ReadFile("client_secret.json")
	if err != nil {
		log.Fatalf("Unable to read client secret file: %v", err)
	}

	// OAuth2の設定に利用を認可するGoogle APIの範囲を定義
	// これらの設定を変更する場合は以前に保存した以下の証明書ファイルを削除する
	// ~/.credentials/sheets.googleapis.com-go-quickstart.json
	config, err := google.ConfigFromJSON(b,
		"https://www.googleapis.com/auth/spreadsheets",	// Google Spreadsheetの操作全般を許可
		"https://www.googleapis.com/auth/drive.file")	// Google Driveへのファイル作成・開く事を許可
	if err != nil {
		log.Fatalf("Unable to parse client secret file to config: %v", err)
	}

	// Google APIクライアントを取得
	client := getClient(ctx, config)

	// スプレッドシートを管理する構造体を生成
	service, err := sheets.New(client)
	if err != nil {
		log.Fatalf("Unable to retrieve Sheets Client %v", err)
	}

	// 新規に生成するスプレッドシートの設定
	spreadsheet := &sheets.Spreadsheet{
		Properties: &sheets.SpreadsheetProperties{
			Title: "New Spreadsheet",	// スプレッドシートの名前
			Locale: "ja_JP",	// ロケール
			TimeZone: "Asia/Tokyo",	// タイムゾーン
		},
	}

	// スプレッドシートを新規作成
	createResponse, err := service.Spreadsheets.Create(spreadsheet).Context(ctx).Do();
	if err != nil {
		log.Fatal(err)
	}

	// シート1のA1セルを起点にして2行分書き込む
	writeRange := "シート1!A1"
    valueRange := &sheets.ValueRange{
		Values: [][]interface{}{
			[]interface{}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12},	// 1行目
			[]interface{}{200, 400, 500, 450, 300, 700, 400, 200, 350, 500, 900, 800},	// 2行目
		},
	}
	_, err = service.Spreadsheets.Values.Update(createResponse.SpreadsheetId, writeRange, valueRange).ValueInputOption("RAW").Do()
	if err != nil {
		log.Fatalf("Unable to retrieve data from sheet. %v", err)
	}

	// 枠線の範囲を設定
	gridRange := &sheets.GridRange{
		SheetId: 0,
		StartRowIndex: 0,
		EndRowIndex: 2,
		StartColumnIndex: 0,
		EndColumnIndex: 12,
	}

	// 枠線の色(RGBとAlpha値)を設定
	borderColor := &sheets.Color{
		Red: 0,
		Green: 0,
		Blue: 0,
		Alpha: 0,
	}

	// 枠線単体を設定する構造体に幅とスタイルを設定して色設定を紐付け
	border := &sheets.Border{
		Style: "SOLID",
		Width: 1,
		Color: borderColor,
	}

	// 枠線更新リクエスト構造体に枠線の設定を紐付け
	updateBordersRequest := &sheets.UpdateBordersRequest{
		Range: gridRange,
		Top: border,
		Bottom: border,
		Left: border,
		Right: border,
		InnerHorizontal: border,
		InnerVertical: border,
	}

	// スプレッドシート更新リクエスト構造体に枠線更新リクエストを紐付け
	batchUpdateRequest := &sheets.BatchUpdateSpreadsheetRequest{
		Requests: []*sheets.Request{
			&sheets.Request{
				UpdateBorders: updateBordersRequest,
			},
		},
	}

	// 更新をスプレッドシートに反映
	batchUpdateResponse, err := service.Spreadsheets.BatchUpdate(createResponse.SpreadsheetId, batchUpdateRequest).Do()
	if err != nil {
		log.Fatalf("Unable to batch update from sheet. %v", err)
	}

	fmt.Printf("Batch update response: %v", batchUpdateResponse);
}
```

## 実行方法
こちらも[Go Quickstartページ](https://developers.google.com/sheets/api/quickstart/go)の **"Step 4: Run the sample"** の項にある通りです。

## 所感
- 枠線引くだけでもなかなか手間がかかるように感じました。グラフの作成やセルの切り貼りなどほとんどの操作がAPIから行えるようですが、装飾やグラフなど設定済みのスプレッドシートを用意しておいて、値のみ書き込むのが現実的な利用方法なのかなと思いました。
- 主に非エンジニアである方から各種データをスプレッドシートに出してくれという要望を受けることがあるので、定期的に必要なものは自動的に出力するプログラムを作成すれば良いですね。