spreadsheetのURLだけから内容を取得してみた。

今回はシート名が不明な状態でURLだけからシートを取得する方法を書きます。
まずよくあるシートを取得するサンプルコードを紹介します。
読むとわかりますが、spreadsheetのIDとシート名を使って取得しています。

```go
package main

import (
	"context"
	"fmt"
	"log"

	"google.golang.org/api/option"
	"google.golang.org/api/sheets/v4"
)

func main() {
  spreadsheetID := "1zrqghzR3UJdrS70JLKLgujCnmGFN93vIf1B7XmtblOM"
	credential := option.WithCredentialsFile("test.json")

	srv, err := sheets.NewService(context.TODO(), credential)
	if err != nil {
		log.Fatal(err)
	}
  // シート名と参照範囲をくっつけた文字列を使う(シート名だけでもおk)
	readRange := "シート1!A1"
	resp, err := srv.Spreadsheets.Values.Get(spreadsheetID, readRange).Do()
	if err != nil {
		log.Fatalln(err)
	}

	for _, row := range resp.Values {
		fmt.Println(row)
	}

}
```

それでは [`https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxx/edit#gid=1891750325`](https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxx/edit#gid=1891750325)のようなURLだけで内容を取得するにはどうすればいいでしょうか。
調べた限りだと、シート名が分からないとシートを取得できないようなのでシート名は探す必要があります。

まずspreadsheetのURLについて解説します。構成は下記になります。
```
https://docs.google.com/spreadsheets/d/{スプレッドシートID}/edit#gid={シートID}
```
gid以降の数字のようなものがシートIDで今回の処理に必要になります。
シートIDは最初に作成されたページでは必ず0になるようです。
下記のコードはシートIDからシート名を取得しています。

```go
package main

import (
	"context"
	"fmt"
	"log"

	"google.golang.org/api/option"
	"google.golang.org/api/sheets/v4"
)

var spreadsheetID = "1zrqghzR3UJdrS70JLKLgujCnmGFN93vIf1B7XmtblOM"

func main() {
	credential := option.WithCredentialsFile("test.json")

	srv, err := sheets.NewService(context.TODO(), credential)
	if err != nil {
		log.Fatal(err)
	}

	resp, err := srv.Spreadsheets.Get(spreadsheetID).Do()
	if err != nil {
		log.Fatalln(err)
	}

	for _, v := range resp.Sheets {
		fmt.Printf("title: %s, sheet_id(gid): %d\n", v.Properties.Title, v.Properties.SheetId)
	}
}
```

このように出力されます。

```bash
title: シート1, sheet_id(gid): 0
title: シート2, sheet_id(gid): 680451458
title: シート3, sheet_id(gid): 1891750325
title: シート4, sheet_id(gid): 317507870
```

全探索して一致するシートIDからシート名を取得できそうです。
このロジックを使ってURLからシートの内容を取得する処理を一通り書きます。
今までと違って必要な手順ごとに関数で分けてます。

```go
package main

import (
	"context"
	"fmt"
	"log"
	"net/url"
	"regexp"
	"strconv"

	"google.golang.org/api/option"
	"google.golang.org/api/sheets/v4"
)

func createService(ctx context.Context) (srv *sheets.Service, err error) {
	credential := option.WithCredentialsFile("test.json")

	srv, err = sheets.NewService(ctx, credential)
	if err != nil {
		return
	}

	return
}

//regex使ってみた
func getID(spreadSheetURL string) (spreadsheetID string, sheetID int64, err error) {
	u, err := url.Parse(spreadSheetURL)
	if err != nil {
		return
	}
	repPath := regexp.MustCompile(`/`)
	spreadsheetID = repPath.Split(u.Path, -1)[3]
	repFragment := regexp.MustCompile(`gid=`)
	tmp := repFragment.Split(u.Fragment, -1)[1]
	sheetID, err = strconv.ParseInt(tmp, 10, 64)
	if err != nil {
		return "", 0, err
	}

	return
}

// ここ重要
func getSheetName(srv *sheets.Service, spreadsheetID string, sheetID int64) (sheetName string, err error) {
	resp, err := srv.Spreadsheets.Get(spreadsheetID).Do()
	if err != nil {
		return
	}

	for _, v := range resp.Sheets {
		fmt.Printf("title: %s, sheet_id: (gid)%d\n", v.Properties.Title, v.Properties.SheetId)
		if sheetID == v.Properties.SheetId {
			sheetName = v.Properties.Title
			break
		}
	}
	return
}

func getSheetContent(srv *sheets.Service, sheetName string, spreadsheetID string) (content *sheets.ValueRange, err error) {
	readRange := fmt.Sprintf("%s%s", sheetName, "!A1")

	content, err = srv.Spreadsheets.Values.Get(spreadsheetID, readRange).Do()
	if err != nil {
		return
	}
	return
}

func main() {
	spreadSheetURL := "https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxx/edit#gid=1891750325"
	ctx := context.Background()
	srv, err := createService(ctx)

	if err != nil {
		log.Fatalln(err)
	}

	spreadsheetID, sheetID, err := getID(spreadSheetURL)
	if err != nil {
		log.Fatalln(err)
	}

	sheetName, err := getSheetName(srv, spreadsheetID, sheetID)
	if err != nil {
		log.Fatalln(err)
	}

	content, err := getSheetContent(srv, sheetName, spreadsheetID)
	if err != nil {s
		log.Fatalln(err)
	}

	fmt.Println(content.Values)

}
```

シートIDから取得する方法はサンプルコードやブログでは書かれていなかったので[リファレンス](https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/sheets)を読み込んだところヒントを見つけました。需要ないのかな…
Sheetsからは色々な情報が取得できるので困ったら見てみると助かるかもしれません。

よかったらいいねお願いします。