かずきち。の日記

サーバサイドエンジニアのつぶやき

【Googleフォーム】データを次のページに引き渡して、選択肢を変動させるアンケートを作成していく

Googleフォームとは?

GoogleフォームとはGoogle社が提供しているオンラインアンケートツールです。

www.google.com
引用:
https://www.google.com/intl/ja_jp/forms/about/

ここにアクセスすると簡単にウェブ上のアンケートを作成ができます。
今までウェブアンケートを作ったことがある方も多いでしょう。

Googleフォームの使い方・作り方 | アンケート回答記録をスプレッドシートで | BOXIL Magazine

作成自体は無料で誰でも作れますからね。
ただ凝った質問をするためには改造をしなくてはいけません。
「前の質問でいいえと答えた方に質問です」などの分岐だと思ってください。

人数制限や質問変動をさせるためにはプログラミングが必要

https://script.google.com/macros/library/d/1-PcGuUUH3zlj3vAtfeRQhUhlckGeh9i-jcaJlFEPSuVG00uuJxiwZO_U/7

まずデモからお見せします。
上記ページにアクセスして回答をしてみてください。

そうするとお弁当のジャンルを聞かれると具体的なお弁当内容を選択ができます。

洋食を選べば、スパゲッティ定食かハンバーグ定食。
和食を選べば、刺身定食か豚汁定食。

のように選択肢を変動ができます。
これは回答状況によってリアルタイム変動ができるメリットがあります。

<head>
  <!-- 外部ライブラリ類を読み込む -->
  <link rel="stylesheet" href="https://ssl.gstatic.com/docs/script/css/add-ons1.css">
  
  <style>
  /* ラベル用のCSS設定 */
  label {
      float: left;
      margin-right: 0.5em;
      color: black;
      font-size: 15px;
  }
  </style>

  <script type="text/javascript">
  //入力補完用データを入れる為のグローバル変数
  var kinokodb = "";
  
  //スプレッドシート側からデータを取得する
  google.script.run.withSuccessHandler(onSuccess).bunrui();
  
  //取得したデータでドロップダウンメニューを作って設置
  function onSuccess(data){
    var json = JSON.parse(data);
    var datalength = json.length;
    
    //ラベルを入れる
    var html = "<label>分類を選択:</label>";
  
    //selectタグの頭を入れる
    html += "<select title='プルダウンより選択' onchange='changeman()' id='kinosyu'><option>分類を選択して下さい</option>";
  
    //HTMLデータの生成
    for(var i = 0;i<datalength;i++){
      //空データの場合ループ脱出
      if(json[i] == ""){
        break;
      }
      
      //オプション項目を追加
      html += "<option>" + json[i] + "</option>"
    }
  
    //selectタグの下を入れる
    html += "</select><p>";
    
    //プルダウンメニューを設置する
    document.getElementById("bunrui").innerHTML = html;
  }
  
  //取得したデータでドロップダウンメニューを作って設置
  function onSuccess2(data){
    //display属性を一時的に変更
    document.getElementById("progress").style.display = "none"
    document.getElementById("pulldown").style.display = "block"
    
    //データを取得する
    var json = JSON.parse(data);
    var datalength = json.length;
    
    //kinokodbにも格納する
    kinokodb = json;
    
    //ラベルを入れる
    var html = "<option selected>お弁当を選択して下さい</option>"
    
    //HTMLデータの生成
    for(var i = 0;i<datalength;i++){
      //空データの場合ループ脱出
      if(json[i][0] == ""){
        break;
      }
      
      //オプション項目を追加
      html += "<option>" + json[i][1] + "</option>"
    }

    //プルダウンメニューを設置する
    document.getElementById("kinoko").innerHTML = html;
  }  
  
  //分類を変更したときに発火する
  function changeman(){
  
    //現在選択されてる分類を取得
    let bunrui = document.getElementById("kinosyu").value
    
    //分類を元にお弁当の種類をリビルド
    if(bunrui == "分類を選択して下さい"){
      //何もしない
    }else{
      //display属性を一時的に変更
      document.getElementById("progress").style.display = "block"
      document.getElementById("pulldown").style.display = "none"
      
      //データを取得する
      google.script.run.withSuccessHandler(onSuccess2).kinoko(bunrui);
    }
  }
  
  //お弁当を選択した場合に発火
  function kinokoman(){
    //現在選択されているお弁当を取得
    let kinopi = document.getElementById("kinoko").value
    
    //お弁当名を元に説明文を表示
    if(kinopi == "お弁当をを選択して下さい"){
      //何もしない
    }else{
      //お弁当の説明情報を探索
      for(var i = 0;i<kinokodb.length;i++){
        if(kinokodb[i][1] == kinopi){
          //アラート表示
          alert(kinokodb[i][2]);
          break;
        }
      }
    }
  }
  
  
  </script>
</head>

<!-- 1個目のプルダウン設置場所 -->
<div id="bunrui">
  <img border="0" src="https://officeforest.org/wp/library/ProgressSpinner.gif" width="20" height="20">
</div>

<!-- ドロップダウンメニュー設置場所 -->
<div id="selectkinoko">
  <div id="pulldown">
    <label>お弁当を選択:</label>
    <select title='プルダウンより選択' onchange='kinokoman()' id="kinoko">
      <option selected>お弁当を選択して下さい</option>
    </select>
  </div>
  
  <div id="progress" style="display:none">
    <img border="0" src="https://officeforest.org/wp/library/ProgressSpinner.gif" width="20" height="20">
  </div>
  
</div>

まずはお弁当の注文を受け付けるインターフェースを作っていきます。
別に何も仕掛けはありません。
単純になんのお弁当を注文したい?というオーダーシートです。
ここから利用者の回答によって、選択肢を分岐させる仕組みをつくっていきます。

doGet(e)でスクリプトを書いていきます。
(e)はeventの頭文字を取ってeが使われています。
doPost(e)もよく聞くと思います。

doGetメソッドは、パラメータ情報をURLにのせてサーブレットへ投げる
doPostメソッドは、パラメータ情報をformタグに含めサーブレットへ投げる

doGetメソッドを使用するので、GETはパラメータとしてURLクエリとしてデータを引き渡します。
意味わからんこと言ってるぞという人安心してください。
早い話がGoogleの検索結果のページと変わりません。

//このスプレッドシートのID
var sheetid = "********************";

//ウェブアプリケーションを表示する
function doGet(e) {
  var html = HtmlService.createHtmlOutputFromFile('index2')
             .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
  return html;
}

//1個目のプルダウン用
function bunrui2(){
  //シートを取得
  var ss = SpreadsheetApp.openById(sheetid)
  var list = ss.getSheetByName("種類").getRange("A2:A").getValues();
  
  //取得データを返す
  return JSON.stringify(list);
}
 
//抽出用プルダウン用
function kinoko2(bunrui){
  //シートを取得
  var ss = SpreadsheetApp.openById(sheetid)
  var list = ss.getSheetByName("お弁当名").getRange("A2:C").getValues();
  
  //配列を用意
  var array = [];
  
  //bunruiに基づきフィルタした値を配列にpush
  for(var i = 0;i<list.length;i++){
    //分類に合致したらpush
    if(list[i][0] == bunrui){
      array.push(list[i]);
    }
  }

  //取得データを返す
  return JSON.stringify(array);
 
}

ここのdoGet関数で次のページにデータを引き渡しています。
何言ってるかわからないかと思いますが、次に見るページにデータを引き渡しているのです。

データの引き渡しというと難しく聞こえる

インターネットは世界中のバケツリレーです。
次のページを見ようとすると世界中のコンピュータがバケツリレーでデータを返してくれています。
技術者の方は途中でデータがロスしないように念には念を入れて、データの配達を行います。

携帯電話から音声を相手の携帯電話に届ける
ウェブページを見ているパソコンに届ける

これ一定のルールに従って行っているのがインターネットです。
その間には電話回線だったり。ルーターだったり、いろいろな器具があります。
どれも途中でデータが消失しないための仕組みです。

データが損失することなんかあるのか?

データが損失することはあります。
早い話が荷物です。
海外旅行で自分の荷物が出てこないようなものです。

日本からアメリカにデータを取りに行って、 アメリカから日本にデータを持ち帰ってくるということがインターネットでやっていることで、

liginc.co.jp

よくインターネットをしていると、404エラーであったり、503エラーを聞くかと思います。
これは海外旅行で言う手荷物の紛失の種類を表しています。

ja.wikipedia.org

これをHTTPステータスコードと呼びます。

200番台は成功
300番台はリダイレクト
400番台はクライアントエラー
500番台はサーバーエラー

とルールが決まっています。
なので、その番号によってどこに原因があるのかわかるのです。

どうやって使うのか?

例えば自分のスマホが壊れて、「503などのエラーコードが返ってきた」とします。
その際に500番台だからサーバーエラーで自分の範疇外のトラブルだと判断ができます。
つまりは500番台なのに携帯ショップに文句を言いにいっても「うちの管轄外だ」と門前払いされます。
一方400番台のエラーを携帯ショップに持っていけば「うちに端末が悪いのかもしれない」と相手をしてもらえます。

番号を示すことはお医者さんに自分の症状を示すことと一緒

番号が返ってくるということはコンピュータが自身の問題を自己診断している。
エラーコードはコロナの自己診断キットのようなものです。

コロナの判定キットは線が出るかどうかで、自分の症状がわかります。
でもコンピュータの場合、症状で自身の行き先をうまく切り分ける仕組みが必要なのですね。
ここの切り分けが上手にできている→すなわち自動化できているということです。

自動ドアも自動車もここの切り分けがしっかり作り込まれているからこそ自動化が行えているのです。
プログラミングをするということは往々にして、何かを自動化することです。
でも時にはパソコンの電源が切れている、インターネットが不調だなんて時があります。
その時がパソコンで言う障害です。

プログラミングで1+1=2になることは当然です。
でもこれからコードを書く人にとって、1+1=0になってしまったときにどうしてこのような結果になってしまったか検証する力が必要です。

日本の学力試験は単発の思考能力を試す機会が多い

例えば、学生はこんな問題を見たときに「セ」の選択肢は1桁だから
0〜9が必ず入ると思ってしまう。
でも現実世界は10かもしれないし、20かもしれない。
だけれど、採点者を楽にする仕組み上マークシートという仕様になっている。

プログラムは誰が悪さをするかわからない心がけが必要で
コンピュータの厄介なとことはステークホルダーが大勢いることだ。
話がだいぶ逸れてしまったが、プログラム一つ取ったときにそのエラーが自分由来のものか、他人由来のものか判定できる能力は結構大事である。