
ACCESSのクエリやVBAで、特定のテーブルの値を参照して計算したいけれど、方法がわからなくて困ったことはありませんか?
ACCESSのある値を元に、他のテーブルの値を参照したい時に使用するのがDLookUp関数です。
EXCELではVLookUp関数が同じような位置づけですね。
今日は非常に使用範囲の広い、DLookUp関数の使い方を解説していきましょう。
こんにちは。
はこにわガジェット (@hakoniwagadget) です。
ACCESSを使った売上管理、顧客管理などのデータベース開発を行っています。
ACCESSは使いこなすために少しスキルが必要なものの、うまく活用すればExcelよりも業務の効率化が図れます。
この記事ではACCESSをもっと使いこなしたい方向けにACCESSの関数をご紹介していきます。
DLookUp関数の構文
最初にDLookUp関数の構文を示します。
DLookUp ( 値を返すフィールド , レコード セット , データ範囲を制限する文字列式 )
引数の指定がすこし複雑なのでいくつか使用例を挙げます。
以下のMST_顧客テーブルと、MST_社員テーブルをサンプルとして準備しました。
MST_顧客

MST_社員

MST_顧客テーブルの一番右の担当社員IDは、MST_社員テーブルの社員IDとリレーションをしています。
それでは、使用例を解説します。
1.MST_社員テーブルから社員IDが3番の人の社員名を参照したい時
DLookUp ( “社員名” , “MST_社員” , “社員ID = 3” )
この場合は、一つ目の引数が表示したいフィールド「社員名」となります。2つ目は参照するテーブル名「MST_社員」で、3つ目は社員IDが3という条件指定になります。
すべての引数は”(ダブルクォーテーション)で囲って文字列として扱う必要があります。
2.MST_顧客テーブルから顧客IDが5番の人の登録日を参照したい時
DLookUp ( “登録日” , “MST_顧客” , “顧客ID = 5” )
この場合は、一つ目の引数が表示したいフィールド「登録日」で、2つ目は参照するテーブル名「MST_顧客」です。3つ目は顧客IDが5という条件指定になります。
3.MST_社員テーブルから、顧客IDが5番の人を担当している社員の社員名を参照したい時
DLookUp ( “社員名” , “MST_社員” , “社員ID = ” & DLookup ( “担当社員ID” , “MST_顧客” , “顧客ID = 5 ” )
これ少し複雑です。DLookUp関数を二重に組み合わせています。
まず、外側のDLookUp関数では、1つ目の引数に「社員名」、2つ目の引数に「MST_社員」を指定します。
ここまでは良いのですが、MST_社員の中の社員の指定方法が、「顧客IDが5番の人を担当している社員」なので、これはMST_社員テーブルだけでは判断できません。
そこで、条件式の社員IDを指定する際に再度DLookup関数を使用し、MST_顧客テーブルから顧客IDが5のレコードの担当社員IDを呼び出しています。
このように、DLookUpを使用する際は、3つ目の引数であるデータ範囲を制限する文字列式が非常に重要です。
クエリでの使用例
ここまでは抽出条件の値を固定で指定しました。
しかし、実務では抽出条件に他のテーブルの値を参照させる利用方法が一般的です。
実際に、DLookUp関数をクエリで使用する場合の例を示します。
先ほどの2つのテーブルを使って、MST_顧客の情報に、担当社員名を付与したクエリを作成してみましょう。
クエリをデザインビューで開き、上段のフィールドリストに「MST_顧客」を配置します。
下段のデザイングリッドでは、新規のフィールドに以下のように設定します。

クエリのフィールド
担当社員名: DLookUp("社員名","MST_社員","社員ID = " & [担当社員ID])
クエリでは、既存のテーブルにあるフィールドを表示する以外に、上記のように新しいフィールドを計算式で作成することが可能です。
この際、「:」で区切った左側(今回でいう「担当社員名」)がフィールド名になります。
一方、「:」の右側が計算式です。
今回はDLookup関数を使っています。
「MST_顧客」テーブルの「担当社員ID」を基に、「MST_社員」テーブルから「社員ID」が一致するレコードを探し、その「社員名」を表示する、という式です。
データシートビューでクエリの結果を見てみましょう。

このように、顧客ごとの担当社員を表示することができました。
ここで記載方法について2点ほど注意点があります。
クエリのフィールド名を使用する場合は[]で囲う
上記の式で最後の商品IDだけが[]で囲われています。
これは何を示しているかというと、このクエリにある「担当社員ID」を使いなさい、という指示なのです。
つまり、クエリで参照している「MST_顧客」の「担当社員ID」ですね。
DookUp関数等をクエリで利用する際、そのクエリ自身にあるフィールド名を参照する場合は[]で囲うことを覚えておきましょう。
条件式は””で囲うが、値を参照する部分は””から除外する
条件式部分は “社員ID = ” & [担当社員ID]と指定しています。
「”」を使っているのは、条件式を文字列型として認識させるためです。
では、なぜ
“社員ID = [担当社員ID]”
と書かないのでしょうか?
それは、 “社員ID = [担当社員ID]” と書いてしまうと、[担当社員ID]の部分をそのままテキストとしてACCESSが読んでしまうためです。
この部分はクエリにある担当社員IDの値に読み替えてもらわなければいけません。
そのため、この部分はテキストとして認識させないように、””の範囲から除外しているのです。
この書き方は非常によく使いますので、覚えておくと便利です。
しかし、実はこの使い方をすることはあまりありません。
なぜなら、クエリでリレーションを設定したほうが早いからです。
つまり、選択クエリでこのように設定すれば同じことができます。

上記の例では、MST_顧客とMST_社員を社員IDでリレーションさせています。
2つのテーブルの間に社員IDを結ぶ線が引かれているのがその証です。
そのうえで、クエリの下段(デザイングリッド)にMST_社員の社員名を表示させています。
これにより、MST_顧客の担当社員IDに紐づいた社員名が、MST_社員から参照されて表示されるのです。
クエリでDLookpUp関数を使用するのは、条件に応じて参照先を変えるためにIIF関数と組み合わせて使用する場合など、単純なテーブル間のリレーションでは解決しない、複雑な場合が多いでしょう。
VBAでの使用例
DLookUp関数は選択クエリで使用するよりは、VBAで使用するケースの方が多いでしょう。
特定のテーブルの値を元に他のテーブルの値を参照したいが、クエリを作成して呼び出すほどでもなくDLookUp関数で呼び出すというケースです。
それではフォームでの利用例として、顧客IDを入力すると顧客名を表示する機能を作成しましょう。

このフォームでは、顧客IDを更新した際に、顧客名に値を表示するようにしました。
そのため、フォームをデザインビューで表示すると、顧客IDの更新後処理にイベントプロシージャを設定しています。

設定したイベントプロシージャの内容は以下の通りです。
Private Sub 顧客ID_AfterUpdate()
Me!顧客名 = DLookup("顧客名", "MST_顧客", "顧客ID = " & Me!顧客ID)
End Sub
顧客IDが更新されると、Me!顧客名、つまりフォーム上の顧客名テキストボックスに、DLookUp関数を用いて求めた顧客名が表示されます。
DLookUp関数でMST_顧客テーブルから、顧客IDがフォームの顧客IDと一致するレコードを抽出し、顧客名フィールドの値を返す、という指定をしています。
DLookupの3つ目の引数である条件をフォームから指定をする際は、カレントフォームの値を参照する「Me」を使うと便利です。
ここでいうMeは、現在利用している「顧客名呼び出し」フォームを指しています。
Meの使い方については下記の記事に書いていますので興味がある方はご覧ください。

では、実際にフォームビューで動作を確認してみましょう。

このように、顧客IDに数値を入力してエンターを押すと、顧客名に対象顧客の顧客名が表示されました。
DLookUp関数を利用する際はNullに注意
このように便利なDLookUp関数ですが、利用にあたって中止すべき点があります。
それは、抽出条件に用いた値がNullの場合です。
例えば、先ほど作成した顧客名呼び出しフォームで、顧客IDを空白にしてみましょう。

すると、以下のエラーが発生します。

これは、DLookUp関数の引数に入力した値がNullのため、DLookUp関数を正しく処理できないというエラーです。
“顧客ID = ” & Me!顧客ID、の最後のMe!顧客IDの部分がNullだとDLookUp関数は動作しません。
こうしたエラーがユーザーの操作で簡単に出てしまうようではシステムとしての使い勝手が悪くなってしまいます。
そのため、DLookUp関数を利用する際は、抽出条件に指定する値がNullであれば処理をスキップするようにしておきましょう。
例えば、先ほどのイベントプロシージャを以下のように修正します。
Private Sub 顧客ID_AfterUpdate()
If Me!顧客ID <> "" Or IsNull(Me!顧客ID) = False Then
Me!顧客名 = DLookup("顧客名", "MST_顧客", "顧客ID = " & Me!顧客ID)
Else
MsgBox "顧客IDを空白にすると顧客名を表示することができません。", vbCritical + vbOKOnly, "顧客ID空白"
End If
End Sub
If関数を使って、DLookUp関数を適用する前に、顧客IDテキストボックスが空白でないかをチェックしています。
ACCESSでは空白とNullは別物として扱われますので、どちらのケースでも対応できるように、
If Me!顧客ID <> "" Or IsNull(Me!顧客ID) = False Then
という条件にしています。
全社が空白でない、後者がNullでない、という意味です。
顧客IDに値が入っていることが確認できれば従来通りDLookUp関数で顧客名を表示し、値が入っていなければ以下のエラーメッセージを出します。

こうすればユーザーも戸惑うことなく、何が悪かったのか理解することができますね。
以上、ACCESSでDLookup関数を使って他のテーブルの値を参照する方法をご紹介しました。
この記事の内容を実際に試したい方へ
本記事の内容を実際にACCESSを動かしながら確認したいという方向けに、記事で紹介した機能が実装されたサンプルファイルを販売しています。記事内で解説しているテーブル、クエリ、フォーム、レポート、VBAのプロシージャなどをそのまま動く形で実装しました。
学習用としてはもちろん、加工して自社業務に利用することも可能です。
ご興味のある方は以下からご覧ください。

ACCESSを使いこなせば、業務の効率化や自動化が実現できます。
しかし、自分でACCESSを学ぶには時間がない、難しそうで不安、という方も多いでしょう。
そんな時は、ACCESS開発歴20年以上、過去に300以上のACCESSデータベースの開発・修正実績のあるはこにわガジェット(@hakoniwagadget)にお任せください。
ACCESSの新規開発、既存のACCESSの修正、ACCESSの操作レッスンなど様々なサービスをご提供しています。
ご興味のある方は下記のサービス一覧をご覧ください。

最後までお読みいただき、ありがとうございました。
