こんにちは,だるだるし です
会社の代表してたり音声作品投稿してたりします
お金がありません,,,金か仕事をください,,,
はい,ていうのはおいておいて
Googleフォームの自動生成
目標
GoogleフォームをスプレッドシートとGASで自動生成する
前段
『 スタディステーション』という(うちの会社の)サービス(現在完全無料なので本当に”サービス”)がある.
各自がGoogleフォームで作成したテスト,問題を皆で共有,検索できるサービス.
ここに小学二年生用の九九のサンプルを投稿したかったが,ポチポチ作るのはめんどくさかったので自動化したい.
【GAS】スプレッドシートからテスト用のGoogleFormを自動生成する
上記の記事を参照した結果,以下気になったので一応プログラマとして改良する
- 速度が遅い(多分毎回シートにアクセスしてるせい)
- 自由記述の解答形式に対応
- 汎用性を持たせる(選択肢や正答の数を無制限にする,セルを決め打ち指定するのを避ける)
- 冗長で複雑な表現を修正(配列をオブジェクトにするなど)
- その他軽微な機能追加
答え
さっくり答え
九九作った時の「スプレッドシート」
で,Googleフォームを生成するGASのコード
正直変数名とかエラーハンドリングは適当にしてあるのでご了承
//データをオブジェクト形式に変換
function getDataObjects(keyRow, dataRow) {
let dataObjects = [];
let keys = [];
for (let i in keyRow) {
let key = keyRow[i];
if (key) {
keys[key] = {
key: key,
i: i,
};
}
}
for (let row of dataRow) {
let obj = {};
for (let k in keys) {
let key = keys[k];
obj[key.key] = row[key.i];
}
dataObjects.push(obj);
}
return dataObjects;
}
//メイン関数
function myFunction() {
//シート名
let sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
let lastRow = sheet.getLastRow();//行
// let lastColumn = sheet.getLastColumn();//列
let formData = {
title: "Googleフォーム",
description: "",
order: false,
};
//全データ取得
let _sheet = sheet.getDataRange().getValues();
let _formData = getDataObjects(_sheet[0], [_sheet[1]])[0];
//フォーム名と説明文を設定
formData.title = _formData.title || formData.title;
formData.description = _formData.description || formData.description;
formData.order = (_formData.order == 1);
Logger.log(formData);
//フォームを作成
let form = FormApp.create(formData.title);
form.setDescription(formData.description);
form.setShuffleQuestions(formData.order);
//クイズモードに設定
form.setIsQuiz(true);
//問題データ
let questions = getDataObjects(_sheet[3], _sheet.splice(5, lastRow - 1));
//問題文・選択肢を作成
for (let question of questions) {
let choices;
//正解の数によってラジオボタンまたは、チェックボックスに形式を変える
let item;
switch (question.format) {
case 1: //数値解答
item = form.addTextItem();
let textValidation = FormApp.createTextValidation()
.setHelpText('数値で入力してください')
.requireNumber()
.build();
item.setValidation(textValidation);
break;
case 2: //記述
item = form.addTextItem();
break;
default: //選択
let n = 1;
switch (question.multiple) {
case 1: //複数解答 //チェックボックスの作成
item = form.addCheckboxItem();
choices = [];
while (question["choices" + n] || question["choices" + n] === 0) {
let correct = false;
for (let i in question.numOfCorrect) {
if (question["choices" + n] === question["answer" + i]);
correct = true;
break;
}
let choice = item.createChoice(question["choices" + n], correct);//text,isCorrect(booblean)
choices.push(choice);
n++;
}
break;
default: //単一解答 //ラジオボタンの作成
item = form.addMultipleChoiceItem();
//選択肢と解答の番号を取得
choices = [];
while (question["choices" + n] || question["choices" + n] === 0) {
let choice = item.createChoice(question["choices" + n], question["choices" + n] === question.answer1);
choices.push(choice);
n++;
}
break;
}
break;
}
//問題文・選択肢・配点・必須をセット
item.setTitle(question.statement || "問題");
if (choices) {
item.setChoices(choices);
}
item.setPoints(question.points);
// item.setRequired(true);
//フィードバックをセット
// Logger.log(question.feedback);
// Logger.log(question.format);
if (question.format != 2 && question.format != 1) {
if (question.feedback) {
item.setFeedbackForCorrect(FormApp.createFeedback().setText(question.feedback).build());
}
if (question.feedbackForI) {
item.setFeedbackForIncorrect(FormApp.createFeedback().setText(question.feedbackForI).build());
}
}
}
}
取り敢えず使い方
元となるスプレッドシートを作成
見にくくて申し訳ないですが,以下のようにスプレッドシートを作成.
スプレッドシートの作成方法は別の記事等を参照のこと
ざっくり解説
一行目は全体に共通する「キー」
二行目は全体に共通する「値」
三行目は空(無視される)
四行目は問題に関する「キー」
五行目はキーの説明(無視される)
六行目以降は問題の「値」(一行で一問)
一行目の「title」の直下の値がGoogleフォームの「タイトル」,
一行目の「description」の直下の値がGoogleフォームの「概要」
になる
同様に
四行目の「statement」の列が問題の「問題文」の列
四行目の「format」の列が問題の「解答形式」の列
「キー」と「値」の列が対応していれば列の順序は自由
また,「キー」が空の列は無視されるので,計算やメモの列を確保可能
正解と選択肢はいくつでも登録可能
例えば選択肢は
「choices1」「choices2」「choices3」「choices4」「choices5」,,,と増やす
「choices1」から詰めて入力
スクリプトエディタ起動
「ツール」→「スクリプト エディタ」
許可等求められた場合は適宜対応
上記スクリプトをコピペ,実行
「実行」を押して実行
ただし「デバッグ」の右隣が「myFunction」になっていることを確認
完成
「実行完了」が出たら完成
Googleドライブの”トップ”に出来ている
ポイント
"シート1"のところはシート名に合わせる
let sheet = SpreadsheetApp.getActive().getSheetByName('シート1');
最初にシート全体を読み込んで読み込み回数を減らす
let _sheet = sheet.getDataRange().getValues();
「getDataObjects関数(自作)」で「question」オブジェクトにする
for文では「of」を使用して「qestionList[i][5]」のようなわかりにくい表現を避ける
//問題データ
let questions = getDataObjects(_sheet[3], _sheet.splice(5, lastRow - 1));
//問題文・選択肢を作成
for (let question of questions) {
,,,
}
テキスト入力解答欄は addTextItem で作成
解答形式を指定する場合は createTextValidation を使用
以下は解答を数字に限定する例
item = form.addTextItem();
let textValidation = FormApp.createTextValidation()
.setHelpText('数値で入力してください')
.requireNumber()
.build();
item.setValidation(textValidation);
問題順をランダムにするには setShuffleQuestions をtrueにする
let form = FormApp.create("title");
form.setShuffleQuestions(true);
問題点
- 高速化したけど遅い(大量の問題を作る場合は結構待つ)
- 自動生成では自由記述型の解答形式の問題に正答を設定できない(手動か選択型なら可能,参考)
おわり
こんな感じです
お付き合いいただきありがとうございました
また,「スタディステーション」等についても記事にしていただきますので
今後ともよろしくお願いたします
あと,仕事ください