Как использовать цикл 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);
}));
}
}
}