スプレッドシートからテスト用Googleフォームを作成するGAS
【入場無料】TD SYNNEX主催のIT展示会「Inspire 2024」10/24(木)東京国際フォーラムにて開催!
Googleスプレッドシートから採点等ができるテスト用Googleフォームを作成するGASを紹介します。
概要
Googleフォームのテスト機能は各質問に配点や正解やフィードバックを設定でき、自動で採点してくれるとても便利な機能です。
しかし、このフォームを1つ1つ作るのはなかなか大変な作業で、問題数が多ければ多いほど負担も増してしまいます。
今回は、スプレッドシート上に問題データを入力しておけば、自動でテスト用のGoogleフォームを作成してくれるGASを紹介したいと思います。
※今回の内容では、問題形式はラジオボタン(選択問題)のみです
使用するGASはスプレッドシート等に紐づいたタイプにしたいと思います。
GASの準備については以前の記事の「スプレッドシートに紐づいたGASの作成方法」の項目を参考にしてください。
スプレッドシートのへデータ入力
スプレッドシートには以下のようにデータを入力し、シート名はそのまま「シート1」としています。
A列 | B列 | C列 | D列 | E列 | F列 | G列 | H列 | I列 | J列 |
---|---|---|---|---|---|---|---|---|---|
フォームタイトル | 理解度テスト | ||||||||
フォームの説明文 | 簡単な理解度チェックのテストです | ||||||||
作成したフォームのURL | |||||||||
問題のタイトル | 問題の説明 | 配点 | 問題形式 | 正解の番号 | 選択肢① | 選択肢② | 選択肢③ | 選択肢④ | フィードバック(答えの解説など) |
問1.GASは何の略称か | GASは以下のうちどれの略称か答えよ。 | 60 | ラジオボタン | 2 | Google Apple System | Google Apps Script | Good Admin Script | Group Apply System | 正解はGoogle Apps Scriptです。 |
問2.GASのベース言語 | GASのベースになっているプログラミング言語は以下のうちどれか。 | 40 | ラジオボタン | 3 | Python | Java | JavaScript | Go | 正解はJavaScriptです。 |
GASの作成
コピペですぐに使いたい人向けに、今回の完成状態のGASを先に紹介しておきます。
この関数createForm()
をスプレッドシート上に作成したボタンに割り当てるなどすれば使用できます。
function createForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
const firstRow = 5;
const lastRow = sheet.getLastRow();
const dataRows = lastRow - (firstRow - 1);
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
const form = FormApp.create(formTitle);
form.setDescription(formDescription)
.setIsQuiz(true);
questionList.forEach(question => {
var item = form.addMultipleChoiceItem();
var choiceList = [];
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = question.answer == (index + 1);
let choiceObj = item.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
item.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
});
sheet.getRange('B3').setValue(form.getEditUrl());
}
以下では詳しく理解したい人向けに、コードの内容についての解説を段階的にしていきたいと思います。
1. スプレッドシートからデータの取得
まずはスプレッドシートからフォーム作成に必要なデータを取得します。
データの取得の詳細についてはこちらの記事を参考にしてください。
function createForm() {
// スプレッドシートとシートオブジェクトを取得
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
// フォームのタイトルと説明文を取得
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
// 問題リストの最初の行(=firstRow =5行目)と、最終行(=lastRow)を取得
const firstRow = 5;
const lastRow = sheet.getLastRow();
// 問題の数(行数)を取得
// 例:9行目まで問題があった場合、9 - (5 - 1) = 5問分なのでdataRows = 5となる
const dataRows = lastRow - (firstRow - 1);
// 問題のデータを取得 getRange(最初の行, 最初の列, 行数, 列数)
// 最初の行はfirstRow、最初の列はA列なので「1」、行数はdataRows、列数はJ列までなので「10」
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
// 実行ログに取得した内容を表示
console.log('formTitle : ' + formTitle);
console.log('formDescription : ' + formDescription);
console.log(questionList);
}
実行結果:
GASの実行ログに取得したデータが表示されました。
2. 問題のデータの整形
問題のデータをmap処理を使って整形します。
map処理についてはこちらの記事内で解説しているので参考にしてください。
function createForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
const firstRow = 5;
const lastRow = sheet.getLastRow();
const dataRows = lastRow - (firstRow - 1);
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
// 追加部ここから
// map処理で問題のデータを整形
// 今回のコードでは問題形式(=type)は使用しませんが今後の為に入れています
// 正解の番号(=answer)は数値型データになるように調整
// 選択肢は配列の形にして1つの項目にしています ※[ 選択肢①, 選択肢②, 選択肢③, 選択肢④ ]という配列
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
// 追加部ここまで
console.log('formTitle : ' + formTitle);
console.log('formDescription : ' + formDescription);
console.log(questionList);
}
実行結果:
GASの実行ログに取得したデータを整形したものが表示されました。
3. フォームの作成と設定
まずはフォーム自体を作成して、フォームの説明文とテストにすることを設定します。
この時点ではまだ問題は作成していないので、素のままのフォームが作成されます。
また、このコード以降は実行するたびに新しくフォームが作成されるので、内容を変えて試す場合は新しく作られたフォームを確認するように気を付けてください。
function createForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
const firstRow = 5;
const lastRow = sheet.getLastRow();
const dataRows = lastRow - (firstRow - 1);
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
// 追加部ここから
// フォームを作成
const form = FormApp.create(formTitle);
// フォームに説明文、テストにすることを設定
form.setDescription(formDescription)
.setIsQuiz(true);
// 実行ログに作成したフォームの編集用URLを表示
console.log(form.getEditUrl())
// 追加部ここまで
}
実行結果:
GASの実行ログに作成したフォームの編集用URLが表示されました。
この編集用URLを開くとフォームが作成されています。
作成されたフォームのタイトルや説明文が指定のものになっていて、設定タブの「テストにする」がONになっているのが確認できます。
4. 問題の作成と選択肢の追加
作成したフォームに問題を1問ずつ追加していきます。
今回は選択肢問題(ラジオボタン)のみ対応しているので.addMultipleChoiceItem()
で問題を追加します。
問題を追加すると、その返り値として「問題オブジェクト(MultipleChoiceItemオブジェクト)」を取得することができます。
手順として、この「問題オブジェクト」に選択肢を作成して、リスト(配列)の形で設定してあげる必要があります。
流れを整理すると以下のようになります。
問題(item)
を作成- 作成した
問題(item)
に選択肢(choiceObj)
を作成 - 作成した
選択肢(choiceObj)
を配列の形にする - 配列にした
選択肢(choiceObj)
を問題(item)
に設定
このコードを実行すると、前項とは別に新しくフォームが作成されるので、前項で開いたフォームではなく実行ログに表示された新しいURLのフォームを確認するように気を付けてください。
function createForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
const firstRow = 5;
const lastRow = sheet.getLastRow();
const dataRows = lastRow - (firstRow - 1);
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
const form = FormApp.create(formTitle);
form.setDescription(formDescription)
.setIsQuiz(true);
console.log(form.getEditUrl())
// 追加部ここから
// 問題を1つずつ作成
questionList.forEach(question => {
// 選択肢問題(ラジオボタン)を作成
var item = form.addMultipleChoiceItem();
// 選択肢リストの枠を作成
var choiceList = [];
// 選択肢データ(question.choices)をforEachで1つずつ処理
question.choices.forEach((choice, index) => {
// 選択肢が空白ではない場合は以降を実行
// ※選択肢が空白 = スプレッドシートの選択肢のセルに何も入力されていない = 選択肢の数が4つ未満 の場合、空の選択肢を追加しないようにしています
if (choice != '') {
// この選択肢が正解かどうかチェック
// indexはこの選択肢が何番目の選択肢かを示します(1つ目の選択肢なら「0」、2つ目の選択肢なら「1」…)
// (index + 1)でスプレッドシート上で指定した正解の番号と一致するかをチェック
// 正解の場合:isCorrect = TRUE、不正解の場合:isCorrect = FALSE
let isCorrect = question.answer == (index + 1);
// 選択肢オブジェクトを作成
// createChoice(選択肢の内容, 正解の選択肢ならTRUE/不正解の選択肢ならFALSE)
let choiceObj = item.createChoice(choice, isCorrect);
// 選択肢リストに選択肢オブジェクトを追加
choiceList.push(choiceObj);
}
});
// 問題に選択肢リストを設定
item.setChoices(choiceList);
});
}
実行結果:
GASの実行ログに作成したフォームの編集用URLが表示されました。
この編集用URLを開くとフォームが作成されています。
作成されたフォームに問題と選択肢、解答集に正解が追加されていることが確認できます。
5. 問題の設定
作成した問題にはまだ問題のタイトルや説明、配点、フィードバックが設定されていません。
それぞれまとめて設定していきましょう。
その際、前項で設定した選択肢リストも合わせて設定します。
フィードバックの設定では、まずフィードバックオブジェクトを作成して、それを正解不正解ごとに設定してあげる必要があります。
ただし今回は正解の場合も不正解の場合も同じフィードバックを表示するようにしておきます。
このコードを実行すると、前項とは別に新しくフォームが作成されるので、前項で開いたフォームではなく実行ログに表示された新しいURLのフォームを確認するように気を付けてください。
function createForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
const firstRow = 5;
const lastRow = sheet.getLastRow();
const dataRows = lastRow - (firstRow - 1);
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
const form = FormApp.create(formTitle);
form.setDescription(formDescription)
.setIsQuiz(true);
console.log(form.getEditUrl())
questionList.forEach(question => {
var item = form.addMultipleChoiceItem();
var choiceList = [];
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = question.answer == (index + 1);
let choiceObj = item.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
// 追加部ここから
// フィードバックオブジェクトを作成
let feedback = FormApp.createFeedback().setText(question.feedback).build()
// 問題のタイトル、説明、配点、選択肢リスト、回答に対するフィードバックを設定
item.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
// 追加部ここまで
});
}
実行結果:
GASの実行ログに作成したフォームの編集用URLが表示されました。
この編集用URLを開くとフォームが作成されています。
作成されたフォームの問題にタイトルと説明、配点、フィードバックが追加されていることが確認できます。
6. スプレッドシートにボタン追加とURLの書き込み
フォーム作成自体はここまでで完了です。
しかしこのままだと実行するために毎度GASを開く必要があるので、スプレッドシート上に実行用のボタンを設置します。
あわせて、完了時にフォーム作成が完了したことがわかるようにメッセージボックスを表示し、作成したフォームのURLをB3セルに書き込んでおきたいと思います。
まずはスプレッドシートに実行用のボタンを設置し、スクリプトを割り当てます。
ボタン作成の詳細手順はこちらの記事内の説明を参考にしてください。
また、このコードを実行すると、前項とは別に新しくフォームが作成されるので、前項で開いたフォームではなく実行ログまたはB3セルに表示された新しいURLのフォームを確認するように気を付けてください。
function createForm() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');
const formTitle = sheet.getRange('B1').getDisplayValue();
const formDescription = sheet.getRange('B2').getDisplayValue();
const firstRow = 5;
const lastRow = sheet.getLastRow();
const dataRows = lastRow - (firstRow - 1);
var questionList = sheet.getRange(firstRow, 1, dataRows, 10).getDisplayValues();
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
const form = FormApp.create(formTitle);
form.setDescription(formDescription)
.setIsQuiz(true);
console.log(form.getEditUrl())
questionList.forEach(question => {
var item = form.addMultipleChoiceItem();
var choiceList = [];
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = question.answer == (index + 1);
let choiceObj = item.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
let feedback = FormApp.createFeedback().setText(question.feedback).build()
item.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
});
// 追加部ここから
// 作成したフォームの編集用URLをB3セルに書き込み
sheet.getRange('B3').setValue(form.getEditUrl());
// メッセージボックスの表示
Browser.msgBox('「' + formTitle + '」の作成が完了しました');
// 追加部ここまで
}
実行結果:
実行用ボタンから実行すると、スプレッドシート上にメッセージボックスが表示され、B3セルにフォームの編集用URLが書き込まれました。
まとめ
今回はスプレッドシートからテスト用Googleフォームを作成する方法をご紹介しました。
この内容ではラジオボタンの選択問題のみのテストを紹介しましたが、Googleフォームではチェックボックスや記述式の問題も作成できます。
他の問題形式にも対応する方法も今後ご紹介する予定です。
テスト用Googleフォームは教育サービスのGoogle Classroomなどにうってつけのとても便利な機能です。
Google Classroomで活用できるテスト用Googleフォームの自動生成についてもいずれは紹介していけたらと思います。