GASを使ってGoogleフォームの回答内容をプリザンターに登録してみる。

本記事は [Pleasanter(プリザンター) Advent Calendar 2020](https://qiita.com/advent-calendar/2020/pleasanter) 七日目の記事です。

## はじめに
今回の記事では、問い合わせフォームやアンケートなどでよく使われているGoogleフォームとプリザンターの連携について紹介します。

具体的にはGoogle Apps Script(以下、GAS)でプリザンターのAPIを叩いてフォームに入力された内容をプリザンターに登録します。
GASでAPIを叩くのはかなり容易ではあるのですが、フォームの内容を特定の項目に登録するには少々コツが必要でした。
通知メールのように回答内容をベタなテキストで送信するだけであれば簡単なのですが。

今回はプリザンターのAPIを使用しますので、Pleasanter.netのフリープラン、ライトプランではお試し頂けません。
お試し環境を持っていない場合は、デモサイトをご利用ください。メールアドレスを登録するだけですぐにお使いいただけます。
[プリザンターのデモサイト](https://pleasanter.azurewebsites.net/users/login)

もちろん、OSS版をお使いいただいている方はそちらでお試しください。
[プリザンターのダウンロード](https://pleasanter.org/)

今回のポイントをざっくり言うと
・Googleフォームを作る
・プリザンターにテーブルを作る
・GASでAPIを叩く
・三密を避ける

## Googleフォームを作る

[Googleフォーム](https://www.google.com/intl/ja_jp/forms/about/)
![スクリーンショット 2020-12-07 16.54.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/ec95acc3-9bc1-9953-9ea8-621d12183286.png)

とりあえず、簡単に「お名前」「メールアドレス」「この記事の内容は？」「ご意見」の4項目を作ってみます。


## プリザンターにテーブルを作る
まずは記録テーブルを作りましょう。とりあえず「Google Form連携」という名前にしておきます。
項目は以下の通りです。

![スクリーンショット 2020-12-07 16.25.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/e1329415-23f2-8d00-b173-e5ba76c85bac.png)

|項目名称|種別|
|:---|:---|
|タイトル|Title|
|お名前|DescriptionA|
|メールアドレス|DescriptionB|
|記事の評価|DescriptionC|
|ご意見|DescriptionD|

![スクリーンショット 2020-12-07 16.26.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/b43ba5c9-0de1-daab-8a68-26aeab500e35.png)


ついでに、APIキーを発行し、手書きでメモしておいてください。
[ユーザーマニュアル：APIキーの作成](https://pleasanter.net/fs/publishes/422358)

## GASでAPIを叩く
プリザンターでテーブルを作ったらGoogleフォームの画面に戻ります。
今回使うフォームを開いたら、右上にあるだんご３兄弟(串無し)みたいなアイコンをクリックして「スクリプトエディタ」をクリックしてください。

![スクリーンショット 2020-12-07 16.57.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/819ca530-abc7-efa3-6c40-77aa839d8479.png)


まず、APIを叩くスクリプトを書く前に、フォームの回答をプリザンターの指定した項目に登録するために、フォームに設置したコントロールのIDを取得する必要があります。

以下のスクリプトをコピペし、実行してください。

※以下のサイトに掲載されているコードを使わせて頂きました。ありがとうございます！
[Pre-Practice Blog：Google Formの質問項目を取得する](https://www.pre-practice.net/2017/11/google-form.html)

```
function get_items() {
  var form = FormApp.getActiveForm();
  var items = form.getItems();
  Logger.log("【items.length】" + items.length);
  for (var i = 0; i < items.length; i++) {
    Logger.log("【getHelpText()】" + items[i].getHelpText());
    Logger.log("【getId()】" + items[i].getId());
    Logger.log("【getIndex()】" + items[i].getIndex());
    Logger.log("【getTitle()】" + items[i].getTitle());
    Logger.log("【getType()】" + items[i].getType());
  }
}
```


実行後、「表示」→「ログ」で以下のログが表示されますので、それぞれのIDを手書きでメモっておいてください。

![スクリーンショット 2020-12-07 17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/b3bd3bc0-2307-082a-1539-c378d3f387a4.png)



今回プリザンターに作ったテーブルは、全てDescription(説明)項目になりますので、APIのリクエストは以下のような記述となります。

```
{
"ApiVersion": 1.1,
"ApiKey": "XXXXXXXXXX...",
"Title": "2020/12/7：Google Form連携!!",
"DescriptionHash": {
    "DescriptionA": "お名前",
    "DescriptionB": "メールアドレス",
    "DescriptionC": "記事の評価"
    "DescriptionC": "ご意見"
}
}
```

実際的にはそれぞれDescription項目に登録する値は、GoogleフォームのコントロールのIDで値を取得して代入することになりますが、IDなどはあまりコードに直接記述したくはないので、APIキーなどと合わせてプロパティとして管理することにします。
「ファイル」→「プロジェクトのプロパティ」→「スクリプトのプロパティ」に以下のように登録します。


![スクリーンショット 2020-12-07 16.2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/2c26988a-88f3-a919-82c7-52f1f64af009.png)

[ユーザーマニュアル：API機能：レコード作成](https://pleasanter.net/fs/publishes/428092/edit)

|プロパティ|値|
|:---|:---|
|API_KEY|プリザンターで発行したAPIキー|
|API_URL|リクエストを投げるURL|
|COLUMN|Json形式のリクエスト|

COLUMNは、以下のようにVALUEには、先程調べたIDをそれぞれ指定してください。

```
{"DescriptionA": "xxIDxx","DescriptionB": "xxIDxx","DescriptionC": "xxIDxx": "DescriptionC": "xxIDxx"}
```

実際に値を取得して、APIを叩くスクリプトは以下の通りです。

```
function SendPleasanter(e) {

    let value = SetValue(e);
  
    function SetValue(e){
        let value = {};
        let columns = JSON.parse(PropertiesService.getScriptProperties().getProperty('COLUMN'));
  
        const form = FormApp.getActiveForm();
        const items = form.getItems();

        const itemResponses = e.response.getItemResponses();
        for (let i = 0; i < itemResponses.length; i++) {
            let itemResponse = itemResponses[i];
            let id = items[i].getId();
            let answer = itemResponse.getResponse();
    
            for(let column_name in columns){
                let targetId = columns[column_name];

                if(targetId == id){
                    value[column_name] = answer;
            }
        }
    }
    return value;
    }

    let date = new Date();
    let year = date.getFullYear();
    let month = date.getMonth() + 1;
    let day = date.getDate();
    let title = year + '/' + month + '/' + day + '：' + 'Google Form連携!!';
  
    var data = {
        'ApiVersion': 1.1,
        'ApiKey': PropertiesService.getScriptProperties().getProperty('API_KEY'),
        'Title': title,
        'DescriptionHash': value,
    };
  
    const api_url = PropertiesService.getScriptProperties().getProperty('API_URL');

    var options = {
        'method': 'post',
        'contentType': 'application/json',
        'payload': JSON.stringify(data)
    };
  
    var response = UrlFetchApp.fetch(api_url, options);
    Logger.log(api_url, options);
}
```

次はGoogleフォームで「送信」が押された時にこのスクリプトが実行されるように、トリガーの設定を行います。
「編集」→「現在のプロジェクトのトリガー」で、画面右下の「トリガーを追加」をクリックし、以下のように設定します。

![スクリーンショット 2020-12-07 18.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/3f3d77f7-286e-830e-6a9c-9e0d5fe2f68f.png)

これで準備はきっと大丈夫です。信じる心こそ大事。

## 実際に送ってみよう
![スクリーンショット 2020-12-07 16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/4699d23d-709d-5a9e-67ed-f18566061cab.png)

送信！

![スクリーンショット 2020-12-07 16.33.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/e8b77607-45c1-cccb-c257-1a5b235b087c.png)

登録されました！

コードの最後に記述してあるログの出力は、実行後にダッシュボードから確認出来ますので動作を確認する際に使うと便利です。
![スクリーンショット 2020-12-07 16.38.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537390/6ccb3c7d-6bca-8e8c-5297-17ae6e22f472.png)

## おわりに
細かい部分はだいぶ端折ったのですが、随分と長い記事になってしまいました。最後までお読み下さりありがとうございます。
今回は全てDescriptionを使っていますが、他の種類の項目を使う場合には、項目ごとにプロパティを分けてあげると良いかもしれません。
というか、そもそも私はエンジニアではないので、もっと効率的なやり方が沢山あると思います。
とりあえずは、いろいろなサイトを参考にさせてもらいつつ悪戦苦闘しながら、何とか思ったように動いてくれて一安心です。
参考にさせて頂いたサイトの皆さん本当にありがとうございました。

GAS、結構楽しいですね。Analyticsとの連携とか誰かやってくれないかなあ…ﾁﾗｯ