VBAでカテゴリごとに小計を自動挿入するには、A列の値が変わるタイミングで行を挿入し、直前グループのB列を合計するループ処理を使います。手作業で数式を入れる必要がなくなるため、集計ミスの防止と工数削減の両方に効果があります。
この記事では、次の内容を順番に解説します。
- 小計を自動挿入するマクロの基本コードと動作の仕組み
- 複数列を同時に集計する応用パターン
- 小計行に書式(背景色・太字)をつける方法
- 末尾に総合計を追加する方法
- よくある質問(小計が二重に入る・ソートとの組み合わせ等)
小計を自動挿入するマクロの基本コードと動作の仕組みを理解するには?
次のコードは、A列のカテゴリが変わるたびに小計行を挿入し、B列の数値を合計するものです。
Sub InsertSubtotals()
Dim i As Long
Dim startRow As Long
Dim lastRow As Long
Dim total As Double
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
startRow = 2 ' データの開始行
For i = startRow + 1 To lastRow + 1
If Cells(i, 1).Value <> Cells(i - 1, 1).Value Then
' 直前グループのB列を合計
total = WorksheetFunction.Sum(Range(Cells(startRow, 2), Cells(i - 1, 2)))
' 行を挿入して小計を書き込む
Rows(i).Insert
Cells(i, 1).Value = "小計"
Cells(i, 2).Value = total
' 次のグループの開始行を更新
startRow = i + 1
i = i + 1
lastRow = lastRow + 1
End If
Next i
MsgBox "小計の挿入が完了しました。"
End Sub
このコードのポイントは次の通りです。
- ループは後ろから操作せず上から進むため、行挿入のたびに
iとlastRowを1ずつ増やしてズレを補正している lastRow + 1までループすることで、最終グループの小計も確実に挿入されるstartRowを小計行の次に更新することで、次グループの集計範囲が正しく保たれる
実行前にデータがA列で並び順に並んでいること(同じカテゴリが連続していること)が前提です。バラバラのままだと、同じカテゴリに複数の小計が入ってしまいます。
複数列を同時に集計するには?
B列とC列など、複数の列を同時に合計したい場合は、列ごとに合計を取って書き込むだけです。
Sub InsertSubtotalsMultiCol()
Dim i As Long
Dim startRow As Long
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row
startRow = 2
For i = startRow + 1 To lastRow + 1
If Cells(i, 1).Value <> Cells(i - 1, 1).Value Then
Rows(i).Insert
Cells(i, 1).Value = "小計"
' B列とC列を同時に合計
Cells(i, 2).Value = WorksheetFunction.Sum(Range(Cells(startRow, 2), Cells(i - 1, 2)))
Cells(i, 3).Value = WorksheetFunction.Sum(Range(Cells(startRow, 3), Cells(i - 1, 3)))
startRow = i + 1
i = i + 1
lastRow = lastRow + 1
End If
Next i
MsgBox "小計の挿入が完了しました。"
End Sub
列の数だけ Cells(i, 列番号).Value = WorksheetFunction.Sum(...) を追加するだけなので、3列・4列への拡張も簡単です。
小計行に書式(背景色・太字)をつけるには?
小計行を視覚的に目立たせたい場合は、行挿入の直後に書式を適用します。
' 小計行に背景色と太字を設定する
With Rows(i)
.Interior.Color = RGB(220, 230, 241) ' 薄い青
.Font.Bold = True
End With
先ほどの基本コードの「行を挿入して小計を書き込む」部分の直後に追加するだけで適用されます。毎回同じ書式で整うため、資料としての見栄えが一定に保たれます。
末尾に総合計を追加するには?
小計行の挿入後に、全体の総合計を末尾に追加したい場合は、ループの後に次の処理を加えます。
' ループ終了後に総合計を追加
Dim totalRow As Long
totalRow = Cells(Rows.Count, 1).End(xlUp).Row + 1
Cells(totalRow, 1).Value = "総合計"
Cells(totalRow, 2).Value = WorksheetFunction.Sum(Range("B2:B" & totalRow - 1))
With Rows(totalRow)
.Interior.Color = RGB(189, 215, 238) ' やや濃い青
.Font.Bold = True
End With
小計行も含めて合計しないよう注意が必要な場合は、小計行を別カラムでフラグ管理するか、「小計」と入力したセルを除外する条件を追加してください。
まとめ
- カテゴリごとの小計挿入は A列の値変化を検知 → 行挿入 → 集計 → 開始行を更新 の流れで実装する
- 行挿入のたびに
iとlastRowを+1 してズレを補正するのが重要なポイント - 複数列への対応は 合計行を列番号ごとに追加 するだけ
- 小計行の書式は 挿入直後に
With Rows(i)でまとめて設定できる - 実行前にカテゴリ列でソートされていることが正しく動作するための前提条件
よくある質問
同じカテゴリに小計が複数入ってしまう場合は?
データがカテゴリ列でソートされていないことが原因です。同じカテゴリが飛び飛びになっていると、値が変わるたびに小計が入ってしまいます。マクロ実行前にA列で昇順ソートしてください。コードの冒頭に Range("A:B").Sort Key1:=Range("A2"), Order1:=xlAscending, Header:=xlYes を入れておくと自動でソートしてから処理できます。
マクロを2回実行すると小計が二重になる場合は?
既存の小計行を削除してから再実行する必要があります。マクロの冒頭で「小計」と書かれた行を削除する処理を入れておくと、何度実行しても正しい状態になります。
' 実行前に既存の小計行を削除する
Dim j As Long
For j = Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
If Cells(j, 1).Value = "小計" Then Rows(j).Delete
Next j
カテゴリ列がA列以外の場合は?
Cells(i, 1) の 1 の部分をカテゴリが入っている列番号に変えてください。たとえばB列(2列目)なら Cells(i, 2) に変更します。合計対象列も同様に列番号を合わせて修正してください。
小計行の「小計」という文字を変えたい場合は?
Cells(i, 1).Value = "小計" の文字列を任意の文字に変更するだけです。たとえば「合計」「subtotal」「グループ計」など、用途に合わせて変えてください。削除処理のチェック条件(If Cells(j, 1).Value = "小計")も合わせて変更することを忘れずに。
処理が遅い場合は?
行数が多いと行挿入のループが重くなることがあります。コードの冒頭に Application.ScreenUpdating = False と Application.Calculation = xlCalculationManual を追加し、処理後に元に戻すと大幅に速くなります。
' 処理前
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' (小計挿入の処理)
' 処理後
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
動画で学びたい方へ
「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。
VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。



