スプレッドシートからテスト用Googleフォームを作成するGAS

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ラジオボタン2Google Apple SystemGoogle Apps ScriptGood Admin ScriptGroup Apply System正解はGoogle Apps Scriptです。
問2.GASのベース言語GASのベースになっているプログラミング言語は以下のうちどれか。40ラジオボタン3PythonJavaJavaScriptGo正解は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オブジェクト)」を取得することができます。
手順として、この「問題オブジェクト」に選択肢を作成して、リスト(配列)の形で設定してあげる必要があります。
流れを整理すると以下のようになります。

  1. 問題(item)を作成
  2. 作成した問題(item)選択肢(choiceObj)を作成
  3. 作成した選択肢(choiceObj)を配列の形にする
  4. 配列にした選択肢(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フォームの自動生成についてもいずれは紹介していけたらと思います。

Google Cloudの導入は当社にご相談ください

ITディストリビューターであるTD SYNNEXはGoogle Cloud™ Partner Award を受賞するなど、長年にわたりGoogle™のグローバル認定ディストリビューターとして、総合的な Googleソリューションを提供しています。お客様にとって最適なソリューションの提案や導入、活用をサポートします。

製品・サービスについてのお問合せ

情報収集中の方へ

導入事例やソリューションをまとめた資料をご提供しております。

資料ダウンロード
導入をご検討中の方へ

折り返し詳細のご案内を差し上げます。お問い合わせお待ちしております。

お問い合わせ