[[Clasp]]を使って、[[スプレッドシート]]をベースにしたシステムのベースを作ってみたメモ。 ## [[Clasp]]のインストール ```console npm install -g @google/clasp ``` [[Google Apps Script API]]を有効にする。 https://script.google.com/home/usersettings?pli=1 ## ログイン https://developers.google.com/apps-script/guides/clasp#login ```console clasp login ``` ホームディレクトリ配下に[[clasprc.json|.clasprc.json]]が作成される。 ## プロジェクト作成 https://github.com/google/clasp/blob/master/docs/typescript.md `clasp-google-spread-sheet-sample`という名前のリポジトリを作成し、プロジェクトを作成する。 ```console cd clasp-google-spread-sheet-sample npm init -y npm i -D @types/google-apps-script ``` ### [[tsconfig.json]]の作成 ドキュメントのサンプルをベースにいくつか設定を追加した[[tsconfig.json]]を作成する。 ```json { "compilerOptions": { "target": "ES2019", "lib": ["esnext"], "experimentalDecorators": true, "strict": true, "skipLibCheck": true } } ``` 変更点は以下 - [[strict]]を`true`にする - 実行前に拾えるエラーを拾うため - [[skipLibCheck]]を`true`にする - ライブラリの型定義に足を引っ張られないようにするため - [[target]]を[[ES2019]]にする - [[V8]]の場合は[[target]]を[[ES2019]]にすべきと [ドキュメントに記載がある](https://github.com/google/clasp/blob/master/docs/typescript.md#v8-engine-support) ため ### [[Clasp]]プロジェクト作成 [[Clasp]]の[[スプレッドシート]]プロジェクトを作成する。 ```console clasp create --type sheets ``` [[clasp.json|.clasp.json]]にシートやスクリプトとの紐づけ情報が記載される。`rootDir`だけ削除した。 ```json { "scriptId": "スクリプトのID", "parentId": [ "シートのID" ] } ``` 以下の関係にある。 - Created new Google Sheet: `https://drive.google.com/open?id=<シートのID>` - もしくは `https://docs.google.com/spreadsheets/d/<シートのID>/` - Sheets Add-on script: `https://script.google.com/d/<スクリプトのID>/edit` - もしくは `https://script.google.com/home/projects/<スクリプトのID>/settings` > [!question]- `rootDir`は指定しなくてもいいのか? > ドキュメントでは`rootDir`にプロジェクトの絶対パスが指定されていたが、以下の理由から削除した。 > - 指定しなくても挙動は変わらない (必要なファイルだけをデプロイしてくれる) > - 指定すると他の人が使えなくなる (パスが違うから) ### [[node_modules]]を無視する [[gitignore|.gitignore]]を追加する。 ```txt node_modules ``` ## スクリプト作成 `src/hello.ts`を作る。全体の構成。 ``` $ tree . -L 2  . ├──  appsscript.json ├──  node_modules │ └──  @types ├──  package-lock.json ├──  package.json ├──  src │ └──  hello.ts └──  tsconfig.json ``` そのままコピペ。 ```ts const greeter = (person: string) => { return `Hello, ${person}!`; }; function testGreeter() { const user = "Grant"; Logger.log(greeter(user)); } ``` ## デプロイ ```console clasp push ``` [[appsscript.json]]と`hello.ts`がアップロードされる。シートから確認する。 ![[Pasted image 20220713180908.png]] デプロイされていることが確認できる。 ![[Pasted image 20220713180954.png]] > [!hint]- [[TypeScript]]のバージョンについて > 4.7.4と最新のバージョンが使われていそう。これは[[Clasp]]の依存関係が`@4.x.y`になっているため。[公式ドキュメントに以下の記述があった](https://github.com/google/clasp/blob/master/docs/typescript.md#typescript-support)ので3系かと思ったが、古いのはドキュメントの方だったようだ...。 > > Currently, clasp supports [email protected]. If there is a feature in a newer TypeScript version that you'd like to support, or some experimental flag you'd like enabled, please open an issue. ## シートを使った処理を書く このままだとつまらないので[[スプレッドシート]]を利用した処理を書く。 <div class="link-card"> <div class="link-card-header"> <img src="https://www.gstatic.com/devrel-devsite/prod/vc168bdd3636a4d0c346e3f7ef8a8dc9473171e3b493766c11713b40799c9ad55/developers/images/favicon.png" class="link-card-site-icon"/> <span class="link-card-site-name">Google Developers</span> </div> <div class="link-card-body"> <div class="link-card-content"> <div> <p class="link-card-title"> Google スプレッドシートによる Apps Script の基礎 #2: スプレッドシート、スプレッドシート、範囲  |  Google Developers</p> </div> <div class="link-card-description"> Apps Script スプレッドシート サービスを使用して Google スプレッドシートでデータの読み取り、書き込み、操作を行う方法をご覧ください。 </div> </div> </div> <a href="https://developers.google.com/codelabs/apps-script-fundamentals-2#0"></a> </div> `A1`と`C1`を足した結果を`E1`に挿入する処理。 ![[Pasted image 20220713184327.png]] 薄いラッパーとして`src/sheets.ts`を作成。 ```ts const activeSpreadSheet = () => SpreadsheetApp.getActiveSpreadsheet(); export const メインSheet = () => activeSpreadSheet().getSheetByName("メイン")!; ``` そして`src/main.ts`。 ```ts import { メインSheet } from "./sheets"; function main() { const result = メインSheet().getRange("A1").getValue() + メインSheet().getRange("C1").getValue(); Logger.log(`結果: ${result}`); メインSheet().getRange("E1").setValue(result); } ``` `clasp push`してスクリプトを実行させようとすると、新たな権限を要求される。今回の変更でスプレッドシートを操作する処理が加わったため。YES。 実行するとエラーになる。 ``` ReferenceError: sheets_1 is not defined main @ src/main.gs:7 ``` ### [[ReferenceError]]の解消 [[📝Claspでデプロイしたスプレッドシートのスクリプトを実行するとReferenceError]] を参考に[[namespace]]を使って回避する。 `src/sheets.ts` ```ts namespace Sheet { const activeSpreadSheet = () => SpreadsheetApp.getActiveSpreadsheet(); export const メイン = () => activeSpreadSheet().getSheetByName("メイン")!; } ``` `src/main.ts` ```ts function main() { const result = Sheet.メイン().getRange("A1").getValue() + Sheet.メイン().getRange("C1").getValue(); Logger.log(`結果: ${result}`); Sheet.メイン().getRange("E1").setValue(result); } ``` 実行すると動いた。 ## 本番環境との切り替え 既に本番環境で利用している[[スプレッドシート]]がある場合、そこから情報を取得する。 #todo あとは設定ファイルとか