見出し画像

#121 複数のフォームからの回答を統合する(2) 出力にフォーム名を追加

この記事は、以下の記事に対する更新です。

この記事に

一つ質問があるのですが、複数のフォームの回答を1つのシートにまとめる際に回答がどのフォームの回答かをスプレッドシートに書き込むことも可能でしょうか?

例えば「フォームNo.1」~「フォームNo.5」の回答を一つの「統合した回答」というスプレッドシートにまとめます。その際にスプレッドシートの1列目に「フォームNo.1」、2列目以降に回答を書き込むというようにしたいのです。

「#75 複数のフォームからの回答を統合する|ともかつのノート」へのコメント

というコメントが寄せられたので、少しプログラムに手を入れてみました。

変更後のプログラム

"use strict";                                       // 変数の宣言を強要する
const OUT_BOOK = '';                                // 統合先のシートがあるファイルの ID ※空欄なら、このファイル
const OUT_SHEET = '統合した回答';                     // 統合先のシートの名前

const FORM_NAME = true;                             // 先頭に回答元のフォーム名(タイトル)を挿入するか?
                                                    //  true  : フォーム名を挿入する 
                                                    //  false : フォーム名を挿入しない
const SHEET_NAME = true;                            // 先頭に回答元のシート名を挿入するか?
                                                    //  true  : シート名を挿入する 
                                                    //  false : シート名を挿入しない

function onFormSubmit(e) {
  let ss;                                           // 処理対象のファイル
  if (OUT_BOOK == '') {
    ss = SpreadsheetApp.getActiveSpreadsheet();     // このファイル
  }
  else {
    ss = SpreadsheetApp.openById(OUT_BOOK);         // 指定された別のファイル
  }

  /**
   * トリガーの引数 e に含まれている range から、回答が記録されているシートを得る
   *    https://developers.google.com/apps-script/guides/triggers/events?hl=ja
   *      ↓
   *    https://developers.google.com/apps-script/reference/spreadsheet/range?hl=ja#getSheet()
   */
  let rSheet = e.range.getSheet();

  /**
   * 回答が記録されているシートに紐づけられているフォームの URL を得る
   *    https://developers.google.com/apps-script/reference/spreadsheet/sheet?hl=ja#getFormUrl()
   */
  let formUrl = rSheet.getFormUrl();

  /**
   * 得られたフォームの URL から、回答の元となった Form を得て、フォームのタイトルを取得
   *    https://developers.google.com/apps-script/reference/forms/form-app?hl=ja#openByUrl(String)
   *      ↓
   *    https://developers.google.com/apps-script/reference/forms/form?hl=ja#getTitle()
   */
  let form = FormApp.openByUrl(formUrl);
  let sTitle = form.getTitle();

  if (SHEET_NAME) {     // シートの名前を追加するか?
    e.values.unshift(rSheet.getName());
  }

  if (FORM_NAME) {      // フォームの名前を追加するか?
    e.values.unshift(sTitle);
  }

  console.log(rSheet.getName());
  console.log(rSheet.getFormUrl());
  console.log(form.getTitle());
  console.log(e.values);

  let sheet = ss.getSheetByName(OUT_SHEET);         // 出力先のシートを開く
  sheet.appendRow(e.values);                        // 回答の内容を、指定されたシートに追加する
}

プログラムの変更点は、冒頭でフォームの名前を統合先のシートに追加するかどうかを、冒頭の FORM_NAME や SHEET_NAME に false か true で設定します。 ※下図では true に設定していますが、配布しているプログラムでは false となっています。

変更点①

プログラムの大きな変更は、下図の部分です。プログラム中のコメントでも説明していますが、下図の範囲が前回のプログラムから追加した部分です。

変更点②

追加したプログラムよりも、コメントや動作確認のためのデバッグ文の方が多そうなプログラムになっていますが、

  1. イベントが発生した回答の範囲(e.range → Range)から、記録されているシートを(Sheet)を取得する

  2. シートに紐づけられているフォーム(Form)を取得して、その名前(タイトル)を取得する

といった処理を行っています。

はじめは、トリガー関数に渡される引数の内容を見ていると、下図のような感じなので、冒頭のコメントにあったような要望は実現できないのではないか、と思いました。
しかしながら、range からたどっていくと、前述のようにフォームのタイトルまでたどり着きました。

「フォームの送信」に渡される引数の内容
https://developers.google.com/apps-script/guides/triggers/events?hl=ja  より

プログラムの使い方

更新した ↑ のプログラムは、以下の元の記事のプログラムに上書きしてあります。

上記の記事中のリンクからスプレッドシートをコピーし直すか、新しいプログラムは前述の 50行余りなので、↑ のプログラムを上書きしてください。

ただし、このままのプログラムでは依然と同じ動作となります。冒頭のコメントにあったように、先頭にフォームの名前を書き出したい場合には、5行目の FORM_NAME を true に変更してください。配布しているプログラムは、false になっています。

フォーム名を書き出すときは、5行目を変更する

5行目の FORM_NAME でフォーム名、8行目の SHEET_NAME でシート名を、それぞれ個別に オン(true)/オフ(false)が設定できるようになっています。片方だけオンにしても構いませんし、両方ともオフのままでも構いません。
両方をオンにした場合は、フォーム名 → シート名、の順に書き出されます。書き出す順序を入れ替えたい場合には、プログラムの変更が必要です。

最後に

最後に、お決まりのフレーズなどを書いておきます。

  • 一応の動作確認は行っているものの、不慮のトラブルによって損害等が生じても、責任はとれませんので予めご了承ください。

  • コメントを含めても 50行くらいのスクリプトであり、実行に際して目的外の場所への書き出しや収集などは行っていません。

  • 特別なエラー処理は行っていないので、意図しないケースでエラーが発生してしまうかもしれません。どうにもならない場合には、ご連絡ください。

わたし自身にしてみると、このような「スクリプトを作ること」が目的になっているような感じですが、このスクリプトが何かの役に立てば幸いです。
「スキ ♡」を押してもらえると、このようなプログラム作成の励みになります。😍

この記事が気に入ったらサポートをしてみませんか?