質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.03%

【GAS】指定したセクションのGoogleフォームに質問を追加する事なく、選択肢となる質問の値のみ常に最新にしたい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 5,071

TS8332

score 11

【やりたいこと】 
Googleスプレッドシートから取得したセルの値を元に、Googleフォームの質問項目となる選択肢に追加させたいと考えております。
以下、構文ではGoogleフォームに対して、スプレッドシートから項目を取得後、新たに質問を追加させる事は出来ました。
しかし、これで完成という訳ではなく、いくつか解決させたい問題があります。 解決させたい問題については、以下構文最後に付け加えさせていただきます。 なお、以下GoogleAppScriptの構文はスプレッドシート内のスクリプトエディタにて実行させております。

【参考コード】

function getCategory() {
  var mspid = "スプレッドシートのファイルID"; //スプレッドシートのID
  var ss = SpreadsheetApp.openById(mspid);
  var sheets = ss.getSheets();
  var mst = sheets[0];

  var dt = mst.getSheetValues(startRow, startColumn, numRows, numColumns);

  var frmid = "フォームのファイルID"; //フォームのID
  var frm = FormApp.openById(frmid);
  var qui = frm.addListItem()
  .setTitle('ラベル名');

  var choices = []
  for (var i = 0; i < dt.length; i++){
    choices.push(qui.createChoice(dt[i][0]));
  }
  qui.setChoices(choices);
}

【解決させたい問題】
1.スプレッドシートより参照する質問の値は、毎日変化する為、トリガーを毎日1時に実行させる事によって、Googleフォームへと表示される質問の値は常に最新の状態へと切り替えたいと考えております。
しかし、上記構文をトリガーによって毎日実行すると、当然ながらGoogleフォームへと表示される質問の値は変わりますが、古い質問の選択肢は残ったままになって、最新の質問だけがトリガーを実行される度、無限に追加される事になってしまいます。

以下の選択肢となる値が、毎日変化してスプレッドシートの同セル内へと表示されている状態となります。
トリガーを実行1回目→選択肢 a1 a2 a3 a4 a5 
トリガーを実行2回目→選択肢 b1 b2 b3 b4 b5
トリガーを実行3回目→選択肢 c1 c2 c3 c4 c5
トリガーを実行4回目→選択肢 d1 d2 d3 d4 d5

質問が追加される事なく、常に最新の値をGoogleスプレッドシートから取得してGoogleフォームの質問の選択肢の欄へと追加させたいのが、解決へと至りたい問題その1となります。


2.セクションが複数あった場合、上記の構文を実行すると、質問は一番下位のセクションへと追加される事になりますが、指定のセクションへと追加させる方法を実現させたいと考えております。
Googleフォームのセクションが4つあったとしまして、質問を追加させたいセクションは2つめのセクションが解決へと至りたい問題その2となります。


長文での質問となって、たいへん実現したい事がわかりにくい事かもしれませんが、ご教示いただければ幸いです。  
宜しくお願いいたします。
また、まずは上記構文を自分と同じくスプレッドシートのスクリプトエディタへと書き込んで実際に実行してみると質問の意味を分かっていただけるかもしれません。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

問題1は、下記のコードでフォームの既存の設問に対し、全ての選択肢を上書きすることができます。設問の新規追加をして最後尾に設問が追加されるわけではないので、フォームの必要な場所に設問を設置しておけばよいことになります(この方法で問題2は解決)

function replaceCategory() {
  var mspid = "スプレッドシートのファイルID"; //スプレッドシートのID
  var ss = SpreadsheetApp.openById(mspid);
  var sheets = ss.getSheets();
  var mst = sheets[0];

  var dt = mst.getSheetValues(startRow, startColumn, numRows, numColumns);

  var frmid = "フォームのファイルID"; //フォームのID
  var frm = FormApp.openById(frmid);

  var listItem =frm.getItems(FormApp.ItemType.LIST);//既存の全LISTを取得

  for (var i0 = 0; i0 < listItem.length; i0++){                                                                                          
    if (listItem[i0].getTitle()=='ラベル名'){//タイトルが一致するLISTを選択                                           
      var qui = listItem[i0].asListItem()//変数quiにobjectを格納
      break;
    }
  }

  if (i0 == listItem.length){//forloopが完走してしまった場合
      Logger.log("指定したタイトルのlistItemが存在しない")
      return
  }

  var choices = []

  for (var i = 0; i < dt.length; i++){
    choices.push(qui.createChoice(dt[i][0]));
  }
  qui.setChoices(choices)
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/01/26 11:34

    御回答いただきましてありがとうございます。
    こちらでも同様に実行しました処、うまく動作する事が確認とれました。

    キャンセル

0

問題2について、もし新規の設問を追加してから指定したセクション(PAGE_BREAK)に移動したい場合の例もあげておきます。INDEXとはform上の出現順番です。IDとはアイテムユニークの番号です。移動実行前と実行後のログを吐き出すfunctionもつけていますので、関係を確認してみてください。

function move_question_before_1stSection() {

  var frmid = "フォームのファイルID"; //フォームのID
  var frm = FormApp.openById(frmid);

  getCategory()//新規の設問を追加(TS8332さんのfunctionをコール)  

  Logger.log("【移動実行前のItemの状態】");
    question_Get_Id()
  Logger.log("-------------------------");

  var Items =frm.getItems();//既存の全itemを取得
  var qui = Items[Items.length-1]//変数quiに最終出現設問のobjectを格納
  var quiID = qui.getId();//指定した設問のIDを取得
  var quiItem = frm.getItemById(quiID);
  var quiIndex = qui.asListItem().getIndex()

  var pageBreak =frm.getItems(FormApp.ItemType.PAGE_BREAK);//既存の全PAGE_BREAKを取得

  if (pageBreak.length > 0){
    var pageIndex = pageBreak[0].asPageBreakItem().getIndex();//最初(=[0])のPAGE_BREAKのIndexを取得
    frm.moveItem(quiItem,pageIndex);//最初のPAGE_BREAKのIndex位置(=直前)に設問を移動

    //または下記でもよい
    //frm.moveItem(quiIndex,pageIndex);//最初のPAGE_BREAKのIndex位置(=直前)に設問を移動
  }
  Logger.log("【移動実行後のItemの状態】");
   question_Get_Id()
}

function question_Get_Id(){//INDEXやIDをログに吐き出す

  var form = "フォームのファイルID"; //フォームのID
  var items = form.getItems();
  for (var i = 0; i < items.length; i++) { //回答内容を取得
    var item = items[i];

    Logger.log("Index:" + i  + " " + item.getTitle() + " -> ID: " +item.getId().toString() + " / " +item.getType());
  }
}

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.03%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる