ディクショナリオブジェクトを使用した集計処理

前のページではディクショナリオブジェクトを使用した重複データの削除を取り上げました。そのサンプルを見てわかった方もいると思いますが、重複データ処理と言いつつもキー項目の出現回数をカウントしていたので、集計処理と見ることもできます。

前ページでは、出現回数のカウント値を重複の判定に使用するだけでしたが、このページでは”集計”を少し掘り下げ、集計項目が複数ある場合の説明をしていきたいと思います。

スポンサーリンク

複数の集計処理

ここでは簡単な例として、入力データを集約し、データ毎に出現回数、合計値、平均値を求めることを考えます。平均値は合計値と出現回数により求められるため、実質集計するのはデータの出現回数と合計値の2つとなります。

集計対象データと集計結果のイメージ

入力データ
入力データ
集計結果
集計結果

出現回数、合計値、平均などはワークシート関数を使えば簡単に集計できますが、集計の条件が複雑になってくるとワークシート関数では対応できなくなってきます。このような場合にこのディクショナリオブジェクトを使用した集計方法が生きてきます。

集計項目毎にディクショナリオブジェクトを用意する

集計項目が複数ある場合の一番単純な対処方法は集計項目毎にディクショナリオブジェクトを生成することです。以下の例は、出現回数カウント用と金額合計値用に2つのディクショナリオブジェクトを使用して集計を行う方法です。

Sub sample_dc014_01()
    Dim dco_Count   As Object
    Dim dco_Sum     As Object
    Dim wRow        As Long
    Dim wKey        As String
    Dim varKeys     As Variant
    Dim var         As Variant
    Dim i           As Long
    'エクセルの列
    Const COL_I_ITEM = 1
    Const COL_I_PRICE = 2
    Const COL_O_ITEM = 4
    Const COL_O_CNT = 5
    Const COL_O_SUM = 6
    Const COL_O_AVG = 7

    'ディクショナリオブジェクトの生成
    Set dco_Count = CreateObject("Scripting.Dictionary")
    Set dco_Sum = CreateObject("Scripting.Dictionary")

    wRow = 3    '入力データ開始行
    Do Until Cells(wRow, COL_I_ITEM).Value = ""
        wKey = Cells(wRow, COL_I_ITEM).Value
        If dco_Count.Exists(wKey) Then
            'カウントアップ
            dco_Count.Item(wKey) = CLng(dco_Count.Item(wKey)) + 1
            '金額加算
            dco_Sum.Item(wKey) = CLng(dco_Sum.Item(wKey)) + _
                                 CLng(Cells(wRow, COL_I_PRICE).Value)
        Else
            '未登録の場合は新規登録
            dco_Count.Add wKey, 1
            dco_Sum.Add wKey, Cells(wRow, COL_I_PRICE).Value
        End If

        wRow = wRow + 1
    Loop

    'キー項目の配列を取得
    varKeys = dco_Count.Keys

    wRow = 3    '出力データ開始行
    '集計項目の表示
    For Each var In varKeys
        Cells(wRow, COL_O_ITEM).Value = var
        Cells(wRow, COL_O_CNT).Value = dco_Count.Item(var)
        Cells(wRow, COL_O_SUM).Value = dco_Sum.Item(var)
        Cells(wRow, COL_O_AVG).Value = _
            dco_Sum.Item(var) / dco_Count.Item(var)
        wRow = wRow + 1
    Next

    'ディクショナリオブジェクトの破棄
    Set dco_Count = Nothing
    Set dco_Sum = Nothing
End Sub

 Setステートメント Do…Loop  For Each…Next 
LBound、UBound関数  データ型変換関数

下図テスト用のワークシートになります。

入力データ
入力データ

上記サンプルマクロを実行すると、右側に集計結果が表示されます。

集計結果
集計結果

複数の集計項目を配列で保持する

この例では、ディクショナリオブジェクトを1つだけ使用し、ディクショナリオブジェクトの値に出現回数と合計値を配列として格納する方法になります。この方法は集計項目がいくら増えてもディクショナリオブジェクト1つで済むのが利点です。

Sub sample_dc014_02()
    Dim dco         As Object
    Dim wRow        As Long
    Dim wKey        As String
    Dim varKeys     As Variant
    Dim var         As Variant
    Dim varValues   As Variant
    Dim i           As Long
    'エクセルの列
    Const COL_I_ITEM = 1
    Const COL_I_PRICE = 2
    Const COL_O_ITEM = 4
    Const COL_O_CNT = 5
    Const COL_O_SUM = 6
    Const COL_O_AVG = 7
    'Value値配列のインデックス
    Const IDX_CNT = 0
    Const IDX_SUM = 1

    'ディクショナリオブジェクトの生成
    Set dco = CreateObject("Scripting.Dictionary")

    wRow = 3    '入力データ開始行
    Do Until Cells(wRow, COL_I_ITEM).Value = ""
        wKey = Cells(wRow, COL_I_ITEM).Value
        If dco.Exists(wKey) Then
            'キーに対応する配列を取得
            varValues = dco.Item(wKey)
            'カウントアップ
            varValues(IDX_CNT) = CLng(varValues(IDX_CNT)) + 1
            '金額加算
            varValues(IDX_SUM) = CLng(varValues(IDX_SUM)) + _
                                 CLng(Cells(wRow, COL_I_PRICE).Value)
            dco.Item(wKey) = varValues
        Else
            '未登録の場合は
            'カウント初期値と金額を配列として新規登録
            dco.Add wKey, Array(1, Cells(wRow, COL_I_PRICE).Value)
        End If

        wRow = wRow + 1
    Loop

    'キー項目の配列を取得
    varKeys = dco.Keys

    wRow = 3    '出力データ開始行
    '集計項目の表示
    For Each var In varKeys
        varValues = dco.Item(var)
        Cells(wRow, COL_O_ITEM).Value = var
        Cells(wRow, COL_O_CNT).Value = varValues(IDX_CNT)
        Cells(wRow, COL_O_SUM).Value = varValues(IDX_SUM)
        Cells(wRow, COL_O_AVG).Value = _
            varValues(IDX_SUM) / varValues(IDX_CNT)
        wRow = wRow + 1
    Next

    'ディクショナリオブジェクトの破棄
    Set dco = Nothing
End Sub

 Setステートメント Do…Loop  For Each…Next 
Array関数  LBound、UBound関数  データ型変換関数

実行結果は sample_dc014_01 と同じになります。

 ディクショナリオブジェクトのプロパティ・メソッド

タイトルとURLをコピーしました