如何在 Google Apps 脚本中使用带有 .createChoice 的 for 循环从 sheet 创建测验?

How to use a for loop with .createChoice in Google Apps Script to create a quiz from a sheet?

我正在使用 Google Apps 脚本从 Sheet 生成 Google 表单。问题在行中,问题选择在列中。

如果需要,这里是 link to the Google sheet

使用 .setChoiceValues(values)

时很简单
if (questionType == 'CHOICE') {
  var choicesForQuestion = [];
  for (var j = 4; j < numberColumns; j++)
    if (data[i][j] != "")
      choicesForQuestion.push(data[i][j]);

  form.addMultipleChoiceItem()
    .setChoiceValues(choicesForQuestion);
}

但是,当我尝试使用 .createChoice(value, isCorrect) 时,参数要求 value 是字符串,isCorrect 是布尔值。

没有循环的示例如下所示:

  var item = FormApp.getActiveForm().addCheckboxItem();
  item.setTitle(data[3][1]);
  // Set options and correct answers
  item.setChoices([
    item.createChoice("chocolate", true),
    item.createChoice("vanilla", true),
    item.createChoice("rum raisin", false),
    item.createChoice("strawberry", true),
    item.createChoice("mint", false)
  ]);

我不知道如何添加循环。阅读其他帖子后,我尝试了以下方法:

if (questionType == 'CHOICE') {
  var questionInfo = [];
  for (var j = optionsCol; j < maxOptions + 1; j++)
    if (data[i][j] != "")
      questionInfo.push( form.createChoice(data[i][j], data[i][j + maxOptions]) );

    form.addMultipleChoiceItem()
      .setChoices(questionInfo);
  }

optionsCol是第一列问题选项 maxOptions 是 sheet 允许的选项数量(当前为 5)。 isCorrect 信息在右侧 5 列。

但是,这不起作用,因为数组 questionsInfo 是空的。

最好的方法是什么?

您的问题可能与您引用的方法有关--Form#createChoice--不存在。您需要通过首先创建项目来调用 MultipleChoiceItem#createChoice

/**
 * @param {Form} formObj the Google Form Quiz being created
 * @param {any[]} data a 1-D array of data for configuring a multiple-choice quiz question
 * @param {number} index The index into `data` that specifies the first choice
 * @param {number} numChoices The maximum possible number of choices for the new item
 */ 
function addMCItemToForm_(formObj, data, index, numChoices) {
  if (!formObj || !data || !Array.isArray(data)
      || Array.isArray(data[0]) || data.length < (index + 2 * numChoices))
  {
    console.error({message: "Bad args given", hasForm: !!formObj, info: data,
        optionIndex: index, numChoices: numChoices});
    throw new Error("Bad arguments given to `addMCItemToForm_` (view on StackDriver)");
  }
  const title = data[1];

  // Shallow-copy the desired half-open interval [index, index + numChoices).
  const choices = data.slice(index, index + numChoices);
  // Shallow-copy the associated true/false data.
  const correctness = data.slice(index + numChoices, index + 2 * numChoices);
  const hasAtLeastOneChoice = choices.some(function (c, i) {
    return (c && typeof correctness[i] === 'boolean');
  });
  if (hasAtLeastOneChoice) {
    const mc = formObj.addMultipleChoiceItem().setTitle(title);

    // Remove empty/unspecified choices.
    while (choices[choices.length - 1] === "") {
      choices.pop();
    }
    // Convert to choices for this specific MultipleChoiceItem.
    mc.setChoices(choices.map(function (choice, i) {
      return mc.createChoice(choice, correctness[i]);
    });
  } else {
    console.warn({message: "Skipped bad mc-item inputs", config: data, 
        choices: choices, correctness: correctness});
  }
}

您将按照其 JSDoc 的描述使用上述函数 - 向其传递一个 Google 表单对象实例以在其中创建测验项目、问题详细信息的数组以及位置的描述详细信息数组中的选择信息。例如:

function foo() {
  const form = FormApp.openById("some id");
  const data = SpreadsheetApp.getActive().getSheetByName("Form Initializer")
    .getSheetValues(/*row*/, /*col*/, /*numRows*/, /*numCols*/);

  data.forEach(function (row) {
    var qType = row[0];
    ...
    if (qType === "CHOICE") {
      addMCItemToForm_(form, row, optionColumn, numOptions);
    } else if (qType === ...
    ...
}

参考资料

我确信上面的答案非常好并且有效,但我只是一个初学者,需要一个更明显(单调)的方法。我正在从 spreadsheet 生成一个表格。问题类型可以包括:简答(文本项)、长答(段落)、下拉(列表项)、多项选择、网格项和复选框问题,以及部分。

我必须能够随机化分布sheet 的输入以进行多项选择,并对下拉菜单的输入进行排序。我现在只允许一个正确答案。

传播的题材搭建区栏目sheet分别为:题型、题型、是否必填、是否有分、提示、答对、无限选择等栏目。

qShtArr:整个sheet的getDataRange corrAnsCol:在正确答案的列上方的索引 begChoiceCol:第一列上面的索引,有 choices

我希望这对其他技术水平较低的编码人员有所帮助。

/**
 *  Build array of choices. One may be identified as correct.
 *  I have not tried to handle multiple correct answers.
 */
function createChoices(make, qShtArr, r, action) {
//  console.log('Begin createChoices - r: ', r);
  let retObj = {}, choiceArr = [], corrArr = [], aChoice, numCol, hasCorr;

  numCol = qShtArr[r].length - 1;   // arrays start at zero
  if ((qShtArr[r][corrAnsCol] != '') && (qShtArr[r][corrAnsCol] != null))  {
    hasCorr = true;
    choiceArr.push([qShtArr[r][corrAnsCol], true]);
    for (let c = begChoiceCol ; c < numCol ; c++) {
      aChoice = qShtArr[r][c];
      if ((aChoice != '') && (aChoice != null)) {         /* skip all blank elements  */
        choiceArr.push([aChoice, false]);
      }
    }  //end for loop for multiple choice options
  }    else    {
    hasCorr = false;
    for (let c = begChoiceCol ; c < numCol ; c++) {
      aChoice = qShtArr[r][c];
      if ((aChoice != '') && (aChoice != null)) {         /* skip all blank elements  */
        choiceArr.push(aChoice);
      }
    }  //end for loop for multiple choice options
  }
  
  if (action == 'random')
    choiceArr = shuffleArrayOrder(choiceArr); 
  if (action == 'sort')
    choiceArr.sort();
  console.log('choiceArr: ', JSON.stringify(choiceArr) );
    
  let choices = [], correctArr = []  ;
  if (hasCorr)  {
    for ( let i = 0 ; i < choiceArr.length ; i++ ) {
      choices.push(choiceArr[i][0]);
//      console.log('choices: ', JSON.stringify(choices) );
      correctArr.push(choiceArr[i][1]);
//      console.log('correctArr: ', JSON.stringify(correctArr) );
    } 
    make.setChoices(choices.map(function (choice, i) {
      return make.createChoice(choice, correctArr[i]);
    }));
  }  else  {                     // no correct answer
    if (action == 'columns' )  {
       make.setColumns(choiceArr);
    }   else   {
      make.setChoices(choiceArr.map(function (choice, i) {
        return make.createChoice(choice);
      }));
    }
  }
}