Как использовать цикл for с.createChoice в Google Apps Script, чтобы создать тест из листа?

Я использую Google Apps Script для создания форм Google из листа. Вопросы в строках, а вопросы в столбцах.

Вот ссылка на Google лист, если это необходимо.

Это простая задача при использовании .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 сколько опций разрешено листом (в настоящее время 5). Правильная информация - это 5 столбцов справа.

Тем не менее, это не работает, потому что массив questionsInfo пустой.

Каков наилучший способ сделать это?

2 ответа

Возможно, ваша проблема связана с методом, на который вы ссылаетесь 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 Form для создания элемента викторины, массив деталей для вопроса и описание местоположения информации выбора в массиве деталей. Например:

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 === ...
    ...
}

Рекомендации

  • Array#slice
  • Array#forEach
  • Array#map
  • Array#some

Я уверен, что приведенный выше ответ очень хорош и работает, но я только новичок, и мне нужен более очевидный (трудоемкий) метод. Я создаю форму из электронной таблицы. Типы вопросов могут включать в себя: краткий ответ (текстовый элемент), длинный ответ (абзац), раскрывающийся список (элемент списка), вопросы с множественным выбором, элемент сетки и флажки, а также разделы.

Мне нужно было иметь возможность рандомизировать ввод из электронной таблицы для множественного выбора и сортировать ввод для раскрывающихся списков. Сейчас я даю только один правильный ответ.

Столбцы в области построения вопроса электронной таблицы: тип вопроса, вопрос, требуется ли он, есть ли в нем баллы, подсказка, правильный ответ и столбцы с неограниченным выбором.

qShtArr: getDataRange всего листа corrAnsCol: index в верхнем столбце с правильным ответом beginChoiceCol: index в первом столбце выше с вариантами выбора

Я надеюсь, что это поможет другим менее опытным программистам.

      /**
 *  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);
      }));
    }
  }
}
Другие вопросы по тегам