【问题标题】:Dynamically update Google Form 'Choose from list' options from column in Spreadsheet从电子表格的列中动态更新 Google 表单“从列表中选择”选项
【发布时间】:2015-05-22 04:07:22
【问题描述】:

我正在尝试设置一个 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...
       ])
}

【问题讨论】:

    标签: google-apps-script google-sheets google-forms


    【解决方案1】:

    此声明:

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

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

    getRange(row, column, numRows, numColumns)
    
    • row - 整数范围的起始行
    • column - 整数范围的起始列
    • numRows - 要返回的行数整数
    • numColumns - 要返回的整数列数

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

    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)
    };
    

    【讨论】:

    • 谢谢@SandyGood。 getValues & getRange 的解释现在对我来说更有意义了。您发布的最后一段代码将放在哪里?我试着说:1.在我的spreadSheetGetterfillFormData函数之间,2.在我的fillFormData函数之后,3.在fillFormData函数内(就在变量之后)。我不断收到错误 Missing ;声明之前。 (第 XX 行,文件“代码副本”) 用于以下行:newItem = "item.createChoice('" + thisValue "')";
    • 查看最后的更新答案。我不确定的唯一部分是字符串公式:newItem = "item.createChoice('" + thisValue + "')"; 最终将如何在数组内部格式化。我刚刚注意到我在那个字符串公式中也有一个错误。我漏掉了一个加号。
    • 太棒了! @SandyGood 那不再显示该错误。现在收到错误无法将数组转换为选择 []。 (第 34 行,文件“代码副本”) 用于代码 .setChoices(arrayOfItems)。我从行中删除了“”:newItem = item.createChoice('" + thisValue + "');,错误不再显示。它现在完美地填充了 setChoices 中的每个选项。剩下的唯一问题是每次脚本运行时都会在表单中创建一个新问题。有没有办法覆盖现有问题,或者删除所有问题然后运行现有脚本?
    • 您应该可以通过 ID 获取商品。 Link to Documentation请将答案标记为正确。
    • 抱歉忘了提及我将上述行编辑为newItem = item.createChoice(thisValue);,以便正确填充 setChoices 选项。我将查看文档,看看是否可以解决。感谢您的所有帮助!
    【解决方案2】:

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

    这里是 FormRanger 描述的链接。本文档中也有教程。

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

    【讨论】:

      【解决方案3】:

      我已经编辑了上面答案中的函数,可以在工作表和表单中工作:

      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 和 Form 的 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());
      }
      

      【讨论】:

      • 以此为基础,我有一个表单,现在可以填充自己的列表。另外我.concat() 一些预设值从不同的工作表到表单添加的值。我想找到一种在单选按钮 multipleChoice 输入中获取它的方法,因为我只有几个项目。目前,这工作得很好。我发现我必须将docID 声明为空,然后仅在numRows &gt; 1 时运行var docID 分配,否则它会将我的表头拉到第1 行。(我还必须重命名docID,因为它根本不是文档ID) .这对创建我的第一个谷歌表单非常有帮助。
      【解决方案4】:

      希望我为此还不算太晚,但我设法让问题中提到的解决方案起作用,这似乎是一个更好的选择,因为它更新了已经构建的表单,无需创建新表单或为此的新选择。我还修改了AllnaturalChrsFthe 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”功能,然后就不需要使用菜单按钮手动更新选项了。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-06-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-28
        • 2018-02-17
        • 2018-09-15
        • 1970-01-01
        相关资源
        最近更新 更多