この記事では、GAS(Google Apps script)を使って、おおよそのセミナーや、企業説明会で使える参加者向けのアンケートを作成します。
お世話になっているサイトは、いつも隣にITのお仕事さんの
です。
まず、下記のような3枚のスプレッドシートを用意します。
・シート「トップ画面」
ここには、ボタンを設置して、後でこのボタンを押すとフォームが作れるようにします。
・シート「フォームのタイトルと説明の情報」
ここには、作成するフォームのタイトルと説明文を入れます。
・シート「項目データ」
ここには、アンケート回答者がラジオボタン、チェックボックス、リストアイテムから選択出来るようスプレッドシートに配置しています。
このデータを二次元配列として取得して、各列ごとに1次元配列に変換して、ラジオボタンなどから選択出来るようにしています。
まず、スプレッドシートのボタンを押すとフォームが作れる関数、「pushButton」を作ります。
シート「フォームのタイトルと説明の情報」を二次元配列arrayとして取得して、array[0][1]をタイトル、array[1][1]をフォームの説明文として取得しています。
また、フォームに氏名とメールアドレスのテキストアイテムを追加します。
メールアドレスは@が含まれているなど、メールアドレスとして正しいかどうかを検証しています。
このメールアドレスとして検証するという部分については、
<ねこフォーム4>ねこあつめフォームに「メールアドレス」を追加する
で詳細に掲載致しました。
//このボタンを押すと、フォームが作成される。
function pushButton() {
//シート「フォームのタイトルと説明の情報」からフォームのタイトルと説明を取得
const ss=SpreadsheetApp.getActiveSpreadsheet();
const array=ss.getSheetByName('フォームのタイトルと説明の情報').getDataRange().getValues();
const formTitle=array[0][1];//タイトル
const formDescription=array[1][1];//フォームの説明文
//フォームを作成。タイトルにはシート「フォームのタイトルと説明の情報」のvalues[0][1]から取得される
const form=FormApp.create(formTitle);
//フォームの説明。フォームの説明文にはシート「フォームのタイトルと説明の情報」のvalues[1][1]から取得される
form.setDescription(formDescription);
//以下、フォームの設問の項目
form.addTextItem().setTitle('氏名').setRequired(true); //氏名は入力必須項目にしている。
const validationEmail=FormApp.createTextValidation().requireTextIsEmail().build();//eメールアドレスが正しいか検証
form.addTextItem().setTitle('メールアドレス').setRequired(true).setValidation(validationEmail);
}
では、いよいよスプレッドシートのシート「項目データ」からデータを取得して、フォームを作成して行きます。
まず、シート「項目データ」を二次元配列として取得するために、下記のコードを書きました。
//以下、シート「項目データ」から取得している。
//シート「項目データ」からフォームの質問の項目を二次元配列として取得し、その二次元配列のタイトル行を削除する
const dataValues=ss.getSheetByName('項目データ').getDataRange().getValues();
dataValues.shift()
このコードでは、定数dataValuesにシートを二次元配列として取得したデータを格納して、先頭のタイトル行をshisft()で削除しています。
この二次元配列の各行をフォームのアイテムから選択出来るように一次元配列に変換して、更に空白行を取り除く関数generateArrayを作成しました。
引数に二次元配列のデータとその行を指定して関数generateArrayに送ります。
ここではmapで一次元配列に変換して、filterで空白行を取り除いています。
/**
* フォームのアイテムの内容をスプレッドシートから取得する関数
* シート「項目データ」の値を取得した二次元配列から、指定の列のデータを抜き出し一次元配列を構成する。その為、mapを使っている。
* その際、列の空白データを削除するためにfilterも使っている。
*
* @param{Object[][]}シートのデータを二次元配列化とした配列
* @param{number}配列の列数(0以上のインデックス)
* @return{Object{}}指定の列(見出しを除く)のデータによる一次元配列
*/
function generateArray(values,column){
return values.map(record=>record[column]).filter(value=>value);
}
関数呼び出し時には、下記のように指定しました。
A列「性別」は、ラジオボタンで、
generateArray(dataValues,0)
と記述し、引数に二次元配列のデータと列数を指定することで「性別」が選択出来ます。
form.addMultipleChoiceItem() //ラジオボタンはシート「項目データ」の「0列目」から取得している。
.setTitle('性別')
.setChoiceValues(generateArray(dataValues,0))
.setRequired(true);
テキストアイテムで学校名を入力します。
form.addTextItem().setTitle('在学、卒業の学校名').setRequired(true);//入力はテキストアイテム
B列「学部」の呼び出しは、ラジオボタンで、
generateArray(dataValues,1)
です。その他の学部も選択記載出来るようにしています。
form.addMultipleChoiceItem() //ラジオボタンはシート「項目データー」の「1列目」から取得している
.setTitle('学部')
.setChoiceValues(generateArray(dataValues,1))
.showOtherOption(true)//その他の選択肢
学科・コースはテキストアイテムで入力します。
form.addTextItem().setTitle('学科・コース');
C列「卒業・在学の区分」はラジオボタン(※必須)で、
generateArray(dataValues,2)
です。その他の項目も選択出来ます。
form.addMultipleChoiceItem() //ラジオボタンはシート「項目データ」の「2列目」から取得している
.setTitle('卒業・在学の区分')
.setChoiceValues(generateArray(dataValues,2))
.showOtherOption(true)//その他の選択肢
.setRequired(true);
D列「出身・在住の都道府県」はリストアイテム(※必須)で、
generateArray(dataValues,3)
です。
これはリストアイテムのタイトルを変えて2回呼び出しています。
1回目の呼び出しはお住まい、2回目は出身です。
form.addListItem() //リストアイテムはシート「項目データ」の「3列目」から取得している
.setTitle('お住まいの都道府県は?')
.setChoiceValues(generateArray(dataValues,3))
.setRequired(true);
form.addListItem() //リストアイテムはシート「項目データ」の「3列目」から取得している
.setTitle('ご出身の都道府県は?')
.setChoiceValues(generateArray(dataValues,3))
.setRequired(true);
E列「当社を知った媒体」はチェックボックス(※必須)で、
generateArray(dataValues,4)
です。
これもその他を選択出来るようにしています。
form.addCheckboxItem() //チェックボックスはシート「項目データ」の「4列目」から取得している
.setTitle('当社を知った媒体はどちらでしょうか。')
.setChoiceValues(generateArray(dataValues,4))
.showOtherOption(true)//その他の選択肢
.setRequired(true);
これ以降は、セミナーの内容が5段階評価で選択出来るようにスケールアイテムを使っています。(※必須)
//以下、スケールアイテム
form.addScaleItem()
.setTitle('講師の声の聞き取りやすさ 1: 全く良くない 〜 5: 大変良い')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('講師の説明の分かりやすさ 1: 全く分からない 〜 5: 大変分かりやすい')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('スタッフの身だしなみ 1: 全く良くない 〜 5: 大変良い')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('スタッフの対応 1: 全く良くない 〜 5: 大変良い')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('当社志望度 1: 低い 〜 5: 高い')
.setBounds(1,5)
.setRequired(true);
最後は自由に記入できる段落入力アイテムです。
form.addParagraphTextItem().setTitle('ご意見ご要望');//段落テキストアイテム
ここまでで実行すると、このようなフォームが作れます。これは目のマークでプレビューを押した画面です。
マイドライブに保存する場合はここまででも良いのですが、指定のドライブに保存したい場合は、プロパティストアというものを使って、フォルダIDをFOLDER_IDという文字列に保存します。
フォルダIDはこちらになります。
このモザイク部分32桁をこちらのコードでFOLDER_IDに保存します。
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXを実際のフォルダーIDに置き換えて下さい。特定のフォルダに指定する場合は、pushButtonを押すよりも先にこちらを実行して下さい。
//フォームを保存したいドライブのIDを指定して、1番最初に実行する。
function setScriptProperty(){
PropertiesService.getScriptProperties().setProperty('FOLDER_ID','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
}
その実行画面です。
この様に何も起こらないので不安になるかと思います。
そこで、FOLDER_IDに格納出来たのか確認するコードを書きました。
//プロパティストアにフォルダIDが格納されたことを確認する
function getScriptProperty(){
const folderid=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
console.log(folderid);
実行結果です。先ほどのフォルダーID32桁が無事に表示されましたので、モザイク処理を施しました。
あとはメインの関数にこの4行のコードを追記します。
プロパティストアからFOLDER_IDを取り出して、フォームをそこに格納し、マイドライブに出来てしまったフォームの方は削除します。
//ここの4行ををコメントアウトすることで、マイドライブに保存が出来る。
//フォームを指定のドライブに保存する
const id=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');//格納するフォルダIDを取り出す
const formFile=DriveApp.getFileById(form.getId());//作成したフォームをオブジェクトとして取得
DriveApp.getFolderById(id).addFile(formFile);//指定のフォルダにFileオブジェクトを追加する
DriveApp.getRootFolder().removeFile(formFile);//マイフォルダからFileオブジェクトを削除する
コメントにもある様、マイドライブ(ルードディレクトリ)に保存したい場合は、一旦コメントアウトをしておいても状況に寄っては宜しいかもしれません。
ここまでの説明で、もう少し詳しくプロパティストアについて知りたいという方は、
<ねこフォーム2>GASで作成したフォームを指定のフォルダに格納する
をご覧ください。
では、これまでのコードをまとめます。
/**
* フォームのアイテムの内容をスプレッドシートから取得する関数
* シート「項目データ」の値を取得した二次元配列から、指定の列のデータを抜き出し一次元配列を構成する。その為、mapを使っている。
* その際、列の空白データを削除するためにfilterも使っている。
*
* @param{Object[][]}シートのデータを二次元配列化とした配列
* @param{number}配列の列数(0以上のインデックス)
* @return{Object{}}指定の列(見出しを除く)のデータによる一次元配列
*/
function generateArray(values,column){
return values.map(record=>record[column]).filter(value=>value);
}
//このボタンを押すと、フォームが作成される。
function pushButton() {
//シート「フォームのタイトルと説明の情報」からフォームのタイトルと説明を取得
const ss=SpreadsheetApp.getActiveSpreadsheet();
const array=ss.getSheetByName('フォームのタイトルと説明の情報').getDataRange().getValues();
const formTitle=array[0][1];//タイトル
const formDescription=array[1][1];//フォームの説明文
//フォームを作成。タイトルにはシート「フォームのタイトルと説明の情報」のvalues[0][1]から取得される
const form=FormApp.create(formTitle);
//フォームの説明。フォームの説明文にはシート「フォームのタイトルと説明の情報」のvalues[1][1]から取得される
form.setDescription(formDescription);
//以下、フォームの設問の項目
form.addTextItem().setTitle('氏名').setRequired(true); //氏名は入力必須項目にしている。
const validationEmail=FormApp.createTextValidation().requireTextIsEmail().build();//eメールアドレスが正しいか検証
form.addTextItem().setTitle('メールアドレス').setRequired(true).setValidation(validationEmail);
//以下、シート「項目データ」から取得している。
//シート「項目データ」からフォームの質問の項目を二次元配列として取得し、その二次元配列のタイトル行を削除する
const dataValues=ss.getSheetByName('項目データ').getDataRange().getValues();
dataValues.shift()
form.addMultipleChoiceItem() //ラジオボタンはシート「項目データ」の「0列目」から取得している。
.setTitle('性別')
.setChoiceValues(generateArray(dataValues,0))
.setRequired(true);
form.addTextItem().setTitle('在学、卒業の学校名').setRequired(true);//入力はテキストアイテム
form.addMultipleChoiceItem() //ラジオボタンはシート「項目データー」の「1列目」から取得している
.setTitle('学部')
.setChoiceValues(generateArray(dataValues,1))
.showOtherOption(true)//その他の選択肢
form.addTextItem().setTitle('学科・コース');
form.addMultipleChoiceItem() //ラジオボタンはシート「項目データ」の「2列目」から取得している
.setTitle('卒業・在学の区分')
.setChoiceValues(generateArray(dataValues,2))
.showOtherOption(true)//その他の選択肢
.setRequired(true);
form.addListItem() //リストアイテムはシート「項目データ」の「3列目」から取得している
.setTitle('お住まいの都道府県は?')
.setChoiceValues(generateArray(dataValues,3))
.setRequired(true);
form.addListItem() //リストアイテムはシート「項目データ」の「3列目」から取得している
.setTitle('ご出身の都道府県は?')
.setChoiceValues(generateArray(dataValues,3))
.setRequired(true);
form.addCheckboxItem() //チェックボックスはシート「項目データ」の「4列目」から取得している
.setTitle('当社を知った媒体はどちらでしょうか。')
.setChoiceValues(generateArray(dataValues,4))
.showOtherOption(true)//その他の選択肢
.setRequired(true);
//以下、スケールアイテム
form.addScaleItem()
.setTitle('講師の声の聞き取りやすさ 1: 全く良くない 〜 5: 大変良い')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('講師の説明の分かりやすさ 1: 全く分からない 〜 5: 大変分かりやすい')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('スタッフの身だしなみ 1: 全く良くない 〜 5: 大変良い')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('スタッフの対応 1: 全く良くない 〜 5: 大変良い')
.setBounds(1,5)
.setRequired(true);
form.addScaleItem()
.setTitle('当社志望度 1: 低い 〜 5: 高い')
.setBounds(1,5)
.setRequired(true);
form.addParagraphTextItem().setTitle('ご意見ご要望');//段落テキストアイテム
//ここの4行ををコメントアウトすることで、マイドライブに保存が出来る。
//フォームを指定のドライブに保存する
const id=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');//格納するフォルダIDを取り出す
const formFile=DriveApp.getFileById(form.getId());//作成したフォームをオブジェクトとして取得
DriveApp.getFolderById(id).addFile(formFile);//指定のフォルダにFileオブジェクトを追加する
DriveApp.getRootFolder().removeFile(formFile);//マイフォルダからFileオブジェクトを削除する
}
//フォームを保存したいドライブのIDを指定して、1番最初に実行する。
function setScriptProperty(){
PropertiesService.getScriptProperties().setProperty('FOLDER_ID','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
}
//プロパティストアにフォルダIDが格納されたことを確認する
function getScriptProperty(){
const folderid=PropertiesService.getScriptProperties().getProperty('FOLDER_ID');
console.log(folderid);
}
あとはスプレッドシートのトップ画面のボタンの右上3点リーダーからスクリプトを「pushButton」に割り当てて押すと、あなたが指定したフォルダ、または上記4行をコメントアウトした場合はマイドライブに保存されます。
お疲れ様でした、ブレイクタイムフォトはこちらになります。
恵比寿ガーデンプレイス、フランスのクリスタルメーカー、バカラのシャンデリア。
カメラはOLYMPUSのミラーレス一眼。
この写真ムービーは、下記の記事でご覧になれます。
■参考文献の紹介■
初めてGASを学ぶ方向け。
スプレッドシートの基本的な使い方からGASのベースとなるJavaScriptの基礎文法、GASでの初歩的なプログラミングを学べます。
GASに少し慣れて来たら、基礎固めとリファレンスとしてこの本を通してじっくり学べます。