スプレッドシートからテスト用Googleフォームを作成するGAS(複数選択)
Googleスプレッドシートから採点等ができる複数選択問題のテスト用Googleフォームを作成するGASを紹介します。
概要
前回の記事では、スプレッドシート上の問題データから、ラジオボタン(選択問題)のテストフォームを作る方法をご紹介しました。
今回は、チェックボックス(複数選択)の問題も作成できるようにし、2種類の問題形式を利用できるGoogleフォームの自動生成スプレッドシートを作ります。
前回の記事で作成したスプレッドシートとGASに手を加えていきたいと思います。
スプレッドシートのへデータ入力
スプレッドシートには以下のようにデータを入力し、シート名はそのまま「シート1」としています。
前回のシートに「問3」の行を追加しています。
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です。 |
問3.Googleのサービス | Googleの提供しているサービスを選択せよ。 | 50 | チェックボックス | 1,3 | Spreadsheet | Excel | Document | Word | 正解はSpreadsheetとDocumentです。 |
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: 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 => {
if (question.type == 'ラジオボタン') {
var choiceItem = form.addMultipleChoiceItem();
var choiceList = [];
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = question.answer == String(index + 1);
let choiceObj = choiceItem.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
choiceItem.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
}
else if (question.type == 'チェックボックス') {
var checkboxItem = form.addCheckboxItem();
var choiceList = [];
var questions = question.answer.split(',');
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = questions.includes( String(index + 1) );
let choiceObj = checkboxItem.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
checkboxItem.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
}
else {
Browser.msgBox('「'+ question.title +'」は作成できない問題形式です');
}
});
sheet.getRange('B3').setValue(form.getEditUrl());
Browser.msgBox('「' + formTitle + '」の作成が完了しました');
}
以下では詳しく理解したい人向けに、前回の記事からの変更点を解説したいと思います。
1. 正解の番号の受け取り方
スプレッドシート上のデータを受け取った後、map処理を用いてデータを整形する部分です。
基本的には前回の記事と同じですが、正解の番号の受け取り方を変更しています。
// map処理で問題のデータを整形
// 正解の番号は複数の場合があるので、そのまま受け取ります。
// ※前回記事では「数値型」に変更していました。
questionList = questionList.map(question => {
return {
title: question[0],
helpText: question[1],
point: question[2],
type: question[3],
answer: question[4], // 変更前: answer: Number(question[4]),
choices: [question[5], question[6], question[7], question[8]],
feedback: question[9]
}
});
2. 問題形式による分岐
フォームの作成後、問題を追加していく部分です。
問題形式によって分岐し、それぞれに合ったオブジェクトを作成します。
※ラジオボタンの場合、MultipleChoiceItemというオブジェクト
※チェックボックスの場合、CheckboxItemというオブジェクト
questionList.forEach(question => {
if (question.type == 'ラジオボタン') {
// ラジオボタン(選択問題)の追加処理
// 一部変更あり、次項で解説
}
else if (question.type == 'チェックボックス') {
// チェックボックス(複数選択)の追加処理
// 後の項で解説
}
else {
// 問題の形式がラジオボタンでもチェックボックスでもなかった場合
// メッセージボックスを表示、問題は作成しません。
Browser.msgBox('「'+ question.title +'」は作成できない問題形式です');
}
});
3. ラジオボタン(選択問題)の追加処理
項1でデータ整形時にデータ型をそのままにした為、question.answer
には「文字列型データ」が格納されています。
正解の番号と問題番号との比較を行う際にデータ型が違うと、エラーとなってしまうのでデータ型を揃える処理を追加します。
// 混同を防ぐため変数名を変えています。
var choiceItem = form.addMultipleChoiceItem(); // 変更前: var item = form.addMultipleChoiceItem();
var choiceList = [];
question.choices.forEach((choice, index) => {
if (choice != '') {
// この選択肢が正解かどうかチェック
// question.answerが「文字列型データ」なので、型を揃えて比較する
let isCorrect = question.answer == String(index + 1); // 変更前: let isCorrect = question.answer == (index + 1)
let choiceObj = choiceItem.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
choiceItem.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
4. チェックボックス(複数選択)の追加処理
チェックボックス(複数選択)の問題を追加する際は.addCheckboxItem()
を用います。
問題の追加手順はラジオボタンと基本同じですが、正解の番号が複数ある部分についてアレンジが必要です。
var checkboxItem = form.addCheckboxItem();
var choiceList = [];
// 正解の番号を配列に変換
// split処理を用いて「文字列型データ」から「文字列型データの配列」に分割します。
// 分割する際の区切り文字は「,(半角カンマ)」です。
var questions = question.answer.split(',');
question.choices.forEach((choice, index) => {
if (choice != '') {
// この選択肢が正解に含まれているかどうかチェック
// questionsにこの選択肢が含まれているかinclueds処理を用いて確認します。
// index + 1は「数値型データ」なので「文字列型データ」に揃えてから確認します。
let isCorrect = questions.includes( String(index + 1) );
let choiceObj = checkboxItem.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
checkboxItem.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
完成
これでラジオボタンとチェックボックスの2種類の問題形式を利用できるフォームの自動生成スプレッドシートが完成しました。
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: 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 => {
if (question.type == 'ラジオボタン') {
var choiceItem = form.addMultipleChoiceItem();
var choiceList = [];
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = question.answer == String(index + 1);
let choiceObj = choiceItem.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
choiceItem.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
}
else if (question.type == 'チェックボックス') {
var checkboxItem = form.addCheckboxItem();
var choiceList = [];
var questions = question.answer.split(',');
question.choices.forEach((choice, index) => {
if (choice != '') {
let isCorrect = questions.includes( String(index + 1) );
let choiceObj = checkboxItem.createChoice(choice, isCorrect);
choiceList.push(choiceObj);
}
});
const feedback = FormApp.createFeedback().setText(question.feedback).build()
checkboxItem.setTitle(question.title)
.setHelpText(question.helpText)
.setPoints(question.point)
.setChoices(choiceList)
.setFeedbackForCorrect(feedback)
.setFeedbackForIncorrect(feedback);
}
else {
Browser.msgBox('「'+ question.title +'」は作成できない問題形式です');
}
});
sheet.getRange('B3').setValue(form.getEditUrl());
Browser.msgBox('「' + formTitle + '」の作成が完了しました');
}
実行結果:
実行用ボタンから実行すると、スプレッドシート上にメッセージボックスが表示され、B3セルにフォームの編集用URLが書き込まれました。
フォームの編集用URLにアクセスすると、このように問題と正解が設定されていることが確認できます。
まとめ
前回の記事に引き続きスプレッドシートからテスト用Googleフォームを作成する方法をご紹介しました。
これで2種類の問題形式が扱えるテストを自動生成できるようになりました。
しかし、Googleフォームでは記述式の問題や画像付き問題も作成できます。
それらについて対応する方法も今後ご紹介する予定です。
テスト用Googleフォームは教育サービスのGoogle Classroomなどにうってつけのとても便利な機能です。
Google Classroomで活用できるテスト用Googleフォームの自動生成についてもいずれは紹介していけたらと思います。