リレーショナルデータベースのように使う


実務で使用されるリストでは、売上台帳と商品台帳が分離していることがあります。売上台帳には商品コードだけを記入し、該当する商品名は商品台帳から参照するような使い方です。こうした使い方は、Access などのリレーショナル データベースが本領を発揮しますが、Excel でも実現することは可能です。ただし、あくまでも「できる」という話で、VBA の深い知識が必要になったり、メンテナンスが困難になる場合もあります。数千件程度のリストなら問題ありませんが、本格的なデータベースを構築するのでしたら、Access などの使用を検討した方がいいでしょう。「餅は餅屋」です。ここでは、今まで使ってきたサンプルを 3 つのシートに分けて考えます。

最初の [売上データ] シートには、次のようなデータが入力されています。商品に関するデータは [商品コード] だけで、商品名はありません。

2 番目の [商品マスター] は次の通りです。

[売上データ] シートから「3月5日から3月11日の間に納品した」データだけを [抽出結果] シートに抽出します。そのとき、[商品マスター] シートで商品名を調べます。

Sub Sample05()
    Dim i As Long
    ''オートフィルタで抽出
    With Worksheets("売上データ").Range("A1")
        .AutoFilter Field:=3, Criteria1:=">=3月5日", Operator:=xlAnd, Criteria2:="<=3月11日"
        .CurrentRegion.SpecialCells(xlVisible).Copy Worksheets("抽出結果").Range("A1")
        .AutoFilter
    End With
    
    With Worksheets("抽出結果")
        ''[抽出結果]シートに「商品名」フィールドを追加
        .Columns("B:B").Insert Shift:=xlToRight
        .Range("B1") = "商品名"
        With .Range("A2")
            ''商品名の表引き
            Do While .Offset(i, 0) <> ""
                .Offset(i, 1) = WorksheetFunction.VLookup(.Offset(i, 0), _
                                         Worksheets("商品マスター").Range("A1:B8"), 2)
                i = i + 1
            Loop
        End With
        .Columns("A:D").EntireColumn.AutoFit
    End With
End Sub

前半はオートフィルタによる抽出です。検索する条件の日付をユーザーから受け取るようにすると実用的ですね。

オートフィルタの結果を [抽出結果] シートに転記したら、[抽出結果] シートの B 列に空列を挿入します。ここが「商品名」フィールドです。

次にリレーショナル処理です。Excel のワークシート関数には、指定したキーをリスト内で検索して該当するデータを返す VLOOKUP 関数というスグレモノがあります。まさにリレーショナルな処理にぴったりですね。VLOOKUP関数の使い方に関しては、この関数はこう使え!の「VLOOKUP関数」を参照してください。

ここでは、Offset プロパティの使い方がポイントです。[抽出結果] シートのセル A2 が .Offset(0, 0) です。したがって、.Offset(1, 0) はセル A2 から 1 行下がったセル A3 を表します。最後に [抽出結果] シートを整形して完了です。

Sample05 では、1 度も「Select していない」点がポイントです。Select すると画面がちらつきますし、速度も著しく低下します。