スプレッドシートから2択クイズのGoogleフォームを自動生成するGAS(FLAG=1行のみ/選択肢もランダム)

Googleスプレッドシートのデータ(A:No / B:FLAG / C:問題 / D:正解)を読み取り、FLAG=1 の行だけを出題に採用して2択のGoogleフォームを自動生成するApps Scriptです。誤答は「次の行のD列(最終行は2行目にループ)」を使い、選択肢はコード側でシャッフル設問順はフォーム機能でシャッフルします。生成されたフォームは元スプレッドシートと同じフォルダに移動されます。

function createTwoChoiceFormFromActiveSheet_ShuffleInCode() {
  // ===== 設定 =====
  const START_ROW        = 2;  // 見出しの次
  const COL_FLAG         = 2;  // B=FLAG
  const COL_Q            = 3;  // C=問題(赤)
  const COL_A            = 4;  // D=正解(青)
  const SHUFFLE_QUESTIONS = true;  // 設問の順番をフォーム機能でシャッフル
  const SHUFFLE_CHOICES   = true;  // 選択肢の順番をコードでシャッフル

  // ===== データ取得 =====
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sh = ss.getActiveSheet();
  const lastRow = sh.getLastRow();
  if (lastRow < START_ROW) throw new Error('データ行がありません。');

  const data = sh.getRange(START_ROW, 1, lastRow - START_ROW + 1, 4).getValues(); // A〜D
  const nAll = data.length;

  // 全行(誤答参照用)& 出題対象(B=1)
  const itemsAll = data.map((row, i) => ({
    rowIndex0: i,
    flag: String(row[COL_FLAG - 1]).trim(),
    q: String(row[COL_Q - 1]).trim(),
    a: String(row[COL_A - 1]).trim(),
  }));

  const itemsQuiz = itemsAll.filter(x => x.flag === '1' && x.q && x.a);
  if (itemsQuiz.length === 0) throw new Error('FLAG=1 かつ C/D が空でない行がありません。');

  // ===== フォーム作成 =====
  const formTitle = `${ss.getName()}|二択クイズ`;
  const formDesc  = '適切な方を選んでください。';
  const form = FormApp.create(formTitle)
    .setDescription(formDesc)
    .setIsQuiz(true)
    .setShuffleQuestions(!!SHUFFLE_QUESTIONS); // 設問順はフォーム機能でランダム化

  // =====(任意)設問自体も事前に並び替えたい場合のシャッフル =====
  const quizArray = itemsQuiz.slice();
  if (SHUFFLE_QUESTIONS) {
    shuffleInPlace(quizArray);
  }

  // ===== 設問追加(選択肢をコードでシャッフル)=====
  quizArray.forEach(item => {
    const nextIdx = (item.rowIndex0 + 1) % nAll;
    let wrong = itemsAll[nextIdx].a || '';
    if (!wrong || wrong === item.a) wrong = itemsAll[0].a || '(ダミー)';

    let choices = [
      { text: item.a,   correct: true  }, // 正解
      { text: wrong,    correct: false }, // 誤答(次の行D)
    ];

    if (SHUFFLE_CHOICES) shuffleInPlace(choices);

    const mc = form.addMultipleChoiceItem();
    mc.setTitle(item.q)
      .setChoices(choices.map(c => mc.createChoice(c.text, c.correct)))
      .setRequired(true);
  });

  // ===== 同じフォルダへ移動 =====
  const ssFile = DriveApp.getFileById(ss.getId());
  const parents = ssFile.getParents();
  if (parents.hasNext()) {
    const parent = parents.next();
    const formFile = DriveApp.getFileById(form.getId());
    parent.addFile(formFile);
    try { DriveApp.getRootFolder().removeFile(formFile); } catch (e) {}
  }

  Logger.log('編集URL: ' + form.getEditUrl());
  Logger.log('回答URL: ' + form.getPublishedUrl());

  // --- ユーティリティ:Fisher–Yates シャッフル ---
  function shuffleInPlace(arr) {
    for (let i = arr.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      const tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;
    }
    return arr;
  }
}

操作方法

目次

0) 事前準備(シート構成)

  • 行1に見出し
    • A: No(任意)
    • B: FLAG … 出題する行は 1、それ以外は空/0
    • C: 問題(赤)
    • D: 正解(青)
  • 行2以降にデータを入力

1) スクリプトを貼り付け

  1. スプレッドシートを開く → メニュー 拡張機能 → Apps Script
  2. 新規プロジェクトに、提示の関数
    createTwoChoiceFormFromActiveSheet_ShuffleInCode()
    を貼り付けて保存

2) 権限付与と実行

  1. ▶️ボタンで関数を実行(初回のみ権限許可ダイアログが出ます)
  2. 実行が終わると、ログ(表示 → ログ)に
    • 編集URL
    • 回答URL
      が表示されます

3) フォームの動作仕様

  • 出題対象B=1 の行のみ
  • 誤答:各行の次の行の D(最終行は2行目のD)
  • 選択肢の順番コードでランダム(Fisher–Yates)
  • 設問の順番:フォーム側の機能でランダム化setShuffleQuestions(true)

4) 保存場所

  • 生成されたフォームは、既定ではマイドライブ直下に作成されますが、スクリプトが元スプレッドシートと同じフォルダへ移動します。

5) よくある質問

  • Q. B=1が1件だけだと?
    誤答の取得に次行のDを使うため、最低2件の出題行(B=1)があると自然です。
  • Q. 選択肢シャッフルをフォーム側のUIでONにする必要は?
    不要です。コードでシャッフルしています。
  • Q. 設問の順番は固定にしたい
    const SHUFFLE_QUESTIONS = false に変更してください。
  • Q. 3択/4択にしたい
    nextIdx+1, +2, +3 と増やして複数誤答を作り、choices 配列を拡張すれば対応できます。
よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

GoodMorning!

デジタルの海原を冒険しながら、美食の宝を探し求める探検家です。テクノロジーの世界を舞台に、新しい発見を求めて、キーボードの海を横断。そして、実世界では、隅々まで足を運んで、舌鼓を打つ価値のある美味しいお店を見つけ出します。

私の使命は、小さなITの豆知識から始まり、心を満たすグルメスポットの紹介まで、あなたの日常にちょっとしたスパイスを加えること。画面の向こう側から、気軽に楽しめる話題を届けたいのです。ここでは、私が「これは!」と思った技術的な小話や、舌の記憶に残るような食べ物屋さんを紹介していきます。

このWebサイトは、ITとグルメ、二つの世界を融合させた、まさにデジタルと現実の融合点。ふらっと立ち寄って、新たな発見や、ほっこりするような話題で一息ついていただけたら幸いです。知識の海を冒険し、味覚の旅を楽しみましょう。毎日を少しだけ特別なものに変える、そんな情報をお届けします。

GoodMorning!

I am an explorer who ventures across the digital sea in search of gastronomic treasures. In the world of technology, I traverse the sea of keyboards in search of new discoveries. And in the real world, I visit every nook and cranny to find a delicious restaurant worth tantalizing your taste buds.

My mission is to add a little spice to your everyday life, starting with little IT tidbits and ending with foodie spots that fill your heart. I want to bring you topics that you can easily enjoy from the other side of the screen. Here, I'm going to share with you some of the technical tidbits and I will introduce small technical stories and food shops that will leave a lasting impression on your taste buds.

This Web site is truly a fusion point of digital and reality, combining the two worlds of IT and gourmet. I hope you will stop by and take a breather with new discoveries and dusty topics. Come explore the sea of knowledge and enjoy a journey of taste. I will bring you the information that will change your everyday life into something a little more special.

目次