从电子表格中的列动态更新 Google 表单 'Choose from list' 选项

Dynamically update Google Form 'Choose from list' options from column in Spreadsheet

我正在尝试设置一个 Google 表单,该表单将创建一个“从列表中选择”的问题,每个选项都是从特定列的行中提取的.

我试过this code,但完全没用。

我目前的代码如下。我能够使用特定列(在本例中为该列的最后一行)中仅一行的数据创建所需的表单问题。

如果有人能给我指出正确的方向,告诉我如何将每个选定的行仅分配给一个问题选项,请提供帮助。 此外,如果这些是每次更新电子表格时动态更新问题选项的某种方式。

var idColumn = 1; // ID of the selected column

//gets document ID from spreadsheet 
//(not 100% sure the role of all of these lines, have worked it out from other examples of code online)
function spreadSheetGetter() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var values = rows.getValues();
  var lr = rows.getLastRow();  

  var docId = sheet.getRange(lr,idColumn,1,1).getValue(); //gets the data from the last row in selected column

fillFormData(docId);
}


//fills for with document ID
function fillFormData(docId) {
var form = FormApp.openById('MY FORMS ID');
var item = form.addListItem();

item.setTitle('Select Existing Customer') //creates the choose from list question
     .setChoices([
         item.createChoice(docId), //data from row 1
         item.createChoice(docId) //data from row 2 etc...
       ])
}

这条语句:

var docId = sheet.getRange(lr,idColumn,1,1).getValue();

只得到一个值。我想你想要列中的所有值,所以使用 getValues() (最后是 's' )方法来获取二维值数组。并将 numRows 参数(要获取的行数)更改为 lr 变量。另外,您可能想从第 2 行开始。语法是:

getRange(row, column, numRows, numColumns)
  • row - 整数范围的起始行
  • column - 整数范围的起始列
  • numRows - 将行数整数为 return
  • numColumns - 将列数整数为 return

所以,参数需要这样设置:

var docId = sheet.getRange(2,idColumn,lr,1).getValues();

如果在电子表格中,第一行有标题名称,您可能不想在项目列表中包含标题。这就是为什么第一个参数设置为数字 2,从第 2 行开始。

然后,您需要处理二维数组中的数据,并创建一个采用 setChoices(choices) 方法所需格式的新数组,以便将每个值添加到列表。你需要一个编程循环。这将每次创建一个新的项目值数组,因此列中的当前值将更新到列表中。

var thisValue = "";
var arrayOfItems = [];
var newItem = "";

for (var i=0;i<docId.length;i++) {
  thisValue = docId[i][0];
  newItem = "item.createChoice('" + thisValue + "')";
  arrayOfItems.push(newItem);
};

完整的函数看起来像这样:

//fills item with document ID
function fillFormData(docId) {
  var form = FormApp.openById('MY FORMS ID');
  var item = form.addListItem();

  var thisValue = "";
  var arrayOfItems = [];
  var newItem = "";

  for (var i=0;i<docId.length;i++) {
    thisValue = docId[i][0];
    Logger.log('thisValue: ' + thisValue);
    newItem = item.createChoice(thisValue);
    arrayOfItems.push(newItem);
  };

  item.setTitle('Select Existing Customer') //creates the choose from list question
     .setChoices(arrayOfItems)
};

我不确定这是否对您有帮助,但是有一种比您自己编写此操作更简单的方法。有一个名为 FormRanger 的 google 表单插件,它将根据另一个电子表格的行中的信息自动填充 "Choose from List" 问题中的字段。您可以通过转到表单的附加组件菜单然后添加新的附加组件来安装它。

这里是link对FormRanger的描述。这个文档里也有教程。

https://docs.google.com/document/d/1qidnsrTShKU9kPnYz4nubHs2cK9yWnQ2z_XBoqgdIhs/edit

希望我还不算太晚,但我设法让问题中提到的解决方案起作用,这似乎是一个更好的选择,因为它更新了一个已经构建的表单,不需要创建一个新的或为此的新选项。我还修改了 Allnatural and ChrsF on the original post 提供的代码,以便它接受命名范围(或常规范围,就此而言),从而减少电子表格中需要的工作表数量。

您应该将此脚本与选项一起放在电子表格中,这样它可以 运行 无论您何时更改它或以设定的时间间隔:

//Here you set the options for the question on your form you want to dinamically change and which named range will populate it
var LIST_DATA = [{formFieldTitle:"Who's your tutor", namedRange:"reg_opcoes"}]

//Inserts a menu entry that allows you to run the function to update the options of the form
function onOpen(e){
  var menuEntries = [];
  menuEntries.push({name: "Update Lists", functionName: "updateLists"});
  SpreadsheetApp.getActiveSpreadsheet().addMenu("List Updater", menuEntries)
}

//The update function itself, it will run for as many options as you set in the LIST_DATA list
function updateLists() {
  var form = FormApp.openById('1Pl3i5Qr8Kq5C2UbBUqA0iZCsmaHXum5eWR1RfIaEL6g'); //Insert your form ID here
  var items = form.getItems();
  for (var i = 0; i < items.length; i += 1){
    for (var j = 0; j < LIST_DATA.length; j+=1) {
      var item = items[i]
      if (item.getTitle() === LIST_DATA[j].formFieldTitle){ //Here the titles of the questions are called
        updateListChoices(item.asListItem(), LIST_DATA[j].namedRange); //Here the range that populates que question with options is called
        break;
      }
    }
  }
}

//Function that actually gets the values from the range you defined
function updateListChoices(item, sheetName){
  var data = (SpreadsheetApp.getActiveSpreadsheet()
              /* 
                 If you want, you might change the option here to .getDataRange() and work with defined ranges.
                 For that, yoiu should also place a .getSheetName() before it, so that'll know of what interval you're talking about
              */
              .getRange(sheetName) 
              .getValues());
  var choices = [];
  for (var i = 0; i < data.length; i+=1){
    choices.push(item.createChoice(data[i][0]));
  }
  item.setChoices(choices);
}

在你让它工作后,你可以设置一个触发器来触发 运行 "updateLists" 函数在你的电子表格中所做的每一个更改,然后就不需要手动更新菜单按钮的选项.

我一直在寻找这个解决方案有一段时间了,我很高兴找到了它。希望对你也有帮助。

我已经编辑了上面答案中的函数,使其在 Sheet 和 Form:

中都有效
var sheetId = '<YOUR_SHEET_ID>';
var sheetName = 'sheet_1';
var column = 'C';
var formId = '<YOUR_FORM_ID>';
var listItemId = 12345678;

function spreadSheetGetter() {
  var sheet = SpreadsheetApp.openById(sheetId).getSheetByName(sheetName);
  var rows = sheet.getDataRange();
  var numRows = rows.getNumRows();
  var docId = sheet.getRange(sheetName+"!"+column+"2:"+column+numRows).getValues();
  fillFormData([].concat.apply([],docId));
}

function fillFormData(docId) {
  var form = FormApp.openById(formId);
  var item = form.getItemById(listItemId).asListItem();
  item.setChoiceValues(docId);
};

我从 URL 中找到了 Sheets 和表单的 ID,而不是 ListItem ID,我使用了提供的代码 here:

var form = FormApp.getActiveForm();
var items = form.getItems();
for (var i in items) { 
  Logger.log(items[i].getTitle() + ': ' + items[i].getId());
}