2022年夏執筆(高3)
ずっと限定公開にしていたのを、4月に公開したので公開日が2026年の4月になっています。内容は変えていません。
↑これを書き加えるために最終更新日が最近の日付になっています。
はじめに
この記事は、ほぼ自分と後輩に向けての書き残しで、プログラミングを授業でやったことがある程度の人に向けてのものです。
GASを使ってつくります。
半年前に初めてGASの基本に触れて、半年ぶりに再びGASを扱った人が書いています。
つくるもの
GASとは何か
開発に至った経緯
半年前にGASに初めて触れてからこれを使って何かしたいと思っていました。そんなときに、ちょうどよく文化祭の時期になったので、売上を集計するものがあれば便利だと思い、開発することにしました、
もともとは、LINE botでクラスラインに売上を通知するのが始まりで、そこからより便利にするために試行錯誤して、このようなものになりました。
スプレッドシートを作る
Google スプレッドシートのページへ飛んでください。
そうしたら「拡張機能」の「Apps Script」からスクリプトエディタを開きます。

これで準備は完了です。
コード解説とスプレッドシート
コード全文
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()で配列をまとめて入力します。
forとifについてはこちらのサイトを読んでいけばわかるので、解説は省きます。
sheetF.getRange(3, 8, 6, 1).clearContent();
sheetF.getRange('D11').clearContent();
clearContent()でgetRange()で取得したセルの値をクリアします。
statistics(シート)の時刻、販売数、販売場所を記録する欄の2行目に何か数値を入れておかないと、スクリプトを実行したときに複数行入力されてしまうという不具合があります。対応策は、図のように2行目にあらかじめ数値を入力しておくことですが、根本的な対策にはなっていませんので、いいコードを考えられたらまた書きにきます。
最後に、このスクリプトをスプレッドシートで作成した図形に設定します。
これで完成です。
LINEで通知
ここで解説するよりも、このサイトを見たほうがいいと思うのでコードだけ紹介しておきます。
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'!セルなどを使って作ってみてください。




