web-dev-qa-db-ja.com

スプレッドシートの列からGoogleフォームの「リストから選択」オプションを動的に更新します

リストから選択」という質問を作成するGoogleフォームを設定しようとしています。各オプションは、特定の列の行から取得されます。

このコード を試しましたが、まったく機能しませんでした。

私がこれまでに持っているコードは以下の通りです。特定の列(この場合は列の最後の行)の1行のみのデータを使用して、目的のフォームの質問を作成できます。

選択した各行を1つの質問オプションのみに割り当てる方法について正しい方向を示してくれる人がいれば。また、これらがスプレッドシートが更新されるたびに質問オプションを動的に更新する何らかの方法である場合。

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...
       ])
}
5
Method

この文:

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

1つの値のみを取得します。列のすべての値が必要だと思うので、 getValues() (最後に「s」)メソッドを使用して、値の2次元配列を取得します。そして、numRowsパラメーター(取得する行数)をlr変数に変更します。また、おそらく2行目から始めたいと思います。構文は次のとおりです。

_getRange(row, column, numRows, numColumns)
_
  • row-範囲の開始行を整数にします
  • column-範囲の開始列を整数にします
  • numRows-返す行数を整数にします
  • numColumns-返す列の数を整数にします

したがって、パラメータは次のように設定する必要があります。

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

スプレッドシートの1行目に見出し名がある場合は、アイテムリストに見出しを含めたくない場合があります。そのため、行2から開始するために、最初のパラメーターが数値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)
};
_
3
Alan Wells

これが役立つかどうかはわかりませんが、この操作を自分でコーディングするよりも簡単な方法があります。別のスプレッドシートの行からの情報に基づいて、「リストから選択」の質問のフィールドに自動入力するFormRangerと呼ばれるGoogleフォームアドオンがあります。フォームのアドオンメニューに移動し、新しいアドオンを追加することでインストールできます。

FormRangerの説明へのリンクは次のとおりです。このドキュメントにもチュートリアルがあります。

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

2
krishnab

これには遅すぎないことを願っていますが、質問に記載されているソリューションを機能させることができました。すでに作成されているフォームを更新するため、新しいオプションを作成する必要はありません。この。また、 Allnatural および ChrsF on 元の投稿 で表示されるコードを変更して、名前付き範囲(または通常の範囲)を受け入れるようにしました。したがって、スプレッドシートに必要なシートの数を減らすことができます。

このスクリプトは、オプションを指定してスプレッドシートに配置する必要があります。これにより、スクリプトを変更するたびに、または設定された間隔で実行できます。

//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」関数を実行するトリガーを設定できます。メニューボタンを使用してオプションを手動で更新する必要はありません。

私はかなり前からこの解決策を探していましたが、見つけてよかったです。それがあなたにも役立つことを願っています。

2
Fogolin

上記の回答の関数を編集して、シートとフォームの両方で機能するようにしました。

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からシートとフォームのIDを見つけましたが、ListItem IDの代わりに、提供されたコードを使用しました ここ

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