先照著 官方文件 的入門步驟做
以下快速帶過這文件內總共做了哪些事情:
1. Enable the Google Sheets API
輸入專案的名稱,最後會得到 credientials.json
的檔案,裡面存放client_id
、project_id
、client_secret
等等,
這些變數都是為了做 開放授權(OAuth) 這事,詳細可以看此篇介紹
2. 下載套件
不曉得為何我載的時候花了很久時間
$ go get -u google.golang.org/api/sheets/v4
$ go get -u golang.org/x/oauth2/google
3. 執行quickstart範例程式
https://github.com/googleworkspace/go-samples/blob/master/sheets/quickstart/quickstart.go
執行完畢會出現如下的網址
點擊進去,點選進階、進入、授權
得到這一組授權碼
最後將授權碼貼回,讓程式產生token
專案底下自動產出的 token
,裡面有 access_token
再執行一次程式,沒意外的話 會印出如下的結果
這等於是用你同意的授權(Read權限)去開 這一份表單,讀取範圍並且把其中兩個欄位的值印出來。
到這邊為止,是 官方文件 Go Quickstart 所做的事。
往下看之前,先大略看過 Quickstart 程式碼的流程,
前幾個 func
都是做與 Config
, Token
相關的事情,
只有在 main
後半部,將試算表內的數值讀出時 才使用到 sheets API
的功能。
srv, err := sheets.New(client)
文件範例程式碼的 sheets.New() 方法已經被棄用了
New方法未來可能會不支援
可以改成以下的方法,透過option.WithHTTPClient
以及 sheets.NewService
來達成。
client := getClient(config)
clientOpts := option.WithHTTPClient(client)
srv, err := sheets.NewService(context.Background(), clientOpts)
if err != nil {
log.Fatalf("Unable to retrieve Sheets client: %v", err)
}
Class Data!A2:E
驚嘆號!
前是表(Table)的名稱
在func ConfigFromJSON
中的https://www.googleapis.com/auth/spreadsheets.readonly
,
把readonly拿掉就能有讀/寫權限,只不過需要刪除Token再產生一次。詳細值參照文件 https://developers.google.com/sheets/api/guides/authorizing#OAuth2Authorizing
取得一個範圍內的值 Get
resp, err := srv.Spreadsheets.Values.Get(SpreadsheetId, readRange).Do()
取得多個範圍的值 BatchGet
resp, err := srv.Spreadsheets.Values.BatchGet(SpreadsheetId).Ranges(readRange1, readRange2).Do()
把剛剛讀取到的欄位數值套用寫回
res, err := srv.Spreadsheets.Values.Update(SpreadsheetId, readRange, resp).ValueInputOption("RAW").Do()
其中的 RAW
可以換成 USER_ENTERED
詳見文檔
vr := sheets.ValueRange{
MajorDimension: "",
Range: "",
Values: nil,
ServerResponse: googleapi.ServerResponse{},
ForceSendFields: nil,
NullFields: nil,
}
MajorDimension: (解析方式的)主要維度
ROWS
表示以 列 方式讀取(先由左至右 再上到下)[[1,2],[3,4]]
COLUMNS
表示以 欄 方式讀取(先由上到下 再左至右)[[1,3],[2,4]]
Range: 範圍,例如 A2:E5
Values: 值。 例如 [[test1 testtest 12] [test2 testtest 4]]
,型別為[][]interface{}
ServerResponse: 伺服器回傳的東西,如 HTTPStatusCode:200
、Header
、Cache-Control
等等
為了將值代入Values中,
需要讓 2D slice string 轉成 2D slice interface,
這邊提供兩個不一樣的方法:
data1D := []string{"1111", "2222"}
s1D := make([]interface{}, len(data1D))
for i, v := range data1D {
s1D[i] = v
}
s2D := [][]interface{}{}
s2D = append(s2D, s1D)
data2D := [][]string{{"AAAA", "1222"}, {"CCCC", "9999,999,1234"}}
s2D := make([][]interface{}, len(data2D))
for i, v := range data2D {
for j, x := range v {
if j == 0 {
s2D[i] = make([]interface{}, len(data2D[0]))
}
s2D[i][j] = x
}
}
創一個 Test資料表 來試試看:
Update前
再來將 data1D
用Update更新回去
vr := sheets.ValueRange{
MajorDimension: "ROWS",
Values: s2D,
}
res, err := Srv.Spreadsheets.Values.Update(SpreadsheetId, "Test!A2:E5", &vr).ValueInputOption("USER_ENTERED").Do()
Update後
一次修改多個範圍 BatchUpdate
var valueRanges = []*sheets.ValueRange{}
for _, ... := range ... {
...
...
valueRanges = append(valueRanges, &valueRange)
}
var batchUpdateRequest = sheets.BatchUpdateValuesRequest{
Data: valueRanges,
ValueInputOption: "USER_ENTERED",
}
_, err := Srv.Spreadsheets.Values.BatchUpdate(spreadsheetId, &batchUpdateRequest).Do()
if err != nil {
log.Println(err)
}
代入的欄位、用法 與Update大同小異,但 Append 不會覆寫欄位、而是附加欄位上去
如果帶入的Range範圍內已有值,則會append到最後一行(Row)。否則會填入Range中。
Append前
vr := sheets.ValueRange{
MajorDimension: "ROWS",
Values: s2D,
}
res, err := Srv.Spreadsheets.Values.Append(SpreadsheetId, "Test!A2:B2", &vr).ValueInputOption("USER_ENTERED").Do()
// Range也可以只帶 "Test!A2"
Append後
cr := sheets.ClearValuesRequest{}
res, err := Srv.Spreadsheets.Values.Clear(SpreadsheetId, "Test!A2:B2", &cr).Do()
Clear後
可以透過Range限制範圍在單一個欄位內,來達成這件事情
目前不行,
只能透過操作變數來修改指定Range範圍。
但查詢功能可以透過表單內建函式 Google Sheet Query 達成SQL語法的查詢操作,只不過沒辦法像SQL那麼便利。
=QUERY(C2:C5, "select *")
=QUERY(C2:C, "select avg(C), max(C)")
googleapi: Error 429: Quota exceeded for quota metric 'Write requests' and limit 'Write requests per minute per user' of service 'sheets.googleapis.com' for consumer 'project_number:123456789'., rateLimitExceeded
還有限制哩,不能太常對試算表進行操作,
大約限制每分鐘每位使用者只能對試算表進行修改60次,
讀取也有所限制。
這時 BatchGet、BatchUpdate 就可以起到作用拉,可以在程式內用計數器,數量到達一定程度時再傳給試算表的API,讓他一次更新。
更改背景顏色
color := sheets.Color{
Alpha: 0,
Blue: 1,
Green: 1,
Red: 0.5,
// 數值範圍在0~1之間
}
req := sheets.Request{RepeatCell: &sheets.RepeatCellRequest{
Cell: &sheets.CellData{
UserEnteredFormat: &sheets.CellFormat{
BackgroundColor: &color,
},
},
Range: &sheets.GridRange{
// 若指定範圍是 `A1:B2` 則為 (0,0) -> (2,2)
StartColumnIndex: 0,
StartRowIndex: 0,
EndColumnIndex: 2,
EndRowIndex: 2,
SheetId: 2054447095,
// SheetId 由 網址的gid而來 : https://docs.google.com/spreadsheets/d/.../edit#gid=2054447095
},
Fields: "UserEnteredFormat(BackgroundColor)", // 只改背景顏色,其他設定不動
}}
reqs := sheets.BatchUpdateSpreadsheetRequest{
Requests: []*sheets.Request{&req},
}
res, err := Srv.Spreadsheets.BatchUpdate(SpreadsheetId, &reqs).Do()
更改背景顏色後
花了好久時間才達成這一步,
表單有太多太多物件、設定跟參數了,
更新、排序、尋找、移動、亂數、字型、對齊、顏色
媽呀,族繁不及備載...
https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets/request