【GAS】ドロップダウンで選択した値をもとにページ遷移する方法

GAS

どうもcoto.です。
今回は前回の続きで、ドロップダウンで選択した値を取得して、その情報をもとに新しいHTMLページに遷移する方法です。

でちょっと条件があって、こういうことをしたい場合にはPostメソッド(doPost関数)を使ってやるのが常套手段らしいのですが、諸事情により今回はdoPost関数なしで実行します。

前回やったこと

前回はスプレッドシート内のデータを使ってWebアプリ上にドロップダウンを設置しました。
その方法は↓こちら

今回やりたいこと

今回は、

アプリを開く→ドロップダウンから顧客を選ぶ→決定ボタンを押す→選んだ顧客の個人ページが開く
ということをやりたいです。

アプリの挙動

こんな感じ。

必要なデータとコード

今回やりたいことをする上で最低限必要になるのは、

・ドロップダウンと個人ページの内容を作るためのデータ(スプレッドシート)
・コードを書いておくgsファイル(コード.gs)
・ドロップダウンを置いておくページ用のHTML(index.html)
・ページ遷移先の個人ページ用HTML(personal.html)

の4つです。

スプレッドシートの内容

ドロップダウンの元になるリストです。B1,C1セルの値については解説の項で。

用意する顧客リスト

GAS(gs)側のコード

実際に使用する場合は20行目のスプレッドシートIDに使用環境のIDを入れてください。

//▼Webアプリを表示するための関数。pageで指定したhtmlに遷移。webアプリにアクセスしたときはまずindex.htmlを開く▼
function doGet(e) {
  let page = e.parameter.page;
  if (!page) {
    page = 'index';
  }
  var htmlOutput = HtmlService.createTemplateFromFile(page).evaluate();
  return htmlOutput
}

//▼html間でページ遷移するための関数▼
function getAppUrl() {
  return ScriptApp.getService().getUrl();
}


//--------------------------------------------------------------------------------------------------

//▼繰り返し使う値グローバル変数で宣言▼
const ss      = SpreadsheetApp.openById("●●●●●●●●●●●●●●●●");     //スプレッドシートIDを指定
const sheetDB = ss.getSheetByName("test");                   //シートtestを開く
const rowDB   = sheetDB.getLastRow();              //シートtestの最終行を取得
var   list    = sheetDB.getRange("B4:D"+rowDB).getValues();  //リストを取得

//▼ドロップダウンの中身になるデータを取得▼
function dropData(){
  //顧客データを返す
  return JSON.stringify(list);
}

//▼顧客呼出ボタンの挙動▼
function yobidashi(kokyakuID, name, tanto) {
    for (var i = 0; i < list.length; i++) {    //顧客リストの人数分処理を繰り返す
      if(list[i][0] == kokyakuID && list[i][1] == name && list[i][2] == tanto){  //ID、名前、担当者が一致する顧客の行番号を検索して取得
           var rowNo = i + 4 ; 
        break;
      }
    }    

    var url = ScriptApp.getService().getUrl();
    sheetDB.getRange("C1").setValue(rowNo);  //一致した行の番号を取得してスプレッドシートのC1セルに入れる

    return url;
}

index.htmlのコード

ドロップダウンを設置するページです。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <script type="text/javascript">  

  //ドロップダウンの一覧データを取得する
  google.script.run.withSuccessHandler(onSuccess).dropData();

  //▼取得したデータでドロップダウンを作る▼

   function onSuccess(list){   
      var data = JSON.parse(list);      //dataをJSONに変換
      var datalength = data.length;     //jsonの要素数を定義
  
      var html =  "";         //ドロップダウンのhtmlを作成
      html += "<select title='顧客を選択する' id='kokyakuSel'><option>顧客を選択して下さい</option>";
  
      //HTMLデータの生成
      for(var i = 0;i<datalength;i++){   //顧客を1人ずつプルダウンにいれていく。要素数分繰り返し、次が空白になったら脱出
       if(data[i] == ""){
          break;                         
         }
       html += "<option>" + data[i] + "</option>"
      }
  
       html += '</select>';
    
      //プルダウンメニューを設置する
       document.getElementById("drop").innerHTML = html;  //以下のbody内のdropにここで作ったhtmlを追記
    }

  </script>


  </head>
  <body>

      <!-- ドロップダウンを設置 -->
      <div id="drop">
      </div>

      <div>
      <input type="button" value="顧客呼出" onclick="callBtn()"/>
      </div>
      </form>


 <script>
  //▼顧客呼び出しボタンの動作制御▼
      function callBtn(){
          var kokyaku = document.getElementById("kokyakuSel").value;  //ドロップダウンのID(kokyakuSel)を指定して値を取得
          var ar = kokyaku.split(',');         //「顧客ID,氏名,担当」の一続きの文字列になってるのでカンマで配列に区切る

        if(kokyaku == "顧客を選択して下さい"){           //「顧客を選択して下さい」の時は何もしない
         }else{ 
            var kokyakuID   = ar[0];
            var name        = ar[1];
            var tanto       = ar[2];

          google.script.run.withSuccessHandler(Jump).yobidashi(kokyakuID, name, tanto);  //顧客情報を挿入関数に送り、成功したらJump()に返してもらう

         }
       }

    function Jump(url){
         window.top.location.href = url + '?page=personal';    //personalを開く(ここでは選択した顧客情報は渡していない)

       }

  </script>


  </body>
</html>

personal.htmlのコード

顧客の個人ページ(ドロップダウンで選択した値が反映されたページ)を作るためのHTMLです。

<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
  </head>
  <body>

   <? var rowNo = sheetDB.getRange("C1").getValue(); ?>
   <? var per   = sheetDB.getRange("B" + rowNo + ":D" + rowNo).getValues(); ?>

   <h1><?= per[0][1] ?>さんの個人ページ</h1>
   <p>ID:<?= per[0][0] ?></p>
   <p>担当者:<?= per[0][2] ?></p>


  </body>
</html>

解説

ドロップダウンの設置については前回の通りなので割愛します。(少し変えているところもあります。)

関数の実行順序としては、

アプリ起動
 ①index.html 開く
 ②コード.gs_dropData() (①の途中で行われる)
 ③index.html_onSuccess(list)
ドロップダウンで選択されてボタンが押される
 ④index.html_callBtn()
 ⑤コード.gs_yobidashi()
 ⑥index.html_Jump()
 ⑦personal.html 開く

という感じですね。

で、選択した顧客データをindex.htmlからpersonal.htmlにどう引き継ぐかですが、⑤のyobidashi()が実行されたときにスプレッドシートのC1セルに顧客の行番号(配列なので実際は行番号+1)を入力し、⑦で改めてその行番号を元に顧客を読み込む形にしています。B1セルはC1セルを消さないで!て書いてあるだけなのでプログラム上はなくても全く問題ありません。

単純にプログラムに顧客データを持たせておいて、とも考えたんですがデータ量が多く(E列以降にもっとたくさん項目があったり。)煩雑になりそうだったのでこのようにしています。

ドロップダウンから選択→呼び出し を同時に複数人が実行したらエラーが起きそうですが、アプリを数人で使用する場合は不便を感じるほどぶつかることはないと思います。

御託

紹介した例では数人の顧客ですが、実は本番環境では数百の物品リストだったので、1つ1つにhtmlを作るなんてことはできず。今回のようにHTMLのテンプレートを作っておいて、値を入れ込んでいく形にしました。

ドロップダウンに入るのが、いくつかの機能や決まったページのような増加が予想されるものではないなら、それぞれにあらかじめHTMLを作成しても良いかもしれませんね。

作りながら参考にしたサイトはどこもdoPostを使っていて、なかなかそれ以外の情報が得られなかったのでご紹介しました。

どなたかのお役にたてばうれしいです。

コメント