LINE Messaging API×GASで家計簿管理用のLINE botを作成する:スプレッドシートへの書き込み

Google Apps Script

LINE家計簿botの作成にあたり、前回・前々回と必要な設定を進めてきました。

今回は、Googleスプレッドシートと連携させて、LINEのメッセージをスプレッドシートに記録する処理を作成します。

LINE developersの登録、Google Apps Script(GAS)の設定、LINEとGASの連携に関しては過去の記事をご参照ください。

Googleスプレッドシートの作成

まず初めに、Googleスプレッドシートを作成しておきます。

GoogleスプレッドシートURL:https://doc.google.com/spreadsheets?hl=ja

空白のスプレッドシートを作成します。

家計簿のテンプレート(ひな形)を作っておきます。

作成するのは以下の2シートです。

  • 「202302」:月のサマリーを記録する用のシート
  • 「202302内訳」:内訳を記録する用のシート

※例では「202302」となっていますが、実行するタイミングの年月に変更してください!

月のサマリーを記録する用のシートは以下のようなレイアウトにしました。

内訳を記録する用のシートは以下になります。

スプレッドシートに金額を書き込むスクリプトを作成する

GASのスクリプトを作成します。スクリプトと聞くとなんだか難しそう、プログラミングやったことないしエラーになったりしてめんどくさそう、と感じる方もいるかと思います。・・・が、以下のコードの数か所をご自身の環境のものに変更していただくだけで作成できますので、コピペして試してみてください。

大丈夫です、中の人間も機械音痴でプログラミング苦手な普通の主婦ですので・・・!

Google Apps Scriptのマイページから、「新しいプロジェクト」を押下します。

前回の記事ですでにプロジェクトを作成済の方は、一覧から該当のプロジェクトを開いてください。

「コード.js」というスクリプトを開いていることを確認して、

いったん全て削除して、以下のソースコードをコピーして貼り付けてください。

/*
  LINE家計簿用bot
*/
// LINE developerで登録したチャネルアクセストークン
var ACCESS_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
// LINEへ応答メッセージを送るAPI
var LINE_ENDPOINT = "https://api.line.me/v2/bot/message/reply";
// スプレッドシートのID
var SHEET_ID = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

// LINEからPOSTリクエストが渡されてきたときに実行される処理
function doPost(e) {

  // LINEからPOSTされるJSON形式のデータをGASで扱える形式(JSオブジェクト)に変換
  var json = JSON.parse(e.postData.contents);

  // LINE側へ応答するためのトークンを作成(LINEからのリクエストに入っているので、それを取得する)
  var reply_token= json.events[0].replyToken;
  if (typeof reply_token === 'undefined') {
    return;
  }

  // LINEから送られてきたメッセージを取得
  var user_message = json.events[0].message.text;
  // 改行で区切って配列にする
  var user_msgarray = user_message.split(/\r\n|\n/);

  // 応答メッセージ本文
  var resultMsg = "";

  // LINEから受け取ったメッセージの内容が形式通りかチェック
  var validate = isValid(user_msgarray);
  if (validate != "OK"){
    resultMsg = validate;
  }
  else if(validate == "OK"){
    // スプレッドシートへの書き込み
    resultMsg = registData(user_msgarray);
  }
  
  // 応答用のメッセージを作成
  var message = {
                  "replyToken"  : reply_token,
                  "messages"    : [{"type": "text",      // メッセージのタイプ(画像、テキストなど)
                                    "text" : resultMsg}] // メッセージの内容
                };

  // LINE側へデータを返す際に必要となる情報
  var options = {
    "method" : "post",
    "headers" : {
      "Content-Type" : "application/json; charset=UTF-8",  // JSON形式を指定、LINEの文字コードはUTF-8
      "Authorization" : "Bearer " + ACCESS_TOKEN           // 認証タイプはBearer(トークン利用)、アクセストークン
    },
    "payload" : JSON.stringify(message)                    // 応答文のメッセージをJSON形式に変換する
  };

  // LINEへ応答メッセージを返す
  UrlFetchApp.fetch(LINE_ENDPOINT, options);
}

// スプレッドシートへの書き込み
function registData(user_msgarray){

  var msg = "";

  // 対象のスプレッドシートを取得
  var spreadSheet = SpreadsheetApp.openById(SHEET_ID);

  // 本日の日付を取得
  var today = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyy/MM/dd');

  // 書き込む対象のシートを取得
  var sheetName = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMM内訳');
  var targetSheet = spreadSheet.getSheetByName(sheetName);

  if (targetSheet != null){

    // 最終行を取得
    var lastRow = targetSheet.getLastRow();
    var targetRow = lastRow + 1;

    // 書き込み
    targetSheet.getRange(targetRow, 1).setValue(today);  // 日付
    targetSheet.getRange(targetRow, 2).setValue(user_msgarray[0]);  // 費目
    targetSheet.getRange(targetRow, 3).setValue(user_msgarray[1]);  // 金額
    msg = "書き込み完了";
  }
  else{
    // 対象のシートが見つからない場合
    msg = "シート名:" + sheetName + "\nが見つかりません";
  }
  return msg;
}

// 値のチェック
function isValid(user_msgarray){

  var result;

  // 対象のスプレッドシートを取得
  var spreadSheet = SpreadsheetApp.openById(SHEET_ID);
  var sheetName = Utilities.formatDate(new Date(), 'Asia/Tokyo', 'yyyyMM');
  var targetSheet = spreadSheet.getSheetByName(sheetName);

  // 入力された費目が存在するかチェック
  var values = targetSheet.getRange("A13:A22").getValues();
  for (var i in values) {
    var iNum = parseInt(i);
    if (values[iNum][0] == user_msgarray[0]){
      result = "OK";
      break;
    }
  }
  if (result != "OK"){
    result = "費目に存在しません: " + user_msgarray[0];
    return result;
  }

  // 入力された金額が正しいかチェック
  if(user_msgarray[1] != null & Number.isInteger(Number(user_msgarray[1]))){
    result = "OK";
  }
  else{
    result = "金額を正しく入力してください";
  }
  return result;
}

書き換える場所は、以下の3箇所です。

5行目・チャネルアクセストークン:Line Developer>Messaging API設定で発行したチャネルアクセストークンを入れます

9行目・スプレッドシートのID:スプレッドシートのURLの、「https://docs.google.com/spreadsheets/d/XXXXXXXXX/edit#gid=~~~」のXXXXXXXXXの部分になります。

107行目・費目リストの取得(任意):こちらは「202302」シートのほうに記載してある費目のリストを取得する部分なのですが、もしここに項目を追加もしくは削除している場合や、記載している場所を変更している場合にはそれに合わせて変更してください。

見本のテンプレと同じように作成している場合は変更不要です。

LINEからメッセージを送信してシートに書き込まれるか確認してみる

上記の設定が完了したら、実際にLINEからメッセージを送信して、スプレッドシートに正しく書き込まれるか確認してみます。

GASのデプロイ

GASの右上メニューから「新しいデプロイ」

種類は「ウェブアプリ」を選択

次のユーザーとして実行を「自分」、アクセスできるユーザーを「全員」にしてデプロイを押下

このとき「アクセスを承認」を出た場合には、「承認」を押下して進めます。

デプロイが完了したら、ウェブアプリのURLをコピーします。

LINE DevelopersにGASのURLを設定

コピーしたURLを、LINE DevelopersのMessaging API設定>Webhook URLに設定します。

LINEでメッセージを送ってみる

では、LINEからメッセージを送信して確認してみます。

  • 1行目:費目
  • 2行目:金額

を送信するとスプレッドシートの「2023内訳」シートに書き込まれるようになっていますので、

「日用品 (改行) 500」というメッセージを送信します。

すると、botから「書き込み完了」というメッセージが送られてきました。

スプレッドシートを見てみると、

投稿した内容が記録されていることを確認できました。

「202302」シートの費目に存在しない費目名で入力すると、

費目に存在しない旨のメッセージが返ってきます。

また、金額に整数以外が入っている場合にも登録できないようになっています。

そもそも、シートが存在していない場合や、対象のシート名が見つからない場合にはシートが見つからない旨のメッセージが返ってきます。

まとめ

今回は、LINE家計簿botの作成を通して、GoogleスプレッドシートとGASの連携によりLINEのメッセージをスプレッドシートに記録する処理を作成しました。

次回は、今回とは逆に、スプレッドシートからデータを参照する処理を作成していきます。

全体像で確認すると、残りは赤枠の箇所です。

ということで、3回にわたりGoogle Apps Script&GoogleスプレッドシートとLINEの連携について学んできましたが、次回でいったん一通り処理が完成します。

LINEで家計簿を管理できると、私のようなズボラな人間でも継続して家計簿を記録できそうです。

もし、「ブログの手順通りに作ってみたけど動かない!!!」という場合には、気軽にコメントか問い合わせフォームでご連絡ください。(トラブルシューティングに関しては別途記事にしようと思っています!)

コメント

  1. Meloooon より:

    LINE APIとGASの紐づけ方を参考にしたく、記事を拝見させて頂きました。

    このひとつ前の記事の、自動返信のテストについては、問題無く実行できたのですが、スプレッドシートと連携させると、返信が何も無く、スプレッドシートにも書き込まれませんでした。

    チャネルアクセストークンや、スプレッドシートを何度も作り直しているのですが、一向に改善しません。Webhookの利用もオンにしています。

    解決できず、お力をお借り出来たらなと思いご連絡させて頂きました。
    何卒よろしくお願いいたします。

    • chaso chaso より:

      コメントありがとうございます。返信が遅くなり申し訳ありません。
      自動返信のテストまではうまくいっているということで、スプレッドシートへの書き込み時に何等かのエラーが出て
      応答がない状態と予想されます。

      本記事の、以下をコメントアウト
      // スプレッドシートへの書き込み
      // resultMsg = registData(user_msgarray);
      この状態で、いったんうまくいくか試してみていただけますでしょうか?

      よろしくお願いいたします。

  2. OLAF より:

    横から失礼いたします。
    私も同じ問題に直面しました。

    73行目~75行目でシート名を日付で取得しているので、
    シート名を「202302」ではなく、当日の年月(yyyymm)にする必要がありそうです。
    私の環境ではこの修正をして問題なく動くようになりました。
    よろしくお願いいたします。

    • chaso chaso より:

      OLAF様
      コメントありがとうございます。
      実行するタイミングによって年月が変わりますので、その対応は必要ですね。
      記事内に明記されていませんでしたので追記しておきます。
      ありがとうございます。

タイトルとURLをコピーしました