AppSheet Automation構築におけるAppSheet APIの利用

# AppSheetって何？

今回、業務の中で触る機会がありまして、せっかくなのでまとめてみました。

https://cloud.google.com/appsheet#key-features

https://www.yoshidumi.co.jp/collaboration-lab/appsheet

**ノーコード**、というワードがいくつかの記事で確認できます。
ゴリゴリのコーディングをせずともアプリをクラウド上に構築できる、といった言われ方をしている印象です。

## AppSheet Automation
メインは**Automationです。**
自動化を構築するときに、役立つ機能です。

他にもいくつか機能はありますが、この記事ではふれません！

#### トリガーと構築可能な処理

https://gihyo.jp/article/2022/09/appsheet-automation

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/73028b71-7ccf-72f3-5850-87ee905f0e91.png)

上記画像の説明にあるものを、
ブラウザでAutomationを構築する際の画面は以下の通りです。

#### EVENTの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/f5bfc37f-b3e8-325a-e342-ea4ff1daa7e9.png)
#### PROCESSの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/9dc9a0e1-5db6-c577-5b51-7b4cbab33b30.png)

選択可能なEVENTは多くないですが、PROCESSの方は色々ある印象です。
**上手に組み合わせれば、様々な作業を自動化できそうです。**
chatGPTなどと組み合わせることで実践的な成果物ができるだろうと感じました。

## この記事でするAutomationに関する話
AutomationのEVENTについて、スプレッドシートのデータ追加を設定していました。
GASを使ってデータ追加処理を行い、Automationが実行されるはずでしたが、思ったようにならず躓きました。その解決の手立てを記しています。

#### 構築を予定していた構成
今回の作成物について話をします。

手順は以下の通りです。

1. **データベースとして利用するスプレッドシートにて、「アドオンを取得」をクリック**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/a50d1f59-6f90-245a-4ac5-fe5fd3bdce7a.png)
1. **マーケットプレイスで、`AppSheet Events`を選択してインストール**
（私はインストール済なので、アンインストールと表示）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/c16bd233-4c17-010f-e73d-d84c556342be.png)
1. **AppSheetのイベントとして利用するための設定**
対象シート名の左にチェックマークが表示されれば設定完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/08b80c37-72be-39be-93ea-ef3db8229e1c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/b5736644-db6c-8eab-c212-74a96a4af5c2.png)
1. **AppSheetのアプリ作成**
シートにカラムを記述しておきます。何も記述していないと、「アプリを作成」が非活性の状態になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/18c13a76-1cb1-de6a-1e8c-7f10e04958d1.png)
1. **Automation作成**
スプレッドシートのデータ追加をトリガーに起動する構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/6011ce67-8c14-86b3-72a3-75c444a747bb.png)
1. **GAS作成**
スプレッドシートにデータ追加するための処理を実装
```javascript:main.gas
function myFunction() {
  // スプレッドシートとシートを取得
  var sheetName = 'sheet1'; // ここにシート名を入力
  var spreadsheet = SpreadsheetApp.openById(SPREADSHEET_ID);
  var sheet = spreadsheet.getSheetByName(sheetName);

  // 現在時刻を取得
  const formattedDate = getCurrentTime();
  
  // 最終行を取得して、次行にデータを追加
  var lastRow = sheet.getLastRow();
  // 追加するデータを定義
  var newData = [formattedDate, `データ${lastRow+1}`];
  sheet.getRange(lastRow + 1, 1, 1, newData.length).setValues([newData]);
}

function getCurrentTime(){
  // 現在時刻を取得
  const now = new Date();
  // 時間を特定の形式でフォーマット
  const formattedDate = Utilities.formatDate(now, Session.getScriptTimeZone(), 'yyyyMMddHHmmss');
  return formattedDate;
}
```
環境変数読み込み用のファイルを別途用意しています。
環境変数の設定・実装は[こちら](https://www.kamo-it.org/blog/gas-env-property/)を参考にしました。
```javascript:setting.gas
const SPREADSHEET_ID = PropertiesService.getScriptProperties().getProperty("SPREADSHEET_ID")
}
```

1. **GASを実行して、Automationga起動することを確認**

## スプレッドシートのデータ追加が検知されない？
GASのコード内からスプレッドシートに対するデータ追加処理を実行しました。
スプレッドシートにデータは追加されました。
**しかし、メールが届きません。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/631a7b50-18f6-1cf1-f195-1e6c785df7b5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/8b39597b-31e4-689a-9644-546212f7c8b0.png)

設定不足か確認するため、手動でスプレッドシートを更新してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/d39e8025-f3e9-294e-81d1-6a6a5fdf7810.png)

すると、**Automationが動きました。**（メールが届いた）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/9d786332-99cf-e16e-57e7-44e3d9e780a5.png)

AppSheetのドキュメントを確認してみました。

## AppSheetのドキュメント参照
https://support.google.com/appsheet/answer/11445188?hl=en&ref_topic=11998887&sjid=3100337950870987100-AP

> Data is added, modified, or deleted through the app. For example, the status of a service ticket is changed through the app. See Configure a data change event.
> データがアプリを通じて追加、変更、または削除されるときに発生します。例えば、サービスチケットのステータスがアプリを通じて変更される場合です。詳細は「データ変更イベントの設定」を参照してください。

> Events generated due to an app action or as a result of an app data change from an AppSheet API call will fire without any external configuration.
> AppSheet API呼び出しによるアプリアクションまたはアプリデータ変更の結果として生成されるイベントは、外部設定なしで発火します。

「XXXの場合に、Automationが起動しない」とは明確に記載されていないですが、
**アプリまたはAPIを通じて、追加・変更・削除の指示を通じて、Automationが起動する**
と受け取りました。

## AppSheetAPIの利用
アプリの中からデータを更新する予定は無く、プログラミング言語問わず実装可能な、AppSheetAPIを利用します。今回はデータ追加に関するAPIを利用します。

https://support.google.com/appsheet/answer/10104797?hl=en

#### AppsheetのAccessKey作成
APIを利用するために、アプリの設定画面から、アクセスキーの発行が必要です。
`Create Application Access Key`をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/2b171ae4-4e6a-8972-653b-bbff443805f3.png)
`Show Access Key`をクリックして、アクセスキーの値を確認し、GASのスクリプトプロパティに変数名`ACCESS_KEY`の値に設定します。
（セキュリティの都合上、クリック後の画像は載せていません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/345414/3bdf9648-8ad7-c4bd-23b4-d4e1ea6e7f42.png)

#### GASの実装修正
AppSheet APIを用いて、POSTリクエストできるように、コードを修正します。
必要なデータの設定とHTTPリクエストに関する処理以外は特にありません。
また、スクリプトプロパティから以下の値を読み込みます。
- `ACCESS_KEY`：直前の手順でコピーしたアクセスキーの値
- `APP_ID`：AppSheetのアプリID（アクセスキーの説明画像で、赤線で隠している部分の値）
- `TABLE_NAME`：スプレッドシートのシート名
```javascript:main.gas
  const formattedDate = getCurrentTime();
  const rows = [{
      "タイムスタンプ": formattedDate,
      "名前": "Sample"
    }];

  // https://support.google.com/appsheet/answer/10104797?hl=en
  var url = `https://api.appsheet.com/api/v2/apps/${APP_ID}/tables/${TABLE_NAME}/Action?applicationAccessKey=${ACCESS_KEY}`;
  var payload = {
    "Action": "Add",
    "Properties": {
      "Locale": "ja-JP",
    },
    "Rows": rows
  };

  var options = {
    'method': 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(payload)
  };
  var response = UrlFetchApp.fetch(url, options);
  console.log(response.getResponseCode())
```
AppSheetに関して、環境変数をいくつか追加しています。
```javascript:setting.gas
const SPREADSHEET_ID = PropertiesService.getScriptProperties().getProperty("SPREADSHEET_ID")
const APP_ID = PropertiesService.getScriptProperties().getProperty("APP_ID")
const TABLE_NAME = PropertiesService.getScriptProperties().getProperty("TABLE_NAME")
const ACCESS_KEY = PropertiesService.getScriptProperties().getProperty("ACCESS_KEY")
```

今回はデータ追加がメインでしたが、
データベースでも存在する更新・削除・取得のAPIも用意されていました。

詳細は以下のリンクをご確認ください。

https://support.google.com/appsheet/topic/10105767?hl=ja&ref_topic=10101404&sjid=2713060602064805976-AP


## AppSheet APIを使ってみて

EVENTがもう少し多様にあったらいいなと感じました。

また、**レスポンススピードが求められるもの、データ量が多くなるものには向いていない、と感じました。**
(2件のデータしかないスプレッドシートから、1件のデータを取得するのに、3秒かかります。もっと件数が増えればもう少し時間がかかるはずです。)

否定的な意見を述べましたが、組み合わせ方次第で色々できるものと感じました。
今後もう少し本格的なものを作る機会があればやってみたいと思います。