るぴブロ

備忘録とかです(*'ω'*)

スプレッドシートをWebアプリから参照する 

こんばんは。
何回かにわけて投稿してきたGoogle Form備忘録ですが、ようやく最終回です。

実現したい事

  • Google Formで時間帯予約フォームを作成
  • 予約データをスプレッドシートと連携
  • 各時間帯には上限があり残席数を知らせたい(予約できなくする等の制限は不要)
  • 登録時にユーザーIDを入力してもらい予約のキャンセル/変更ができる
  • スプレッドシートのデータを検索し現在の登録状況を検索/表示する事ができる
  • ユーザーはスマホWebブラウザからのアクセスのみ(ガラケは無視でおk)
  • 尚、ユーザーはGoogleアカウントでログインしない事とする(震

 

最後の機能はGoogle Formに登録した回答内容をどうにかして確認する術を探すというものですw

基本的にこちらもGoogleアカウントでログインしていただければ簡単に確認する事ができますのでこんな面倒な方法は不要かと思いまが、色々失敗してスプレッドシートをWebアプリケーションから呼び出す仕様になったので、そこはは別の用途で使えそうですね。

はじめは…

スプレッドシートにデータを保存しているので、単純に確認用のスプレッドシートを準備してユーザーの方にIDを入力→GASで必要事項を表示するといった仕様でした。

 

f:id:rupic:20190307235617p:plain

とりあえずこんな感じのTHEエクセルチックなシートを準備して、ユーザーIDを入力し図形描画で作った検索ボタン(GASを割付)をクリックしたらスプレッドシートの中身を検索というものを作成してみました。

なんとなくGASの使い方にも慣れ10分くらいで完成し、動作確認もバッチリです😊

www.atmarkit.co.jp

 

しかし…

上記で作成したスプレッドシートを公開してユーザーの方にページにアクセスしてもらうという算段でしたが、Googleアカウントでログインしない時点でスプレッドシートは読み取り専用となり、ユーザーには何やら検索できそうな画面を見るだけという謎仕様のものが見えるのみとなってしまいましたwwwwww

 

スプレッドシートをWebアプリから参照する 

もうダメかと思ってネットサーフィンしてたらこんな記事を見つけました。

qiita.com

 

どうやらスプレッドシートをDBの様に見立てて、Webアプリから参照する事ができる様です。

developers.google.com

 

公式によるとWebアプリとして公開するには以下の条件を満たしている必要があるらしいです。

  • doGet() または doPost() 関数を実装する
  • HTML service HtmlOutput オブジェクト または Content service TextOutput オブジェクト を返す

作ってみよう

とりあえず、gsファイルとHTML、javascriptを書きます。

index.gs

function getData(userid,week) {
  
  const fw_id = "***スプレッドシートのIDを入力***";
  const sw_id = "***スプレッドシートのIDを入力***";
  
  var spreadsheet;
  if(week === '1'){
    spreadsheet = SpreadsheetApp.openById(fw_id);
  } else {
    spreadsheet = SpreadsheetApp.openById(sw_id);
  }  
  
  var sheet = spreadsheet.getActiveSheet();
  
  const inventory = sheet.getDataRange().getValues()
  .filter(function(row){return row[1] === userid})
  .map(function(e){
    const columns = [0,1,2,3,4,5,6,7,8,9,10,11],row = [];
    for(var i = 0; i < columns.length; i++) row.push(e[columns[i]]);
    return row;
    
  });
  
  if(inventory.length === 0){
    return inventory;
  }
  
  return inventory[inventory.length -1];
}

function doGet(e) {
  var data = getData(e.parameter.name,e.parameter.id);
  return ContentService.createTextOutput(JSON.stringify(data, null, 2))
  .setMimeType(ContentService.MimeType.JSON);
}

index.html

<!DOCTYPE html>
<html lang="en">

    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
        <title>バス予約確認</title>
        <link rel="icon" href="img/fav.png" type="image/x-icon">
    
        <!-- Bootstrap -->
        <link href="css/bootstrap.min.css" rel="stylesheet">
    
        <!-- main css -->
        <link href="css/style.css" rel="stylesheet">      
    
        <!-- modernizr -->
        <script src="js/modernizr.js"></script>           

    </head>
    <body>        
        <div class="container main-container">
            <div class="header">
                <a class="h2" href="#" onclick="location.reload();">バス予約確認</a>
            </div>
            <br>            
            <div class="row col-md-12">
                <div class="input-contact col-md-4" style="width: 200px">
                    <input type="text" id="jcode" placeholder="ユーザーIDを入力">
                    <br>
                    <div class="btn-group" data-toggle="buttons" style="margin-top: 10px">
                        <label class="btn btn-default active">
                            <input name="week" type="radio" autocomplete="off" checked> 1週目
                        </label>
                        <label class="btn btn-default">
                            <input name="week" type="radio" autocomplete="off"> 2週目
                        </label>
                    </div>                    
                </div>
            </div>
            <div class="row col-lg-12">
                <div>
                        <input type="submit" id="search" class="btn btn-box" value="検索">
                </div>                
            </div>            
            <div class="row col-md-12">
                <div id="fw" class="col-md-6 values">
                    <h2>1週目</h2>
                    <table class="table table-borderd table-striped">
                        <th></th>
                        <th>行き</th>
                        <th>帰り</th>
                        <tr>
                            <th>3月4日(月)</th>
                            <td id="fw_go_mon"></td>
                            <td id="fw_rtn_mon"></td>
                        </tr>
                        <tr>
                            <th>3月5日(火)</th>
                            <td id="fw_go_tue"></td>
                            <td id="fw_rtn_tue"></td>
                        </tr>
                        <tr>
                            <th>3月6日(水)</th>
                            <td id="fw_go_wed"></td>
                            <td id="fw_rtn_wed"></td>
                        </tr>
                        <tr>
                            <th>3月7日(木)</th>
                            <td id="fw_go_thu"></td>
                            <td id="fw_rtn_thu"></td>
                        </tr>
                        <tr>
                            <th>3月8日(金)</th>
                            <td id="fw_go_fri"></td>
                            <td id="fw_rtn_fri"></td>
                        </tr>
                    </table>
                </div>
                <div id="sw" class="col-md-6">
                    <h2>2週目</h2>
                    <table class="table table-borderd table-striped">
                        <th></th>
                        <th>行き</th>
                        <th>帰り</th>
                        <tr>
                            <th>3月11日(月)</th>
                            <td id="sw_go_mon"></td>
                            <td id="sw_rtn_mon"></td>
                        </tr>
                        <tr>
                            <th>3月12日(火)</th>
                            <td id="sw_go_tue"></td>
                            <td id="sw_rtn_tue"></td>
                        </tr>
                        <tr>
                            <th>3月13日(水)</th>
                            <td id="sw_go_wed"></td>
                            <td id="sw_rtn_wed"></td>
                        </tr>
                        <tr>
                            <th>3月14日(木)</th>
                            <td id="sw_go_thu"></td>
                            <td id="sw_rtn_thu"></td>
                        </tr>
                        <tr>
                            <th>3月15日(金)</th>
                            <td id="sw_go_fri"></td>
                            <td id="sw_rtn_fri"></td>
                        </tr>
                    </table>
                </div>
            </div>

        </div>
        <footer>
            <div class="container-fluid">
                <p class="copyright">© Rupic</p>
            </div>
        </footer>

        <!-- jQuery -->
        <script src="js/jquery-2.1.1.js"></script>
        <!--  plugins -->
        <script src="js/bootstrap.min.js"></script>
        <script src="js/sheet.js"></script>
    </body>
</html>

seet.js

$(function(){
    $("#fw").css("display", "none");
    $("#sw").css("display", "none");

    $('#search').click(function(){
        var jcode = $('#jcode').val();
        var week = 0;
        $("#fw").css("display", "none");
        $("#sw").css("display", "none");

        if($('input[name=week]:eq(0)').prop('checked')){
          $("#fw").toggle();
          week = 1;
        }else{
          $("#sw").toggle();
          week = 2;
        };

        var url = 'https://script.google.com/macros/s/AKfycbyolai-14OF6N_jWKCnykga3WpVcCX06LYvRBn23W1gjkyYDFU/exec?name='+jcode+"&id="+week;

        $.ajax({ // json読み込み開始
            type: 'GET',
            url: url,
            dataType: 'json'
          })
          .then(
            function(json) { // jsonの読み込みに成功した時
              if(week===1){
                $('#fw_go_mon').text(json[2]);
                $('#fw_go_tue').text(json[3]);
                $('#fw_go_wed').text(json[4]);
                $('#fw_go_thu').text(json[5]);
                $('#fw_go_fri').text(json[6]);
                $('#fw_rtn_mon').text(json[7]);
                $('#fw_rtn_tue').text(json[8]);
                $('#fw_rtn_wed').text(json[9]);
                $('#fw_rtn_thu').text(json[10]);
                $('#fw_rtn_fri').text(json[11]);
              }else{
                $('#sw_go_mon').text(json[2]);
                $('#sw_go_tue').text(json[3]);
                $('#sw_go_wed').text(json[4]);
                $('#sw_go_thu').text(json[5]);
                $('#sw_go_fri').text(json[6]);
                $('#sw_rtn_mon').text(json[7]);
                $('#sw_rtn_tue').text(json[8]);
                $('#sw_rtn_wed').text(json[9]);
                $('#sw_rtn_thu').text(json[10]);
                $('#sw_rtn_fri').text(json[11]);
              }
            },
            function() { //jsonの読み込みに失敗した時
              alert('予期せぬ不具合が発生しました');
            }
           );
    });
});

 

適当にWebサーバーにデプロイして接続してみます。

f:id:rupic:20190309012921p:plain

まとめ

  • 急ぎで作成したので雑で申し訳ないです
  • 簡単にWebアプリから呼び出し可能なのでサクッと作りたい時に重宝しそう?
  • UIは自分の好きな感じで作成できるので融通が効きますね

 

今回のGoogle Formシリーズはこれにて終了ですが、また機会があれば、色々触ってみようかと思いますm(_ _)m