0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

文化祭で使う会計アプリとLINE Botをつくった

0
Last updated at Posted at 2026-04-11

2022年夏執筆(高3)
ずっと限定公開にしていたのを、4月に公開したので公開日が2026年の4月になっています。内容は変えていません。
↑これを書き加えるために最終更新日が最近の日付になっています。

はじめに

この記事は、ほぼ自分と後輩に向けての書き残しで、プログラミングを授業でやったことがある程度の人に向けてのものです。
GASを使ってつくります。
半年前に初めてGASの基本に触れて、半年ぶりに再びGASを扱った人が書いています。

つくるもの

  • スプレッドシートに売った数と支払額を入力して、販売時刻、販売数、在庫、代金、お釣りを表示させるもの
  • それらをLINEで通知するもの
    スクリーンショット (196).png
    スクリーンショット (198).png
    4adaf4d2-5f77-4f39-b57c-bcc3c6cf119c.jpg

GASとは何か

ググれgas

開発に至った経緯

半年前にGASに初めて触れてからこれを使って何かしたいと思っていました。そんなときに、ちょうどよく文化祭の時期になったので、売上を集計するものがあれば便利だと思い、開発することにしました、
もともとは、LINE botでクラスラインに売上を通知するのが始まりで、そこからより便利にするために試行錯誤して、このようなものになりました。

スプレッドシートを作る

Google スプレッドシートのページへ飛んでください。
そうしたら「拡張機能」の「Apps Script」からスクリプトエディタを開きます。
9b414f02-fbae-4955-b187-04e1ce8ebe76.jpg
これで準備は完了です。

コード解説とスプレッドシート

スクリーンショット (196).png
スクリーンショット (198).png

コード全文

会計
function inputInfo() {

  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('statistics');
  var sheetF = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('form');

  var lastRow = sheet.getLastRow();

  var now = new Date();
  var now = Utilities.formatDate(now, "Asia/Tokyo", "HH:mm");

  var quantity = sheetF.getRange('H9').getValue();

  var s = sheetF.getRange(4, 2, 6, 1).getValues();
  var i = sheetF.getRange(3, 8, 6, 1).getValues();

  var rA = Number(s[0]) + Number(i[0]);
  var rB = Number(s[1]) + Number(i[1]);
  var rC = Number(s[2]) + Number(i[2]);
  var rD = Number(s[3]) + Number(i[3]);
  var rE = Number(s[4]) + Number(i[4]);
  var rF = Number(s[5]) + Number(i[5]);

  var arr = [[rA, rB, rC, rD, rE, rF]];
  var iData = [[now, quantity, '売り場']];

  sheet.getRange(11, 5, 1, arr[0].length).setValues(arr);
  
  for(let i = 2; i <= lastRow; i++) {
    if(!sheet.getRange(i, 1).getValue()){
        sheet.getRange(i, 1, 1, iData[0].length).setValues(iData);
      break;
    }
    sheetF.getRange(3, 8, 6, 1).clearContent();
    sheetF.getRange('D11').clearContent();
  }
};

大まかにこのスクリプトを解説すると、form(シート)数量(H3:H8)の欄のセルの値を取得して、スクリプト実行時の種類別総販売数(B4:B9)を足したものを新しい在庫数として、statistics(シート)販売数(E11:J11)に入力するというものになっています。

基本的なところはこちらを見てください。
また、コード内でたくさん使われているgetRange()についてはこちらでとても詳しく解説されているので説明は省きます。

  var lastRow = sheet.getLastRow();

getLastRow()statistics(シート)の最終行を取得します。

  var now = new Date();
  var now = Utilities.formatDate(now, "Asia/Tokyo", "HH:mm");

new Date()で現在時刻を取得して、Utilities.formatDate(now, "Asia/Tokyo", "HH:mm")で24時間表記に変換し、それをnowに代入します。

  var quantity = sheetF.getRange('H9').getValue();

getValue()でH9の値を取得します。

  var s = sheetF.getRange(4, 2, 6, 1).getValues();
  var i = sheetF.getRange(3, 8, 6, 1).getValues();

s種類別総販売数(B4:B9)で、i種類別販売数(H3:H8)です。
getRange()で取得した範囲のセルの値をgetValues()でまとめて取得します。
このとき、取得した値は配列になっています。

  var rA = Number(s[0]) + Number(i[0]);
  var rB = Number(s[1]) + Number(i[1]);
  var rC = Number(s[2]) + Number(i[2]);
  var rD = Number(s[3]) + Number(i[3]);
  var rE = Number(s[4]) + Number(i[4]);
  var rF = Number(s[5]) + Number(i[5]);

rX(X = A, B, ..., F)statistics(シート)種類別総販売数(E11:J11)に入力する値です(rAなら種類Aの販売数)。
配列で取得した値は文字型になっていて、計算できないのでNumber()で数値型に変換します。配列に格納された値の取り出し方も、先ほど紹介したサイトで紹介されています。
ここのコードを配列同士の足し算にして処理を少なくしようとしましたが、サポートされていないようなのでできませんでした。めんどくさいのでしませんが、for文を使えばできそうです。

  var arr = [[rA, rB, rC, rD, rE, rF]];
  var iData = [[now, quantity, '売り場']];

rX(X = A, B, ..., F)などを配列にします。
arrには各種類ごとの販売数を、iDataには時間と1会計での販売数を代入します。
配列にすることで、処理を簡略化できます。

  sheet.getRange(11, 5, 1, arr[0].length).setValues(arr);

  for(let i = 2; i <= lastRow; i++) {
    if(!sheet.getRange(i, 1).getValue()){
        sheet.getRange(i, 1, 1, iData[0].length).setValues(iData);
      break;
    }

.lengthで配列の要素数を取得します。arrの要素数は6なので取得する値は6になります。同様に、iDataの要素数は3です。
setValues()で配列をまとめて入力します。
forifについてはこちらのサイトを読んでいけばわかるので、解説は省きます。

  sheetF.getRange(3, 8, 6, 1).clearContent();
  sheetF.getRange('D11').clearContent();

clearContent()getRange()で取得したセルの値をクリアします。

statistics(シート)の時刻、販売数、販売場所を記録する欄の2行目に何か数値を入れておかないと、スクリプトを実行したときに複数行入力されてしまうという不具合があります。対応策は、図のように2行目にあらかじめ数値を入力しておくことですが、根本的な対策にはなっていませんので、いいコードを考えられたらまた書きにきます。

最後に、このスクリプトをスプレッドシートで作成した図形に設定します。
これで完成です。

LINEで通知

ここで解説するよりも、このサイトを見たほうがいいと思うのでコードだけ紹介しておきます。

LINE bot
const url = 'https://api.line.me/v2/bot/message/push';
const token = PropertiesService.getScriptProperties().getProperty('TOKEN'); //token

function postLINE() {
  //時間取得
  var now = new Date(); //現在日時を取得
  var now = Utilities.formatDate(now, "Asia/Tokyo", "MM/dd HH:mm");
  //シート取得
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('statistics');
  //販売数
  var cumulativeRange = sheet.getRange("E2");
  var cumulative = cumulativeRange.getValue().toLocaleString();
  //売上
  var salesRange = sheet.getRange("F2");
  var sales = salesRange.getValue().toLocaleString();
  //在庫
  var stockRange = sheet.getRange("E5");
  var stock = stockRange.getValue().toLocaleString();

  //メッセージ内容
  var message = now + '\n'
  message += '\n'
  message += "販売数:" + cumulative + "" + '\n'
  message += "売上:" + sales + "" + '\n'
  message += "在庫:" + stock + "" + '\n'
  message += '\n'
  message += "このメッセージを見たら水分補給🥤";

  const payload = {
    to: 'ここにIDを入力', //id
    messages: [
      {type: 'text', text: message }
    ]
  };

  const params = {
    method: 'post',
    contentType: 'application/json',
    headers: {
      Authorization: 'Bearer ' + token
    },
    payload: JSON.stringify(payload)
  };

  UrlFetchApp.fetch(url, params);
};

少しだけ解説を

const token = PropertiesService.getScriptProperties().getProperty('TOKEN'); //token

ここのTOKENにはトークンを格納しています。格納の仕方はこちらで紹介されています。IDの取得方法についてはこちらから。
このコードではテキストメッセージになりますが、Flex Messageにしても面白そうですね。
導入する際は、クラスLINEに入っている人には必ず許可をもらってからにしましょう。

最後に

最初に書いた「プログラミングを授業で扱ったことがある人に向けて」の記事になったかはわかりませんが、大量に貼ったリンク先のページが非常にわかりやすいのでそっちをメインで見てください。
ここではスクリプトの処理を書きましたが、スプレッドシートだけでの処理もあります。sum+-'sheet'!セルなどを使って作ってみてください。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?