Google Formは基本的に複数のデータを送信することは出来ません。ですので、例えば、旅行申込書というフォームを作ったとしても、送れるデータは1名分(1レコード)のみです。擬似的に複数の人間分テキストボックスを用意するということは可能と言えば可能ですが、非常に煩雑なものになり、また、それを分解して複数レコードとして送り出す為に、余計なコードを書かなければなりません。HTML Serviceを利用したフォームでもそのままでは同様の事が言えます。

しかし、HTML Servicesの場合、JavaScriptとライブラリを駆使して、複数レコードを送信するようなフォームを作る事が可能です。投稿するレコード数に制限をつけず、また画面遷移が出来ないHTML Servicesでは、ちょっとしたテクニックが必要になります。今回は、それに挑戦してみたいと思います。

※今回のフォームを超絶発展させたものが、備品貸出管理フォームのようなものになります。

図:lotnum単位で複数レコード同時登録します

使用するメソッド・クラス、準備するもの

ソースコード

GAS側コード

ウェブアプリケーションとして作成するので、doGet()でHTMLを表示させる。また、送信ボタンを押した時のコードを用意しておく。基本的には、HTML側からのデータを受け取って、スプレッドシートに一括書き込みをするのが主な仕事です。

  • ID列は単純に連番を取ってるレコードのIDです。
  • 対して、lotnumとは、複数送られてくる塊に対してのIDをつけています。つまり同じIDならばそれらは1度に送信された塊と判別することが可能です。
  • HTML側から送られてくる配列に、連番のuidとlotnumを加えた配列に作り変えてあげてます。
  • 最後に、スプレッドシートの一番最後の行に、appendRowのように一気に書き込みをしています。
  • このコードだけですと、複数名同時にアクセスされた場合、連番がおかしくなったり、書き込みがバッティングする可能性があるので、排他制御も同時に扱うようにすると良いでしょう。

HTML側コード

今回は、テーブルレイアウトの為に色々なCSSを組み込んでいます。主にUIを作るに当って、以下のような仕組みを施してあります。

  1. 入力画面そのものは、jQuery Dialogを使用しています。
  2. 一覧表示部分はテーブルとし、そこに新規レコードが挿入されていきます。
  3. 一定の数以上になると自動でスクロールバーが出て、テーブル内でスクロールするようにしています。
  4. データの更新時のダイアログだけ、削除ボタンが表示されるようになっています。
  5. ダイアログ画面を綺麗に整形する為にCSS側で動的生成されたjQuery UIのコンポーネント用のCSSを設定しています。

  • 今回は、グリッドについては特別なライブラリを使用せずに、tableタグのみで実現しています(jQueryだけは使ってます)。
  • テーブルタグではありますが、ある程度の件数が追加されるとスクロールバーが出るようになっています。
  • 追加でデータを追加し、送信をするとスプレッドシートに複数レコードが一気に書き込まれます。
  • 複数データをもとに、例えば請求書のような複数レコードを要する書類を生成し、PDF化して送ることも可能です。
  • この手のフォームの全ての原型になるので、身に付けるとGASでフォームアプリケーションの幅が一気に広がりますよ。

実行結果

今回のアプリケーションは、Google Formではなくウェブアプリケーションとしてのフォームなので、最後に以下の手順で公開作業が必要です。

  1. スクリプトエディタの「公開」⇒「ウェブアプリケーションとして公開」をクリック
  2. プロジェクトバージョンはNewとする
  3. 次のユーザとしてアプリケーションを実行で、自分とすると、他人であっても自分の権限で書き込まれるので、スプレッドシートを自分のみにしても、書き込みが可能な状態にすることが出来ます。
  4. アプリケーションにアクセスできるユーザは基本は自分のドメイン内に限定しましょう。

図:こんな形で複数のレコードを送り込めます

図:登録用のダイアログが必要です。

ポイント

  • GAS側で書き込む処理はそれほど複雑ではありません。HTML側から配列の塊を受け取ったら、ちょっと加工してスプレッドシートの最終行にappendRowするかのように、改めて作成した配列データをドカっと書き込むといった具合です。
  • HTML側は少々複雑で、主な仕組みは空のテーブルと空の配列を用意し、データの追加削除をそれぞれに対して同時に行っています。データの書き込み時はその時点での配列データをGAS側に渡しています。
  • データ修正時は、trタグに設定してあるIDを元に配列データからダイアログ側に値を抽出して復元しています。また、データ削除はtrまるごと削除と配列からspliceさせています。
  • insertrecdeleterec、およびdialogcleargetdialogのそれぞれのメソッドが実作業を行う担当関数です。データの挿入・削除・終了時にダイアログのコントロール値をクリアする、ダイアログの値を収集するといった作業を行っています。
  • makedown関数に渡す引数によって、それが修正時なのか新規追加時なのかを判定させています。
  • jQuery UIのCSS等はそのままだと馬鹿でかい文字とかボタンの大きさになるので、それをスマートにするために、自分が用意したCSS内でコントロールのstyleを再定義させています。このへんは好みですね。

実行結果

動画:実際に複数データを送ってみた

Google Formで擬似的に複数レコード挿入

概要

メールで質問をいただきまして、Google Formでも擬似的に特定の条件の時に複数レコードを作れるのではないだろうか?ということで作ってみました。アルバイトのシフト表を登録するGoogle Formです。なんとか実現できないかなぁと思いついた手法がこれでした。利用シーンは限られるとは思いますが、こういった形であれば、複数データの擬似的な送信が実現します。

登録を行うと、1回の送信でスプレッドシートに複数登録され、その登録データを元にQuery関数でシフト表を組み上げるものとなっています。ただし、いくつかこれを実現する為に、トリッキーなテクニックを使っています。

  1. Query関数でのPivotではカラム名でのソートができないので、数字+文字列だとオカシナ並び順になる。これを防ぐ為に1桁の場合には頭に0をつけてあげるようにした。(1ならば01となるようにする)。
  2. Pivotの集計はA列のカウントにしておいた。本来は労働時間などを入れて集計が良いのかもしれない。
  3. 複数登録の為に出勤可否の項目は「選択式(グリッド)」を使っています。これが複数個登録される基準になります。
  4. 出勤の時だけ配列に加えて書き込み対象にしています。
  5. グリッドの選択肢を増やしたり、チェックボックスを使ったり。グリッドの場合ならば、その回答内容で条件分岐させて、時間を計算して値を配列に入れるといったような工夫ができれば、4、5個あっても対応可能。

図:こんな感じのグリッドパーツを使います。

ソースコード

  • 同時に登録がないとは思いますが、万が一もあるので排他処理を入れておくと良いでしょう(複数データ登録があるので)
  • 選択式グリッドの値はまとめて配列で送られてきます。[出勤,出勤,休暇,出勤….]といった具合に。
  • フォームの各種値、uid生成、選択式グリッドの日付と一致するように生成するdaycntを用意して、書き込み用配列を用意する。
  • データの書き込みはendrowを調べてまとめてガッツリ書き込みます。

使い方

フォームのソースコード内に書き込み先スプレッドシートのIDを入れてあげます。また、Formの送信時トリガーにシートへの書き込みをしてるsendFormsを登録してあげます。Form自身のスプレッドシート書き込み機能は利用しません。

これで送信を行うと、スプレッドシートに1回の送信で複数登録され、それを元にクロス集計シートでquery関数にてPivot化される仕組みになっています。

※忘れがちですが、Formのスクリプトエディタに入って、1度sendformsを実行して認証をしないと、スクリプトは動かないです。地味なハマりポイントです。

図:トリガーを設置する必要がある

図:1回の送信で複数登録される

図:Query関数のPivot化でシフト表が完成する

関連リンク

共有してみる: