GoogleAppScriptをローカルで開発・ローカルから実行してみた



去年はdokkuを試したが、今年はGASを試してみた。
GAS自体は触ったことあるけど、クラウドだからちょっとめんどくさい・・・ってイメージで、
ローカルでやったらまた違って便利かも？と思いついたのでやってみた。



ライブラリをインストールしてログイン

```
npm i @google/clasp -g
clasp login
```

自動でブラウザが立ち上がって認証リクエストが出てきた


![スクリーンショット_2020-04-22_18_42_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/b7cde634-c155-f4d5-e1a4-73369f016e3d.png)

ちょっと権限多くてびっくり・・・。
認証すればログイン完了

```
$ clasp login
Logging in globally...
🔑 Authorize clasp by visiting this url:
https://accounts.google.com/o/oauth2/v2/auth?xxxxxxxxxxxxx

Authorization successful.

Default credentials saved to: ~/.clasprc.json (/Users/xxxxx/.clasprc.json).

```

# ファイル作成

```
$ clasp create projectName
? Create which script? 
  standalone 
  docs 
❯ sheets 
  slides 
  forms 
  webapp 
  api 

```

そしたら怒られた。

```

Created new Google Sheet: https://drive.google.com/open?id=xxxxx
User has not enabled the Apps Script API. Enable it by visiting https://script.google.com/home/usersettings then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.

```


どうやら別途権限が必要らしい。

指定されたURL ( https://script.google.com/home/usersettings )を見てみると確かにオフになってたので、オンに変更

![スクリーンショット 2020-04-22 18.49.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/d9e97a80-d53a-b0a3-3256-d92f6171eb81.png)

再度チャレンジ

```
$ clasp create projectName
? Create which script? sheets
  standalone 
  docs 
❯ sheets 
  slides 
  forms 
  webapp 
  api 

Created new Google Sheet: https://drive.google.com/open?id=xxxxxx
Created new Google Sheets Add-on script: https://script.google.com/d/xxxxx/edit
Warning: files in subfolder are not accounted for unless you set a '.claspignore' file.
Cloned 1 file.
└─ appsscript.json
```

とりあえず作成成功。
作成されたGoogle SheetとGoogle Sheet Add-onのURLにアクセスしてもちゃんとアクセスできた。


とりあえず、spreadsheetのA１セルをカウントアップするプログラムを書いてみる。


```javascript:index.js

global.updateA1Cell = () => {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet()
  const sheet = spreadsheet.getSheets()[0];
  const cell = sheet.getRange('A1');
  let count = parseInt(cell.getValue());
  count++;
  console.log(count);
  cell.setValue(count);

}

```


GASのサーバーへ送信する。上書きする？とだけ聞かれた

```
clasp push
? Manifest file has been updated. Do you want to push and overwrite? Yes
└─ appsscript.json
└─ index.js
Pushed 2 files.
```

ファイルがアップロードされてGASのページでも見れる

![スクリーンショット 2020-04-22 19.30.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/3cc6ece4-5830-3812-4b63-b173eb4d2ece.png)

実行ボタンを押すと認証求められたのでポチポチと対応。
![スクリーンショット 2020-04-22 19.28.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/a6895d6e-3dd6-b317-9a02-176421b93c11.png)

カウントできた！

![スクリーンショット 2020-04-22 19.36.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/75544d4b-2e84-9ddd-3d20-7e69ce99fd61.png)


ちなみに、typescriptで書きたいなーと思ってやってみたら、コンパイラが自動で入って`clasp push`したときに変換してくれるっぽい。すごい

![スクリーンショット 2020-04-22 19.35.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/f67f61a0-9939-9267-4fec-56d405a4c3ce.png)



## 実行もGASを開かずに行う

実行もclaspからできるけど、そのためにがGCPのプロジェクト作ってoauthの認証して〜で急に難しくなる

まず、GCPのプロジェクトを作る必要がある
https://console.cloud.google.com/projectcreate?

![スクリーンショット 2020-04-22 19.47.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/d09b2c6d-cbd2-7240-0d8b-db0555bc32d6.png)

そして、OAuth同意画面を追加して、
https://console.cloud.google.com/apis/credentials?

![スクリーンショット_2020-04-22_19_47_38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/351d85cb-2d95-2cb4-f2e4-cfda0eed16f2.png)


認証情報を作成ボタンから、OAuthのキーを作成


![スクリーンショット 2020-04-22 19.48.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/97edc9b0-ef3c-8344-7823-729c823dcc97.png)


![スクリーンショット 2020-04-22 19.48.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/b0c2b6fe-d8eb-e0b0-4ca5-cefdcafdfdea.png)


![スクリーンショット_2020-04-22_19_49_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/46710be3-ce90-2e43-77a5-d0155d668cfc.png)


作成が完了したら、右側のDLボタンからファイルをダウンロードして、そのファイルを指定して再ログインする

![スクリーンショット 2020-04-22 19.49.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/ceceda4e-306d-a1af-ec24-aae6b03559e1.png)

```
$ clasp login --creds client_secret_xxxxxxx.apps.googleusercontent.com.json 
Logging in locally...

Authorizing with the following scopes:
https://www.googleapis.com/auth/script.webapp.deploy

  NOTE: The full list of scopes your project may need can be found at script.google.com under:
  File > Project Properties > Scopes
  
Using credentials located here:
https://console.developers.google.com/apis/credentials?project=xxxxxx

🔑 Authorize clasp by visiting this url:
https://accounts.google.com/o/oauth2/v2/auth?xxxxxxx

Authorization successful.

Local credentials saved to: ./.clasprc.json.
*Be sure to never commit this file!* It's basically a password.
Open this link: https://script.google.com/d/xxxxxxxx/edit

Go to *Resource > Cloud Platform Project...* and copy your projectId
(including "project-id-")

? What is your GCP projectId? body-control-gas

```

途中でGCPのプロジェクトIDを聞かれるので、ダッシュボードで確認して答えたら完了。
https://console.cloud.google.com/home/dashboard

appsscript.jsonにアクセス権の情報を入力。

```json:appsscript.json

{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "executionApi": {                    //ここからの3行を追加
    "access": "ANYONE"
  },
}

```

色々情報が変わってるのでpushしてから実行

```
$ clasp push
? Manifest file has been updated. Do you want to push and overwrite? Yes
└─ appsscript.json
└─ src/index.ts
Pushed 2 files.

$ clasp run updateA1Cell
Running in dev mode.
Error: Permission denied. Be sure that you have:
- Added the necessary scopes needed for the API.
- Enabled the Apps Script API.
- Enable required APIs for project.
$ 

```

あれ、怒られた

GAS側で、GCPのプロジェクトを紐付ける必要があるらしい。

GASのCloudPlatformプロジェクトを選択して
![スクリーンショット 2020-04-22 20.00.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/5b3bbfd0-5ce7-cae1-bb52-6f8731fabfb8.png)

プロジェクトIDを入力。
![スクリーンショット 2020-04-22 20.00.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/fdedac67-bc4e-4759-1b11-f94470afdfac.png)



そして実行！

```
$ clasp run updateA1Cell
Running in dev mode.
Exception: ScriptError Exception: You do not have permission to call SpreadsheetApp.getActiveSpreadsheet. Required permissions: (https://www.googleapis.com/auth/spreadsheets.currentonly || https://www.googleapis.com/auth/spreadsheets) [ { function: 'updateA1Cell', lineNumber: 3 } ]
```

今度は実行できた！が、途中でエラー

どうやら実行するための権限と、spreadsheetにアクセスするための権限は別の模様。

appsscript.jsonにスコープを記載

```json:appsscript.json
{
  "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8",
  "executionApi": {
    "access": "ANYONE"
  },
  "oauthScopes": [                                         //ここのスコープを追加
    "https://www.googleapis.com/auth/spreadsheets.currentonly",
    "https://www.googleapis.com/auth/spreadsheets"
  ]
}
```

認証を取り直すのでログインし直して

```
clasp login --creds client_secret_xxxxxxx.apps.googleusercontent.com.json 
```

実行！

```
$ clasp login 

$ clasp run updateA1Cell
Running in dev mode.
No response.
```

できた！

![スクリーンショット 2020-04-22 20.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227015/fbb2f8c1-ff34-cc39-39af-2a6905c4c5b5.png)