Simple is Best

GASを使っていい感じの応募フォームを作った話


この記事はGoogle Apps Script Advent Calendar 201816日目の記事です。

ちょうど去年の今頃に、ある団体でオリジナルトレーナーを作ろうという話が持ち上がりました。

団体規模は3桁、日本各地にいるという状態だったのでどのような流れでトレーナーを届けるか色々思案しました。

そのときにちょうどGASというものを知ったので、Google FormとSpreadSheetsとGASを使って注文フォームを作りました。

その時のコードを知見として紹介できたらなと思います。

また、記事を書くにあたって現代の文法にリメイク(リファクタリング?)しました。

全体の流れ

当時は以下のような流れで注文者のもとにトレーナーを届けていました。

Process

今回は主に赤丸の部分について説明していきます。

環境構築

なるべく今風に書くにあたって、ES6以上の構文を使ってローカルで組めるようにしました。

ローカルでGASを組む

ローカルでGASを組みには、claspというGoogle製のツールを使います。

claspについては7日目のmatsuoshi氏や、9日目のtakanakahiko氏が記事として取り上げていらっしゃるので、詳細は割愛させていただきます。

ES6以上の構文でGASを組む

両氏ともTypeScriptを用いて組まれていらっしゃるのですが、私はTypeScriptを書いたことがないのでBabelを利用してJavaScriptで書いています。

結構ゴリ押しなのですが、まずはBabelをインストールして(Babel7から名前が babel- から @babel/ に変わってます。)

1
yarn add -D @babel/core @babel/cli

PresetとPluginを入れます。

1
yarn add -D @babel/preset-env babel-plugin-transform-member-expression-literals babel-plugin-transform-property-literals

PresetとPluginはこちらを参考にしました。(何故か配布されているやつをインストールしても使えなかった…)

あとは .babelrc に記述して

1
2
3
4
{
"presets": ["@babel/preset-env"],
"plugins": ["transform-property-literals", "transform-member-expression-literals"]
}

npm scriptsを設定すれば完了です。

1
2
3
"scripts": {
"build": "npx babel src/*.js --out-dir build"
}

この設定をしておけば、 npm run build をした後 ./dist 下で clasp push をすればOKです。

一つ注意点ですが、 clasp push をするディレクトリに appsscript.json を置かなくてはいけません。(ここでちょっとハマった)

Formを準備する

今回必要な情報は

  • メールアドレス
  • 名前
  • フリガナ
  • 郵便番号
  • 住所
  • トレーナーのサイズ

です。

Formはただ質問を準備するだけなので、特に説明はしません。

今回は以下のように準備しました。

Form 1

Form 2

郵便番号は正規表現を用いてフォーマットを固定しています。([0-9]{3}-[\d]{4})

氏名やフリガナが姓と名で分かれているのは、入力者による入力フォーマットの差を無くすためです。

実際に書いたコード

以下のコードはES6以降の構文を用いたものです。

FormからのResponseが保存されているシートの名前は Original、整形してリスト化したものを保存するシートの名前が Roster です。

原則として Original のデータは触りません。何か変更があった場合は必ず Roster のデータをいじります。(何か起こったときに修復できるように)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
const reservation = () => {

// FormからのResponseが保存されるSheetを取得
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Original");
reservationWithIndex(sheet.getLastRow(), sheet);

}

const reservationWithIndex = (index, sheet) => {

const info = sheet.getRange(index, 1, 1, sheet.getLastColumn()).getValues()[0];

const name = `${info[2]} ${info[3]}`; // 名前
const ruby = `${info[4]} ${info[5]}`; // ふりがな
const addressCode = info[6]; // 郵便番号
const address = info[7] + info[8]; // 住所
const size = info[9]; // サイズ

const message = "メール本文";

try {

// MailApp.sendEmail(送信先メールアドレス, メールタイトル, メール本文)
MailApp.sendEmail(info[1],"{メールタイトル}", message);

} catch(e) {

// エラーが出たときは自分のメールにエラー内容を送る
MailApp.sendEmail("hogehoge@blog.oldbigbuddha.net", e.message, e.message);

}

// 別シートに情報を写す関数(自作)
makeList(info);

}

// サイズの値段を計算
const calcPrice = size => {

if ( size === "XS" ) return "4,100"; // XSのとき
else if ( size === "XXL" ) return "5,000"; // S,M,Lのとき
else return "4,500"; // XLのとき

}

const makeList = info => {

// 書き込み先のSheetを取得
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Roster");

const name = `${info[2]} ${info[3]}`; // 氏名
const ruby = `${info[4]} ${info[5]}`; // ふりがな
const addressCode = info[6]; // 郵便番号
const address = info[7] + info[8]; // 住所
const size = info[9]; // サイズ

var info = [ [
info[0], // メールアドレス
size,
name,
ruby,
addressCode,
address
] ];

// 最終行に新規注文者を追加
sheet.getRange(sheet.getLastRow() + 1, 1, 1, 6).setValues(info);

}

reservation の実行TriggerをFormからResponseが来たときに設定しておきます。getLastRow() の値がその得た情報のIndexを示しています。

reservationWithIndexreservation をわけることによって、何か情報を修正したりメールを再送信する必要ができたときに即席のfix関数を用意できるようにしています。

締め

コード各所にコメントを入れているので、特にコードに関する説明はしませんでした。

もしここの処理なにやってるのかわからんとか、ここはこう書いたほうがいいよっていうのがありましたら @OJI_1941 までお願いします。DMは閉じていますのでリプライかメンションでお願いします。

ローカルで組めたり、今どきの構文で書けたりとGASもなかなか進化しましたね。最近はG Suite DeveloperHubが追加されたりとGASの環境が整いつつありますので、ぜひ皆さんご活用されてみてはと思います。(カレンダー経由で来た方はすでにフル活用されていることと思いますがw)

ありがとうございました。


URLをクリップボードにコピーしました。

GitHub Trending をRSS配信する