Excel VBA 逆引き集 | SUMIFS相当

Excel VBA
スポンサーリンク

SUMIFS相当

複数条件で合計する処理は「WorksheetFunction.SumIfs を直接呼ぶ」のが最短。大量データや柔軟条件が必要なら「配列+ループ」や「辞書で集計」が堅牢で速いです。初心者向けに、壊れにくいテンプレと例題をまとめました。


選び方の指針

  • 最短・安全: WorksheetFunction.SumIfs(Excel関数をVBAから呼ぶ)
  • 柔軟な比較(関数では表現しづらい条件): ループ+If(配列で高速化)
  • 大量データのグループ集計: 辞書(キーを複合条件にして合計)
  • 見た目抽出後に合計: AutoFilter+WorksheetFunction.Sum(手軽)

基本テンプレ:WorksheetFunction.SumIfs をそのまま使う

Sub SumIfs_Basic()
    '範囲例:A列=部署、B列=日付、C列=レベル、D列=金額
    Dim sumRange As Range, deptRange As Range, dateRange As Range, levelRange As Range
    Set sumRange  = Range("D2:D10000")
    Set deptRange = Range("A2:A10000")
    Set dateRange = Range("B2:B10000")
    Set levelRange= Range("C2:C10000")

    Dim dept As String: dept = "営業"
    Dim startD As Date: startD = DateSerial(2025, 1, 1)
    Dim endD   As Date: endD   = DateSerial(2025, 1, 31)
    Dim level  As String: level = "ERROR"

    Dim total As Double
    total = Application.WorksheetFunction.SumIfs( _
        sumRange, _
        deptRange, dept, _
        dateRange, ">=" & CLng(startD), _
        dateRange, "<=" & CLng(endD), _
        levelRange, level)

    Range("H2").Value = total
End Sub
VB
  • ポイント:
    • 日付比較はシリアルで渡す: ">=" & CLng(startD) のように文字列式で指定。
    • 複数条件は「範囲, 条件」のペアを続けて渡す。
    • テキスト一致はそのまま文字列でOK。部分一致は関数では対応外なので後述のループ法へ。

応用:条件をセルから読み取って可変にする

Sub SumIfs_FromInputCells()
    Dim sumR As Range, depR As Range, datR As Range, levR As Range
    Set sumR = Range("D2:D100000")
    Set depR = Range("A2:A100000")
    Set datR = Range("B2:B100000")
    Set levR = Range("C2:C100000")

    Dim dept As String: dept = Range("F2").Value         '部署
    Dim startD As Date: startD = Range("F3").Value       '開始日
    Dim endD As Date:   endD   = Range("F4").Value       '終了日
    Dim levels As Variant: levels = Array("ERROR", "WARN") 'OR条件例

    Dim total As Double, i As Long
    For i = LBound(levels) To UBound(levels)
        total = total + Application.WorksheetFunction.SumIfs( _
            sumR, depR, dept, datR, ">=" & CLng(startD), datR, "<=" & CLng(endD), levR, levels(i))
    Next

    Range("H2").Value = total
End Sub
VB
  • ポイント:
    • SUMIFSは1フィールドのOR条件が弱いので、配列で回して「合算」するのが簡単。
    • 条件セルから読み取ると運用が楽。

柔軟条件:配列+ループで「SUMIFS相当」を自作

Sub Sum_ByLoop_Flexible()
    Dim rg As Range: Set rg = Range("A1").CurrentRegion '表全体
    Dim v As Variant: v = rg.Value                      '配列へ(爆速の基本)

    Dim dept As String: dept = "営業"                   'A列:部署(部分一致OK)
    Dim startD As Date: startD = DateSerial(2025, 1, 1) 'B列:日付
    Dim endD As Date:   endD   = DateSerial(2025, 1, 31)
    Dim levels As Object: Set levels = CreateObject("Scripting.Dictionary")
    levels("ERROR") = True: levels("WARN") = True       'C列:レベル(OR対応)
    Dim minAmt As Double: minAmt = 10000                'D列:金額(下限)

    Dim sumV As Double, i As Long
    For i = 2 To UBound(v, 1)                           '2行目から(ヘッダー除外)
        Dim a As String: a = CStr(v(i, 1))              '部署
        Dim b As Date:   b = v(i, 2)                    '日付
        Dim c As String: c = CStr(v(i, 3))              'レベル
        Dim d As Double: d = Val(v(i, 4))               '金額

        If InStr(1, a, dept, vbTextCompare) > 0 _       '部分一致
           And b >= startD And b <= endD _
           And levels.Exists(UCase$(c)) _
           And d >= minAmt Then
            sumV = sumV + d
        End If
    Next

    Range("H2").Value = sumV
End Sub
VB
  • ポイント:
    • 部分一致や複雑条件(大小文字無視、範囲外除外など)を自在に書ける。
    • 範囲→配列→一括判定→結果のみ書き戻しが高速。

大量データのグループ集計(辞書でSUMIFS風)

Sub Sum_GroupBy_CompositeKey()
    'A=部署、B=日付、C=レベル、D=金額
    Dim rg As Range: Set rg = Range("A1").CurrentRegion
    Dim v As Variant: v = rg.Value

    'グルーピングキー:部署 + 年月(yyyymm) + レベル
    Dim dict As Object: Set dict = CreateObject("Scripting.Dictionary")
    Dim i As Long, key As String

    For i = 2 To UBound(v, 1)
        Dim dept As String: dept = UCase$(CStr(v(i, 1)))
        Dim ym As String: ym = Format$(v(i, 2), "yyyymm")
        Dim level As String: level = UCase$(CStr(v(i, 3)))
        key = dept & "|" & ym & "|" & level

        If dict.Exists(key) Then
            dict(key) = dict(key) + Val(v(i, 4))
        Else
            dict.Add key, Val(v(i, 4))
        End If
    Next

    '結果の書き出し(キー分解して表形式に)
    Dim k As Variant, rOut As Long: rOut = 2
    With Worksheets("集計")
        .Range("A1:C1").Value = Array("部署", "年月", "レベル")
        .Range("D1").Value = "合計"
        For Each k In dict.Keys
            Dim parts() As String: parts = Split(k, "|")
            .Cells(rOut, 1).Value = parts(0)
            .Cells(rOut, 2).Value = parts(1)
            .Cells(rOut, 3).Value = parts(2)
            .Cells(rOut, 4).Value = dict(k)
            rOut = rOut + 1
        Next
    End With
End Sub
VB
  • ポイント:
    • SUMIFSでは難しい「複数軸での一括グループ集計」が一瞬でできる。
    • キーは型揺れ防止のため UCase などで正規化。

AutoFilterで絞ってから合計(見た目優先の最短)

Sub FilterThenSum()
    With Range("A1").CurrentRegion
        .AutoFilter Field:=1, Criteria1:="営業"
        .AutoFilter Field:=3, Criteria1:=Array("ERROR", "WARN"), Operator:=xlFilterValues
        .AutoFilter Field:=2, Operator:=xlAnd, Criteria1:=">=1/1/2025", Criteria2:="<=1/31/2025"

        Dim vis As Range
        On Error Resume Next
        Set vis = .Columns(4).SpecialCells(xlCellTypeVisible) 'D列の可視セル
        On Error GoTo 0
        If Not vis Is Nothing Then
            Range("H2").Value = Application.WorksheetFunction.Sum(vis)
        End If

        .AutoFilter '解除
    End With
End Sub
VB
  • ポイント:
    • 見た目で確認しながら合計を取りたいときに便利。
    • フィルタ解除を忘れない。

安全・高速ラップ(大量時の基本)

Sub SafeWrapStart()
    Application.ScreenUpdating = False
    Application.EnableEvents = False
    Application.Calculation = xlCalculationManual
End Sub

Sub SafeWrapEnd()
    Application.Calculation = xlCalculationAutomatic
    Application.EnableEvents = True
    Application.ScreenUpdating = True
End Sub
VB
  • ポイント:
    • 取り込み前後に挟むだけで体感速度が改善。失敗時も復帰できるよう On Error GoTo Cleanup を併用。

よくある落とし穴と対策

  • 日付条件がうまく効かない
    • 対策: SUMIFSでは ">=" & CLng(date) のようにシリアル化して渡す。セルが文字列日付なら事前にDate型へ変換。
  • OR条件(同じフィールドに複数値)
    • 対策: SUMIFSを値ごとに回して合算、またはループ法で辞書に集計。
  • 部分一致が必要
    • 対策: SUMIFSは完全一致用。部分一致は配列+InStrで自作判定へ。
  • セル往復で遅い
    • 対策: 範囲→配列→判定→一括書き戻しが鉄板。辞書でグループ化するとさらに速い。
  • 型揺れで取りこぼし
    • 対策: 文字列は UCase/CStr、日付は Date、数値は Val で正規化。連結キーは "|" など見出しにない文字で区切る。

例題で練習

'例1:営業×2025年1月×ERRORの金額合計をH2へ(SUMIFS)
Sub Example_SumIfs()
    Call SumIfs_Basic
End Sub

'例2:営業(部分一致)×2025年1月×ERROR/WARN×金額>=1万の合計(ループ法)
Sub Example_FlexibleSum()
    Call Sum_ByLoop_Flexible
End Sub

'例3:部署×年月×レベルの多軸グループ集計(辞書)
Sub Example_GroupSum()
    Call Sum_GroupBy_CompositeKey
End Sub
VB
タイトルとURLをコピーしました