2
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?

GASで移動スーパーの日報データを販売場所ごとに見える化してみた

2
Last updated at Posted at 2026-06-25

はじめに

移動スーパーの業務では、1日の中で複数の販売場所を回ります。

そのため、あとから振り返るときには、1日全体の売上だけでなく、販売場所ごとの客数や売上も確認したくなります。

ただ、日報や売上データ、備考などが別々に残っていると、あとから整理するのに手間がかかります。

今回は、その課題を小さく切り出し、Google Apps Script(GAS)を使って、日報データを販売場所ごとに集計する仕組みを試しました。

この記事でやること

日報データを販売場所ごとに整理し、
客数・売上・備考をまとめて確認できる形にする。


なぜGASを使ったのか

今回は、Googleスプレッドシートに入力した日報データをそのまま集計したかったため、Google Apps Script(GAS)を使いました。

GASであれば、スプレッドシート上のデータを直接読み取り、集計結果を別シートに出力できます。

特別なソフトを追加せずにブラウザ上で作成できるため、まず小さく試すには扱いやすいと感じました。


今回作ったもの

Googleスプレッドシートに入力した日報データを、GASで販売場所ごとに集計します。

まずは、販売場所ごとの客数と売上を確認できる形を作りました。
その後、見てもらった感想をもとに、備考まとめ、売上順の並び替え、合計行を追加しました。

全体の流れ

日報データをGoogleスプレッドシートに入力
↓
GASを実行
↓
販売場所ごとの集計結果を別シートに出力
↓
見てもらった感想をもとに改善

image.png


今回の構成

今回のプロトタイプは、GoogleスプレッドシートとGoogle Apps Scriptを組み合わせて作りました。

項目 役割
Google スプレッドシート 日報データの入力先、集計結果の表示先
Google Apps Script 販売場所ごとの集計処理
日報データシート 日付、店舗、コース、販売場所、客数、売上、備考を入力するシート
集計結果シート GASで集計した結果を出力するシート

今回は社内システムや実データとは接続せず、公開可能なダミーデータだけを使いました。


元データ(日報データ)

まず、Googleスプレッドシートに 日報データ というシートを作成しました。

実際の業務では日々の日報データを使う想定ですが、今回はダミーデータにしています。


日報データ シート

スクリーンショット 2026-06-25 192723.png

日付、店舗、コース、販売場所、客数、売上、備考を1行ずつ入力しています。


まず作ったもの:販売場所ごとの客数と売上を集計する

ここでは、販売場所ごとの客数合計売上合計を出す処理を作ります。

移動スーパーでは、1日の中で複数の販売場所を回ります。
そのため、1日全体の売上だけでは、どの場所にどれくらいお客さまが来て、どの場所でどれくらい売上があったのかが見えにくくなります。

まず確認したかったのは、販売場所ごとの客数と売上です。

この2つが分かれば、どの場所にお客さまが集まりやすいのか、どの場所の売上が大きいのかを把握できます。

そこで、日報データから販売場所ごとの客数合計と売上合計を出す処理を作りました。


GASコード入力画面
スクリーンショット 2026-06-25 192054.png

▲ GASコードを見る
function aggregateDailyReportSimple() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sourceSheet = ss.getSheetByName('日報データ');

  if (!sourceSheet) {
    SpreadsheetApp.getUi().alert('「日報データ」シートが見つかりません。');
    return;
  }

  const values = sourceSheet.getDataRange().getValues();

  if (values.length <= 1) {
    SpreadsheetApp.getUi().alert('集計するデータがありません。');
    return;
  }

  // 1行目は見出しなので除外する
  const data = values.slice(1);

  // 列番号。0から数える
  // A列=0, B列=1, C列=2, D列=3, E列=4, F列=5, G列=6
  const PLACE_COL = 3;     // 販売場所
  const CUSTOMERS_COL = 4; // 客数
  const SALES_COL = 5;     // 売上

  const summary = {};

  data.forEach(row => {
    const place = row[PLACE_COL];
    const customers = Number(row[CUSTOMERS_COL]) || 0;
    const sales = Number(row[SALES_COL]) || 0;

    if (!place) return;

    if (!summary[place]) {
      summary[place] = {
        customers: 0,
        sales: 0
      };
    }

    summary[place].customers += customers;
    summary[place].sales += sales;
  });

  // 出力先シートを作る。すでにあれば中身を消す
  let outputSheet = ss.getSheetByName('集計結果_簡素版');

  if (!outputSheet) {
    outputSheet = ss.insertSheet('集計結果_簡素版');
  } else {
    outputSheet.clear();
  }

  const output = [
    ['販売場所', '客数合計', '売上合計']
  ];

  Object.keys(summary).forEach(place => {
    output.push([
      place,
      summary[place].customers,
      summary[place].sales
    ]);
  });

  outputSheet.getRange(1, 1, output.length, output[0].length).setValues(output);

  SpreadsheetApp.getUi().alert('販売場所ごとの簡易集計が完了しました。');
}

出力結果

GASを実行すると、販売場所ごとの集計結果が別シートに出力されます。

出力画面
スクリーンショット 2026-06-25 192418.png

これで、販売場所ごとの客数と売上を一覧で確認できるようになりました。

ここで確認できること

  • どの販売場所にお客さまが多いか
  • どの販売場所の売上が大きいか
  • 販売場所ごとの傾向をざっくり見られるか

見てもらって分かったこと

作成した集計結果を、移動スーパーの業務を知っている方に見てもらいました。

集計結果を見ながら話していると、次回販売で使うにはもう少し情報があるとよさそうだと分かりました。

販売場所ごとにまとまっているのは分かりやすい。
ただ、客数と売上だけだと、次回販売にどう活かすかまでは分かりにくい。
備考も一緒に見られると、前回その場所で何があったのか確認しやすい。
売上が高い順に並んでいると、どこから見ればよいか分かりやすい。
全体の合計もあると確認しやすい。

客数と売上が分かれば、販売場所ごとの傾向は確認できます。

ただ、実際に次回販売や運行の見直しに使うには、数字だけでなく補足情報も一緒に見られる方が整理しやすいことが分かりました。

特に、備考の情報は重要です。

  • どの商品が足りなかったのか
  • 問い合わせがあったのか
  • 到着が遅れたのか
  • 天候の影響があったのか

こうした情報が数字と一緒に見えると、次回販売に使いやすくなります。


image.png


感想をもとに改善したこと

もらった感想をもとに、集計結果に以下の内容を追加しました。

改善内容 理由
備考まとめを追加 次回販売に使える情報も一緒に確認したい
売上合計の大きい順に並び替え 優先して確認する販売場所が分かりやすい
合計行を追加 全体の客数・売上を確認しやすい

また、見出しや合計行を太字にし、罫線も追加しました。
これは機能というより、集計結果を見やすくするための調整です。


改善コード 入力画面
スクリーンショット 2026-06-25 192611.png

▲ 改善後のGASコードを見る
function aggregateDailyReportImproved() {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sourceSheet = ss.getSheetByName('日報データ');

  if (!sourceSheet) {
    SpreadsheetApp.getUi().alert('「日報データ」シートが見つかりません。');
    return;
  }

  const values = sourceSheet.getDataRange().getValues();

  if (values.length <= 1) {
    SpreadsheetApp.getUi().alert('集計するデータがありません。');
    return;
  }

  // 1行目は見出しなので除外する
  const data = values.slice(1);

  // 列番号。0から数える
  const PLACE_COL = 3;     // 販売場所
  const CUSTOMERS_COL = 4; // 客数
  const SALES_COL = 5;     // 売上
  const NOTE_COL = 6;      // 備考

  const summary = {};

  data.forEach(row => {
    const place = row[PLACE_COL];
    const customers = Number(row[CUSTOMERS_COL]) || 0;
    const sales = Number(row[SALES_COL]) || 0;
    const note = row[NOTE_COL];

    if (!place) return;

    if (!summary[place]) {
      summary[place] = {
        customers: 0,
        sales: 0,
        notes: []
      };
    }

    summary[place].customers += customers;
    summary[place].sales += sales;

    if (note && note !== '特になし') {
      summary[place].notes.push(note);
    }
  });

  // オブジェクトを配列に変換して、売上合計の大きい順に並べる
  const rows = Object.keys(summary).map(place => {
    return [
      place,
      summary[place].customers,
      summary[place].sales,
      summary[place].notes.join(' / ')
    ];
  });

  rows.sort((a, b) => b[2] - a[2]);

  const totalCustomers = rows.reduce((sum, row) => sum + row[1], 0);
  const totalSales = rows.reduce((sum, row) => sum + row[2], 0);

  // 出力先シートを作る。すでにあれば中身を消す
  let outputSheet = ss.getSheetByName('集計結果_改善版');

  if (!outputSheet) {
    outputSheet = ss.insertSheet('集計結果_改善版');
  } else {
    outputSheet.clear();
  }

  const output = [
    ['販売場所', '客数合計', '売上合計', '備考まとめ'],
    ...rows,
    ['合計', totalCustomers, totalSales, '']
  ];

  outputSheet.getRange(1, 1, output.length, output[0].length).setValues(output);

  // 見た目を整える
  const lastRow = output.length;
  const lastCol = output[0].length;

  outputSheet.getRange(1, 1, 1, lastCol).setFontWeight('bold');
  outputSheet.getRange(lastRow, 1, 1, lastCol).setFontWeight('bold');

  outputSheet.getRange(1, 1, lastRow, lastCol).setBorder(true, true, true, true, true, true);

  outputSheet.getRange(2, 3, lastRow - 1, 1).setNumberFormat('#,##0');
  outputSheet.autoResizeColumns(1, lastCol);

  SpreadsheetApp.getUi().alert('改善版の集計が完了しました。');
}

改善後の出力結果

改善後は、販売場所ごとの客数・売上に加えて、備考もまとめて確認できるようにしました。

改善後 出力画面
スクリーンショット 2026-06-25 192723.png


元の集計と改善後の集計の違い

項目 元の集計 改善後の集計
客数合計 あり あり
売上合計 あり あり
備考まとめ なし あり
売上順の並び替え なし あり
合計行 なし あり
表の見やすさ 最低限 見出し・罫線・合計行を調整

客数と売上を集計するだけでも、販売場所ごとの傾向は見えます。

ただ、備考や並び順、合計行を加えることで、単なる集計表ではなく、次回販売に使いやすい一覧に近づきました。

image.png


改善して気づいたこと

今回作ったものは、かなり小さな集計ツールです。

販売場所ごとの客数と売上が見えるだけでも、どの場所にお客さまが多いのか、どの場所の売上が大きいのかは確認できます。

ただ、実際に見てもらうと、数字だけでなく、備考のような補足情報も一緒に見られる方が整理しやすいことが分かりました。

たとえば、

  • 何が足りなかったのか
  • どんな問い合わせがあったのか
  • 次回販売で気をつけることは何か

こうした情報が数字と一緒に見えることで、集計結果が次の行動につながりやすくなります。

数字だけを集計するのではなく、販売時のメモも一緒に扱うことが大事だと感じました。


次に業務で使う形へ近づけるなら

今回は、Googleスプレッドシート上の日報データをGASで集計してみました。

販売場所ごとに客数や売上をまとめること自体は、GASでも十分できそうです。
一方で、実際の業務に近づけるなら、どこまでをGASで行い、どこからを別の仕組みに任せるかは改めて考える必要があります。

たとえば、次に考えることは以下です。

次に考えること 理由
店舗ごとの絞り込み 複数店舗のデータを扱うため
日付・期間での絞り込み 週次・月次で確認しやすくするため
コースごとの集計 運行の見直しに使うため
備考の見せ方 次回販売に使いやすくするため
PDF日報への出力 報告資料として使いやすくするため
入力方法の検討 スプレッドシート入力のままでよいかを考えるため

今回のGASは、完成形というより、日報データを販売場所ごとに整理できるかを試すための入口です。

このままGASで広げる方法もあります。
ただ、入力のしやすさや販売担当者側での使い方まで考えると、AppSheetや別の入力フォームと組み合わせる方がよい場面もありそうです。


まとめ

今回は、Google Apps Scriptを使って、日報データを販売場所ごとに集計する仕組みを試しました。

客数と売上を販売場所ごとに整理するだけでも、場所ごとの傾向は見えやすくなります。
さらに、備考を一緒に扱うことで、数字だけでは分からない状況も確認しやすくなりました。

日報データは、ただ残すだけではあとから使いにくい。

販売場所ごとに整理し、数字とメモを一緒に見られる形にすると、次の販売や判断に使いやすくなる。

今回の小さな集計ツールで、その入口を確認できました。

2
0
0

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
2
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?