LoginSignup
0

More than 3 years have passed since last update.

Excelで日々の売り上げを月ごとに集計する方法

Posted at

はじめに

この記事では、Excelを使用して日々の売り上げを月ごとに自動集計するシートを作成してみたいと思います。
基本的には、SUMIF関数(作業列が必要)やピボットテーブルで実現できますが、VBAの勉強のため、自作の関数を作成してみます。

Excelのバージョン

使用しているExcelのバージョンは「Excel 2013」になります。

画面イメージ

以下のようなシートを作成しました。
ちなみに、左側の売り上げテーブルには「Amazon」という名前を付けています。

agg_01.png

SUMIF関数を使用した場合の関数

まず、売り上げテーブルに「(月)」という作業列を追加して、日付カラムのデータから何月のデータなのかを取得しています。[E5]セルには以下のような式を入力します。

=MONTH(B5)

そして、SUMIF関数を使用している[H5]セルには以下のような式を入力します。

=SUMIF(Amazon[(月)],[@月別],Amazon[金額])

これで、売り上げテーブルにデータが追加される度に、集計テーブル(左側)が自動的に更新されていきます。
この方法で特に問題はありませんが、1つ気になるのが作業列として「(月)」というカラムを追加しなければいけない、という点です。
それを解決するために以下のような関数を自作してみます。

自作の関数を使用した場合

VBAエディタを起動して、以下のような関数を作成します。

Option Explicit

Public Function AggMonthly(dummy As Object, MonthVal As Integer) As Integer
    Dim nTotal As Integer
    Dim row As ListRow
    Dim tbl As ListObject
    Dim dtTemp As Date

    ' dummyはAmazonテーブルが編集された時に、この関数が呼ばれるための仕掛け
    ' Application.Volatileの使用は避けたい

    Set tbl = ActiveSheet.ListObjects("Amazon")

    For Each row In tbl.ListRows
        dtTemp = row.Range(1)

        ' 対象となる月のデータを集計していく
        If Month(dtTemp) = MonthVal Then
            nTotal = nTotal + row.Range(3)
        End If

        ' 時系列に並んでいることが分かっている場合には最適化する
        ' そうでない場合には、以下の3行はコメントアウトする
        If Month(dtTemp) > MonthVal Then
            Exit For
        End If
    Next row

    AggMonthly = nTotal
End Function

そして、[K5]セルには以下のような式を入力します。

=AggMonthly(Amazon,[@月別])

これで、売り上げテーブルにデータが追加される度に、集計テーブル(中央)が自動的に更新されていきます。

コードの解説

AggMonthly関数の中では、Set tbl = ActiveSheet.ListObjects("Amazon")という式で売り上げテーブルを取得していますが、引数でもdummy As Objectという記述をしています。

これには2つの理由があります。

  • 関数の引数にListObject型が指定できなかった。何故かRange型になってしまいます。
  • 関数の引数として売り上げテーブルを渡していないと、テーブルが更新された時に、AggMonthly関数がコールされない。

このような理由により、ダミーの引数を渡しています。

これで、売り上げテーブルが追加される度に、集計テーブル(右側)が自動的に更新されていきます。

ピボットテーブルを使用した場合

ピボットテーブルを使えば、この手の集計は簡単に行えます。
ただし、売り上げテーブルにデータを追加してもリアルタイムでピボットテーブルが更新されません。
意図的に「ピボットテーブルの更新」コマンド(Alt+F5)を実行する必要があるようです。これはちょっと面倒です。
(もしかしてExcel2013だから?)

補足

日々の作業では、「今日の日付」、「ギフト券番号」、「金額」の3つを入力していきますが、私の場合にはペースターというツールを使用して半自動的に入力しています。
例えば、ギフト券取得のメールを受信すると、メールの本文に記載されている「金額」と「ギフト券番号」を連続してコピーしてしまいます。
これで、ペースターのクリップボード履歴にセットされます。
あとは、[B12]セルなどをアクティブにしてから、ペースターのキーストロークの発行タグを使用すると、今日の日付、ギフト券番号、金額を一発で入力できます。

ちなみに、ペースターのカスタムメニューには以下のように記述しています。

MenuItem.txt
Amazonギフト券の集計(ペースター)\tAlt+Ctrl+F9|
[Y1]/[T2]/[D2][!K "TAB"][C1][!K "TAB"][C2]
/E

まず、今日の日付を貼り付けて、[TAB]キーを押して、履歴の1番を貼り付けて、[TAB]キーを押して、履歴の2番を貼り付ける、、、という処理が行われます。
見て頂けると分かると思いますが、このコマンドにはショートカットキーが割り当ててありますので、メニューを表示する必要もありません。

操作イメージを動画にしてみましたので、参考にしてみて下さい。
YouTubeの動画(約30秒)

終わりに

今回のタスクを作成している時に困ったのが以下の点です。

AggMonthly関数の引数として渡している売り上げテーブルを、関数の方でListObject型として直接受け取れないということです。
もし、以下のように記述できたらもっとスマートなのになぁ・・・と思いました。

Function AggMonthly(tbl As ListObject, MonthVal As Integer) As Integer

もしかしたら、Excel2016以降では普通にできるのでしょうか?

それでは、この辺で失礼します。

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
What you can do with signing up
0