GASをグルー言語的に使った話

# はじめに

この記事ではGASを[グルー言語](https://ja.wikipedia.org/wiki/%E3%82%B0%E3%83%AB%E3%83%BC%E8%A8%80%E8%AA%9E)的に使った例を紹介します。皆さんご存知の通りにGASは言語ではありませんが、二つのサービスをつなぐ用途でも使ってみたよ！という内容になっております。こんな内容でトリを汚していいのだろうか、、、とも思ったのですが、GAS LOVEなもんで勢いで書いてしまいました。

# それで何をしたの？

最近、車のリースをしている会社さんのサイト作りのお手伝いをしているのですが、既存のサイトと新規作成のサイトをつなぐ為にGASが動いています。これは二つの案件をこなすうちに自然にそういう形になったので、それぞれについて簡単に説明します。ちなみにGSUITEアカウントではなく、無料のGoogleアカウントで実現しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29999/a9973500-6a6a-89c5-b6f1-c8d85673809b.png)

# 案件1　Word Pressからのメールを整形してPDFにする

私が案件を受けた時は、Word Pressのサイトに審査申し込みフォームがありました。お客さんはまずそこから自分の情報を入力して、それを受けたクライアントさんが審査する流れになっていました。この時、フォームの内容がメールでクライアントさんに届くのですが、項目が並んでいるだけで社内資料として残せる体裁ではありませんでした。そこで、このメールから体裁を整えたPDFを作ってメールして欲しいという要望を頂きました。フォーム入力された情報以外にも、そこから保険会社に送る見積依頼書なども自動生成して欲しいとの事でした。そこで対応したのが次のようなシステムです。なお、[GASでサービスを作った話](https://qiita.com/plsplsme/items/fd3fc0752701c3dd5635)でこれについて少し書いてあります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29999/426426e6-ff1f-ac71-4197-e80b4930314c.png)

まずクライアントさんのGmailにWord Pressからのメールが届きます。これをGASで見に行きたいのですが、GASではプログラムをホストしているアカウントのGmailしか見に行けません。クライアントさんのアカウントを使うわけにはいかないので、必要なメールだけ私のアカウント(Dev Account)にForwardする設定をGmailでしました。実際に見に行くメールは私のアカウントになります。GASの処理は次のような感じです。

1. 転送されたメールを正規表現でparseしてjson形式にする
2. HTMLで作っておいた雛型の中身を上記のjsonで置き換えてPDFに変換
3. 作成されたPDFとオリジナルのメールに添付されていたファイルをメール送信
4. 上記ファイルをGoogle Driveに保存

Google Driveの特定フォルダを本アプリように利用しており、クライアントさんが中身を見れるようにシェアしました。

# 案件２　リース業務全般を管理するサイト作成

さて、案件１は大きな問題もなく一年ほど動いていました。その後、リースに関連する一通りの業務をウェブサイトに集約したいという要望を受け、Node + Firebaseの構成で作成する事になりました（みんな大好きServerlessではありません)。この新規サイトでもWord Pressからのフォームの内容を見たいとの事で、次のような構成にしました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29999/206491dc-7746-9b36-b898-994e2676e8df.png)

図のようにGoogle Functionを叩く処理をGASに追加しました。GASからのHTTPに興味があれば[Google cloud schedulerを試した](https://qiita.com/plsplsme/items/69f1e65bca7660498068)を参照してください。

GASはフォームの内容とGoogle Driveに保存したファイルの[ファイルID](https://developers.google.com/apps-script/reference/drive/file#getId())を一緒にしてjson形式でFunctionsに送信しています。Functionsはこのデータを元にFirestoreへドキュメントを追加します。

Express製の新規サイトの方では上記のドキュメントからフォームの情報を取り出して表示しています。なお、Google Driveに格納されているファイルは全て上記のファイルIDを利用してClous Storageにコピーしています。ExpressのサイトからはCloud Storageしか見に行かない事にしたかったので、この仕組みを入れました。これでGASが無事グルー言語(?)として動き出しましたね。めでたしめでたし、、、？

# でも、Word Pressいらなくね？

はいその通りですすいません。新規サイトの方に審査申し込みフォームを入れれば良いですね。その場合はGASをAPIサーバーにして次のような構成になると思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/29999/16b7f183-416e-09df-d9f6-19d1255a2f6e.png)

ただ、全体の工数を考えるとGASに手を加える方が早かったので、フォームの作り直しはやめました。一つ目の案件を受けていなければ、恐らく作り直したと思いますが。なお、GASでやっている作業をNodeで書く事も出来ますが、私はGASの方が手軽で好きです。

# Tips

せっかくなので、このシステム開発でのGASに関する学びをいくつか共有しておきます。

## 特定のデータからPDFを作るのはGoogle Slideの方が良い

本サービスではhtmlをPDFにしたのですが、画像ファイルを一緒に変換する事が出来ませんでした。またHTMLはPDFにした時に１ページでプリント出来るようにする調節が面倒です。PDFを作ってみないと確認出来ません。フォームのデザインの手間を減らす為に、Word PressのCSSをそのまま使いたくてHTMLにしたのですが、ちょっとこれは失敗でした。

別の案件ではGoogle Slideを使いました。Slideだと画像も使えるし、１ページに収まらない問題も解決します。
Slideには`${name}`のような感じにプレースホルダーを配置して、それを置き換えます。置き換えプログラムは次のような感じです。

```javascript
function modifySlide_(id, params) {
  var s = SlidesApp.openById(id);
  for (var key in params) {
    s.replaceAllText(key, params[key], true);
  }
  s.saveAndClose();
```

PDFの作成は次のように行いました。

```javascript
function convertSlideToPdf(slideId, folderId) {
  var blob = DriveApp.getFileById(slideId).getBlob();
  const folder = DriveApp.getFolderById(folderId);
  const pdf = folder.createFile(blob);
  return pdf.getId();
}
```

簡単ですね。私がGAS LOVEな理由はここです。別案件ではメンバーカードのようなものを作ったのですが、簡易的な名刺も作れるでしょうし、色々と利用出来ると思います。
※SlideをPDFにするのは@wf9a5m75さんもAdvent Calender Day21で[書かれて](https://qiita.com/wf9a5m75/items/a4973adc1bd4e44d03d8)いました。PDFの取り出し方はそちらの方が便利そうです。

## 既に処理したメールを確認するにはTAGを使うと良い

これは結構なボリュームなので[別の記事](https://qiita.com/plsplsme/items/c3c464fd81f711c808b6)にまとめました。

## ソースコードに書きたくない情報はProject Propertiesに書く

たとえばAPI KEYなどはProject PropertiesのScript Propertiesに入れます。ソースコードに書かなくて済みますし、開発用のアカウントではAPIを変えるなども出来ます。

またアプリで使うファイルをDriveに入れる時は、アプリ用ルートフォルダのIDをプロパティに入れておきます。例えばGoogle Driveでファイルを移動しようとすると、ルートディレクトリから一つ一つフォルダを辿って指定しないといけなくて面倒ですよね。GASでも同じように特定のディレクトリからrecursiveに辿っていく必要があります。

ただし、特定のフォルダをダイレクトに指定する唯一の方法としてフォルダIDです。従って、アプリ用のフォルダにアクセスする時は、アプリ用ルートフォルダをIDから引っ張ってきて、そこからrecursiveに辿るようにしています。このIDもアカウントによって違うので、Propertyに入れています。

ほかにもあった気がするので、思い出したら追記しようと思います、、、。