‹ www.michinoeki-mania.com

はてなブログのためにGoogle Apps Scriptができることは何かある?

Sep 06, 2017

はいどうも、よっしーです。
僕のブログには【随時更新】とタイトルの付いた記事があり、そのタイトル通り内容が事あるごとに更新・追記しています。今回は、その更新・追記の作業を少しでも楽にしたいということで、Google先生が提供するGoogle Apps Scriptを使ってみました。

とりあえず今回は、【随時更新】記事の更新を楽にしたいというのが目的です。

これまでの更新フロー

今回Google Apps Script(以下、GAS)を導入したのは、

http://www.michinoeki-mania.com/entry/2017/04/11/215950

の記事です。
オイル交換やタイヤ交換などのメンテナンス記録を書いているわけですが、メンテナンス種別による絞込機能を入れるために記録のテーブル部分はhtml直書きになってます。つまり、行を足すだけとは言え毎回htmlを記述(コピペ)しないといけないという、なんとも面倒くさい仕様になってます。

なので、メンテナンス記録のデータ自体は別の場所に見やすい形で保持しておいて、この記事では勝手にそのデータを取得して表示させるようにしたいなというのが始まりです。

で、その 別の場所 というのがGoogle Drive上のスプレッドシートで、勝手にそのデータを取得して という部分をGASにやってもらおうということです。

スプレッドシートでのデータの持ち方

メンテナンス記録の記事を見ていただくとわかるかと思いますが、各記録で必要になるデータは、メンテナンスの種類ODOメーターの値メモです。ものすごく内部的な話になりますが、このうち`メンテナンスの種類`は、実際に表示されている日本語部分(オイル交換 など)と、絞り込み時に使っている識別子(ソースを表示してもらうとわかるとおもいます)を含んでます。

なので、各記録に必要なのは メンテナンスの種類(識別子)メンテナンスの種類(日本語)ODOメーターの値メモ の4つとなります。

ということで、スプレッドシートのデータの持ち方はこんな感じです。

20170906222623

今後記録データが増えていった場合にはここに追記していくことになりますが、データの持ち方が非常にシンプルなので更新も楽になります。

GASのソース

では、このスプレッドシートのデータをどうやってブログ記事内に表示させるかという話ですが、ここでGASの出番です。 GASとは何なんだ、という方も多いと思いますが、Googleの各種サービス(Drive、Mail、Mapなど)を、外から触れるやつです(語彙力)

今回の場合だと、Google Driveのスプレッドシートにあるデータを、Google Driveにアクセスしなくても取得ができるわけです。

各サービス用にあらかじめ準備された関数があるので、それらを組み合わせてプログラムを組むことで、Googleの各種サービスを利用した独自のWEBアプリケーションだったりAPIを作ることができます。
言語は javascript に似たようなもので、公式のリファレンスも充実しているので何かしらの言語でプログラムを書いたことがある人なら割ととっつきやすいと思います。

今回GASを使って作りたいのが、あるURLを叩けばスプレッドシートの内容が json 形式で受け取れる というものです。で、実際に作ったものがこれです(雑)

|javascript| function getData(id, sheetName) { var sheet = SpreadsheetApp.openById(id).getSheetByName(sheetName); var keys = sheet.getRange(1, 1, 1, 4).getValues().splice(0, 1)[0]; var nolast = true; var lastIdx = 2; var n = 2; var chk; while (nolast) { chk = sheet.getRange(n, 3).getValue(); if (chk == “") { nolast = false; lastIdx = n - 1; } n++; }

var returnObj = { update_date:"”, history: [] }; var tmpRpw; for (var m = 2; m <= lastIdx; m++) { var obj = {}; tmpRow = sheet.getRange(m, 1, 1, 4).getValues().splice(0, 1)[0]; tmpRow.map(function(item, index) { if (keys[index] == “odo”) { var tmpItem = “"; item = item + “"; for (var j = 1; j <= item.length; j++) { if (j % 3 == 0 && j != item.length) { tmpItem = “,” + item[item.length - j] + tmpItem; } else { tmpItem = item[item.length - j] + tmpItem; } } item = tmpItem; } obj[keys[index]] = item; }); returnObj.history.push(obj); }

returnObj.update_date = Utilities.formatDate( DriveApp.getFileById(id).getLastUpdated(), ‘Asia/Tokyo’, ‘yyyy年M月d日’);

return returnObj; }

function doGet() { var data = getData(‘XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX’, ‘maintenance’); return ContentService.createTextOutput(JSON.stringify(data, null, 2)) .setMimeType(ContentService.MimeType.JSON); } ||<

あるURLを叩くと duGet() 関数が呼ばれて、その中では getData() 関数を呼んでスプレッドシートのデータを取得し、return で呼び出し元に json 形式で返却しています。

getData() 関数の引数になっているのが、データを取りに行くスプレッドシートのIDと、対象となるシート名です。
ごちゃごちゃと書いていますが、スプレッドシートの内容が今感じの json で取得できます。

|json| { “update_date”: “2017年9月6日”, “history”: [ { “class”: “oil”, “type”: “オイル交換”, “odo”: “9,426”, “memo”: “elf MOTO 4RS (レッドバロン オイルリザーブ VSグレード)” }, { “class”: “tire”, “type”: “タイヤ交換”, “odo”: “9,426”, “memo”: “DUNLOP GPR200 F (120/70) R (190/50)” }, { “class”: “oil”, “type”: “オイル交換”, “odo”: “12,538”, “memo”: “elf MOTO 4RS (レッドバロン オイルリザーブ VSグレード)” }, …. } ||<

update_date は、スプレッドシートの更新日から取っています。これを取ることで、ブログ記事内の「◯月△日 更新」という部分も勝手に入ってくれます。

この受け取った json をテーブル表示させればOKです。

JSONをテーブル表示させる

ページの読み込み時に、あるURLに対してajax通信して json を受け取り、それをもとにしてテーブルのhtmlを生成して表示させます。その処理がこちら(雑)

|javascript|

$(document).ready(function(){

var table = "";
$.ajax(
    "https://script.google.com/macros/s/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/exec",
    {
        type: "get"
    }
)
.done(function(data){
    table = '<table id="maintenance-history">'
          + '<tbody>'
          + '<tr>'
          + '<th>距離(km)</th>'
          + '<th>内容</th>'
          + '<th>備考</th>'
          + '</tr>'
          + '<tr>'
          + '<td class="meter">5,898 km</td>'
          + '<td class="mente-type">その他</td>'
          + '<td>納車</td>'
          + '</tr>';

    for (var n = 0; n < data.history.length; n++) {
        table += '<tr class="his '+data.history[n].class+'">'
              + '<td class="meter">'+data.history[n].odo+' km</td>'
              + '<td class="mente-type">'+data.history[n].type+'</td>'
              + '<td>'+data.history[n].memo+'</td>'
              + '</tr>';
    }

    table += '</table>';

    $("#maintenance-history-table-area").html(table);
    $("#last-updated").text(data.update_date);
});

});

||<

|javascript| $("#maintenance-history-table-area”).html(table); $("#last-updated”).text(data.update_date); ||<

最後のこの2行で実際に表示をしているわけなので、ブログ記事の方にはこのjsと、(適当な箇所に)以下のhtmlの記述が必要になります。

|html|

||<

まとめ

はい、どうだったでしょうか(雑) スプレッドシートにデータを持っていると、他の用途で使用する際にも便利なので、個人的にはこの方法に切り替えてよかったと思います。 ただ1点未完成な部分としては、この状態ではリクエストのURLを叩けば誰でもjsonを取れるっていうところですね(笑) 一般的なWebアプリケーションからURLを叩く場合、用意したGASに認証を設けて、URLのパラメータとして認証キーやトークンを渡したりしますが、如何せん呼び出し元が自分の手元にある環境ではないのでそういった処理を組み込むことはできてません。 とは言っても今回の場合はただの整備記録で、なおかつ読み込みのみの口しか用意してないので特に問題はないです。 ただし冒頭にも書いたようにGASを使えばスプレッドシートの内容を外から編集したり、Gmailアカウントでメールを送ったりすることも可能なので、そういったスクリプトを作った際にはスクリプトの実行権限の設定はしっかりする必要があります。

今後もはてなブログ内で使えそうなものを思いついたら試して見たいと思います。