部分合計の作成
「グループごとに合計行を差し込む」「フィルタ後の表示分だけを合計する」「テーブルで合計行を出す」などの場面を、初心者向けに最短コードでまとめました。Excelの“部分合計”は大きく3系統です。Range.Subtotal(行を差し込む自動集計)、ワークシート関数SUBTOTAL(見えているセルの集計)、ListObject(テーブル)の合計行。用途に合わせて使い分けましょう。
基本1:行を差し込む「自動・見た目の部分合計」
Sub Subtotal_InsertRows_Basic()
'見出しがA1、表はA1からの連続領域
Dim rg As Range
Set rg = Range("A1").CurrentRegion
'前提:集計基準列(例:部門)が事前にソート済み
rg.Sort Key1:=rg.Columns(2), Order1:=xlAscending, Header:=xlYes
'部分合計を挿入(部門=2列目でグループ、金額=5列目を合計)
rg.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(5), _
Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End Sub
VB- ポイント:
- GroupBy: 見出しから数えて「何列目」でグループ化するか。
- TotalList: 集計したい列の番号配列(複数列OK)。
- ソート必須: GroupBy列を事前に並べておくと意図通りにまとまる。
基本2:フィルタや手動非表示に強い「SUBTOTAL関数」
Sub Subtotal_VisibleOnly()
Dim last As Long
last = Cells(Rows.Count, "E").End(xlUp).Row '金額=E列
'見出しの右(G2)に「表示中だけ」の合計を出す
Range("G2").Formula = "=SUBTOTAL(9,E2:E" & last & ")"
End Sub
VB- ポイント:
- 9(SUM): 非表示行も含めた合計。
- 109(SUM): フィルタや手動非表示を除外して「見えているセルだけ」合計。
- VBAで値取得: WorksheetFunction.Subtotal(9, Range(“E2:E” & last)) でもOK。
目的別テンプレート
'1) フィルタで表示中だけの金額合計をセルへ(数式不要で即値)
Sub Sum_VisibleToCell()
Dim last As Long, s As Double
last = Cells(Rows.Count, "E").End(xlUp).Row
s = Application.WorksheetFunction.Subtotal(109, Range("E2:E" & last))
Range("G2").Value = s
End Sub
'2) 複数列を同時に部分合計挿入(部門ごとに数量・金額)
Sub Subtotal_InsertRows_MultiColumns()
Dim rg As Range: Set rg = Range("A1").CurrentRegion
rg.Sort Key1:=rg.Columns(2), Order1:=xlAscending, Header:=xlYes
rg.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(4, 5), _
Replace:=True, PageBreaks:=False, SummaryBelowData:=True
End Sub
'3) 部門ごとに小計行+最後に総合計行を追加
Sub Subtotal_WithGrandTotal()
Dim rg As Range: Set rg = Range("A1").CurrentRegion
rg.Sort Key1:=rg.Columns(2), Order1:=xlAscending, Header:=xlYes
rg.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(5), _
Replace:=True, PageBreaks:=False, SummaryBelowData:=True
'最終行の次に総合計を出す(見出し除く全E列)
Dim last As Long: last = Cells(Rows.Count, "A").End(xlUp).Row
Cells(last + 1, "D").Value = "総合計"
Cells(last + 1, "E").Formula = "=SUBTOTAL(9,E2:E" & last & ")"
End Sub
VB- ラベルのヒント:
- 109の意味: フィルタなどで非表示のセルを除外。
- Replace:=True: 既存の部分合計があれば置き換え。二重小計防止。
- Grand total: SUBTOTAL(9, …) は非表示も含めた全体合計に便利。
テーブルでの部分合計(ListObject)
Sub Subtotal_ListObject_TotalsRow()
Dim lo As ListObject
Set lo = ActiveSheet.ListObjects("売上テーブル")
'合計行(TotalsRow)を表示
lo.ShowTotals = True
'金額列の合計を設定(列名で指定)
lo.ListColumns("金額").TotalsCalculation = xlTotalsCalculationSum
End Sub
VB- ポイント:
- TotalsRow: テーブル下部に小計・平均などを表示。
- 列名指定: 列を入れ替えても壊れにくい。
- フィルタ連動: テーブルのフィルタ結果に連動して合計が変わる。
例題で練習
例題1:部門ごとの金額小計行を自動挿入して印刷
Sub Example_SubtotalAndPrint()
Dim rg As Range: Set rg = Range("A1").CurrentRegion
rg.Sort Key1:=rg.Columns(2), Order1:=xlAscending, Header:=xlYes
rg.Subtotal GroupBy:=2, Function:=xlSum, TotalList:=Array(5), _
Replace:=True, PageBreaks:=True, SummaryBelowData:=True
ActiveSheet.PrintOut
End Sub
VB例題2:今月の表示行だけ金額合計をG2へ(即値)
Sub Example_VisibleThisMonthSum()
Dim rg As Range: Set rg = Range("A1").CurrentRegion
Dim d1 As Date, d2 As Date
d1 = DateSerial(Year(Date), Month(Date), 1)
d2 = DateSerial(Year(Date), Month(Date) + 1, 0)
rg.AutoFilter Field:=4, Criteria1:=">=" & d1, Operator:=xlAnd, Criteria2:="<=" & d2
Dim s As Double
s = Application.WorksheetFunction.Subtotal(109, rg.Offset(1).Resize(rg.Rows.Count - 1).Columns(5))
Range("G2").Value = s
End Sub
VB例題3:テーブル右下に合計行を出して金額合計
Sub Example_TableTotalsRow()
Dim lo As ListObject: Set lo = ActiveSheet.ListObjects("売上テーブル")
lo.ShowTotals = True
lo.ListColumns("金額").TotalsCalculation = xlTotalsCalculationSum
End Sub
VBSUBTOTAL の関数番号(よく使うもの)
- 9(SUM): 合計。
- 109(SUM): 合計(非表示を除外)。
- 1(AVERAGE)/101: 平均(101は非表示除外)。
- 2(COUNT)/102: 数値カウント。
- 3(COUNTA)/103: 非空白カウント。
100番台は「フィルタや手動非表示のセルを除外」するモード。
実務の落とし穴と対策
- 並べ替え忘れで小計が分散: GroupBy列は事前にソートしてから Range.Subtotal を実行。
- 二重小計の混在: Replace:=True で置き換え、不要な小計行は ClearOutline/再適用。
- Hiddenの扱い違い: SUBTOTALの9は非表示も含む、109は除外。用途に合わせて選ぶ。
- フィルタ0件でエラー: SpecialCellsや対象範囲のサイズが0の可能性に備え、Nothingチェックや件数判定を入れる。
- テーブルと通常範囲の違い: テーブルは TotalsRow を使うのが安全。通常の部分合計挿入は表構造を物理的に変える。
