Help us understand the problem. What is going on with this article?

GASでWebアプリ「映画鑑賞記録」を作る

最初に

 勉強の為に、GASでWebアプリを作ろっと思って題材を考えていたら、趣味の映画鑑賞の記録をつけているので、これにしようと思いました。
 記録を入力するのも、後回しにすると忘れてしまったりするので、鑑賞後にその場で入力できれば忘れる事も防げますし、将来的には鑑賞後のメモを入力できる様にすれば、後からレビューを書くときの助けにもなると思います。

現状(Excelファイル)

 Webアプリにしようとしている元ネタは、Excel(映画鑑賞記録.xlsx)で管理しています。
 内容を簡単に説明します。

[鑑賞履歴]シート

鑑賞履歴.png
 このシートが、鑑賞記録そのものと成ります。

  1. 「ID」は、ユニークな連番です。
  2. 「鑑賞日」は、そのままですが、管理が悪くて実際の日付にはなっていません。 :sweat_smile: :sweat_drops:
  3. 「タイトル」も、そのままです。
  4. 「初見」は、初めて観た場合に1をセットします。(既に鑑賞した事がある場合は0
  5. 「鑑賞種別」は、鑑賞方法により区分をセットします。(※[鑑賞種別]シートを参照)
  6. 「映画館名」は、基本的(「鑑賞種別」=1の場合)に鑑賞した映画館の名前をセットします。

[映画館]シート

映画館.png

  1. 「映画館名」は、[鑑賞履歴]シートの「映画館名」と同じ。
  2. 「鑑賞種別」は、[鑑賞履歴]シートの「鑑賞種別」と同じ。
  3. 「初」は、初めて行った映画館の場合に1をセットします。年末にその年に初めて行った映画館を知るために使っています。なので、年始に全てのデータに0をセット(クリア)します。
    このリストに追加されている映画館は、既に行った事のある映画館と言う事になります。
    「鑑賞種別」≠1の場合は、対処外として9をセットします。

[鑑賞種別]シート

鑑賞種別.png

  1. 「ID」は、鑑賞方法の区分を表します。([鑑賞履歴]シートの「鑑賞種別」にセットする値)
  2. 「鑑賞種別」は、鑑賞方法を表しています。
    • 映画館 映画館で鑑賞した場合。
    • DVD   DVD、Blu-ray Disc、ビデオテープ等パッケージ製品で個人的に鑑賞した場合。
          「映画館名」にはレンタル会社名、パッケージの持ち主をセットする。
    • 配信  配信サービスで個人的に鑑賞した場合。「映画館名」にはサービス会社名をセットする。
    • その他 上記以外。映画館以外でのイベント上映会など。popcornでの鑑賞はコッチ。
          「映画館名」には会場名などをセットする。

取り敢えず一覧表示のみ

 先ず、ExcelファイルをGoogleドライブにアップロードして、スプレッドシートに変換します。(詳細は割愛します)
 次に、上記スプレッドシート(「映画鑑賞記録」)のデータを、Web画面に表示するGASのコードを用意します。
 会社内のGAS勉強会で使用したものをそのまま流用しました。(詳細については別に投稿します)
映画鑑賞記録.png
 設定ファイルやCSSの設定は別にあるのですが、メインで使用しているのは次の3ファイルのみです。

  • ViewingRecord.gs サーバ側の処理。
  • Index.html     クライアント側の画面表示。
  • javascript.html   クライアント側の処理。

ViewingRecord.gs

function doGet(e) {
  var template = HtmlService.createTemplateFromFile('Index');
  var title = "映画鑑賞記録";
  var html = template.evaluate().setTitle(title).setSandboxMode(HtmlService.SandboxMode.IFRAME);

  return html;
}

function getReportListBy(cond) {
  cond.type = "viewingRecord";
  Logger.log(cond);

  var sheet = SpreadsheetApp.openById(ViewingRecordID).getSheetByName('鑑賞履歴');
  var lastRow = sheet.getLastRow();
  var results = sheet.getRange(3, 2, (lastRow - 2), 6).getValues();
  //Logger.log(results);

  return JSON.stringify(results);
}

Index.html

<!DOCTYPE html>
<html>
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/redmond/jquery-ui.css" />
  <!-- Bootstrap -->
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/moment.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.14.1/locale/ja.js"></script>

  <?!= HtmlService.createHtmlOutputFromFile('css').getContent(); ?>
  <?!= HtmlService.createHtmlOutputFromFile('javascript').getContent(); ?>

  <script>
  var reportListCache = [];  // 検索結果退避
  </script>
  <head>
    <base target="_top">
  </head>
  <body>
    <p></p>
    <div class="container-fluid">
    <table id="resultList" class="table table-striped table-bordered table-headerfixed">
      <thead class="scrollHead">
        <tr class="info">
          <th class="head01">ID</th>
          <th class="head01">鑑賞日</th>
          <th class="head02">タイトル</th>
          <th class="head01">初見</th>
          <th class="head01">鑑賞種別</th>
          <th class="head04">映画館</th>
        </tr>
      </thead>
      <tbody class="scrollBody"></tbody>
    </table>
    </div>
  </body>
</html>

javascript.html

  <script>
  $(document).ready(function() {
    searchResults();
  });

  function searchResults() {
    var cond = {}; // 条件があれば...
    google.script.run.withSuccessHandler(
          function(v, element) {
            drawTable(v);
            reportListCache = v;
          })
        .withFailureHandler(
          function(msg, element) {
            showError(msg);
          })
        .withUserObject(this)
        .getReportListBy(cond);
  }

  function drawTable(data) {
    var records = JSON.parse(data)
    //console.log(records);
    var tag = '';
    for(var i = 0; i < records.length; i++) {
      tag += '<tr>';
      tag += '<td class="col01">'+ records[i][0] + '</td>';      
      tag += '<td class="col01">'+ convDate(records[i][1]) + '</td>';
      tag += '<td class="col02">'+ records[i][2] + '</td>';
      tag += '<td class="col01">'+ records[i][3] + '</td>';
      tag += '<td class="col01">'+ records[i][4] + '</td>';
      tag += '<td class="col04">'+ records[i][5] + '</td>';
      tag += '</tr>';
    }
    $('#resultList tbody').html(tag);
  }

  function convDate(date) {
    //console.log(date);
    var res = date.substr(5, 2) + '/' + date.substr(8, 2);
    return res;
  }

  function showError(msg) {
    console.log('msg:' + msg.toString());
    console.log(msg);
    alert(msg);
  }

  function convNaN(value) {
    var res = '';
    if(isFinite(value)) {
      res = value;
    }
    return res;
  }

  </script>

 こんな簡単なコードで、Webでの一覧表示が作れます。
 細かい説明は別に投稿していきますが、1ヶ所つまずいた所があるので記します。
 処理の大雑把な流れは次の様になっています。

  1. Index.html が読み込まれて、javascript.html$(document).ready()が実行されます。
  2. 続けて、searchResults()が呼ばれます。
  3. searchResults()では、サーバ側の処理(ViewingRecord.gsgetReportListBy()が呼び出されます。
  4. getReportListBy()では、スプレッドシートのデータを取得してreturnに返し、その値をsearchResults()google.script.run.withSuccessHandler()vとして受け取る事ができます。

 最初、スプレッドシートのデータ(results)を直接returnに渡していたのですが、この方法では値は渡りません。
 スプレッドシートのデータの様な配列のデータを渡す場合は、JSON.stringify()を使う(JSONデータにして渡す)必要があるそうです。
 なので、受ける側ではJSON.parse()も使う(javascript.htmldrawTable())必要があります。
 ◆参考サイト Google Apps Scriptでウェブアプリケーション作成入門

pump33
元COBOLER、VBやって、今GASとJavaを勉強中。 趣味は、映画鑑賞。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした