ACCESS VBAで処理を作成する際、指定したNullになっていると思わぬエラーが発生してしまいます。
そのため、処理の前にNullか否かの判定を行うことが一般的です。
この際、日付型のデータのNull判定には少しコツが必要です。
今回は、日付のNullを判定する方法をご紹介します。
こんにちは。
はこにわガジェット (@hakoniwagadget) です。
ACCESSを使った売上管理、顧客管理などのデータベース開発を行っています。
ACCESSは基本機能だけでも十分便利ですが、VBAを使うことで格段に使いやすいデータベースを作成可能です。
この記事ではACCESSでのVBAの使い方をご紹介していきます。
プログラムの記述方法によって判別方法が異なる
VBAで日付型のフィールドがNullか否かを判別する際にややこしいのは、プログラムの記述方法によって判別方法が異なるということです。
主にVBAでは以下の2つの方法で判定を行います。
- if ~ thenの条件分岐
- ADOのfilterプロパティ
このそれぞれでNullの判別方法が異なるのです。
以下に判定方法をまとめました。
| 記述方法 | Nullの場合 | Nullでない場合 |
|---|---|---|
| if ~ thenの条件分岐 | if フィールド名 = “” then | if フィールド名 <> “” then |
| ADOのfilterプロパティ | レコードセット.Filter = “フィールド名 = Null” | レコードセット.Filter = “フィールド名 <> Null” |
厳密には空白とNullは別物なのですが、日付型のフィールドは空白にできないので、Nullを使って判別します。
しかし、if ~ thenの条件分岐はNullでは判別できず空白で、ADOのfilterプロパティではNullで判別するのです。
以降、詳細に説明します。
if ~ thenの条件分岐で日付型のNullを判別するにはフィールド名 = “”
if ~ thenの条件分岐で日付型のNullを判別するには
if フィールド名 = "" then
と記述します。
逆に空白でない、という条件であれば
if フィールド名 <> "" then
となります。
これを
If フィールド名 = Null Then
や
If フィールド名 <> Null Then
と記載すると条件式自体が無視されます。
特にエラーも出ずに想定した挙動にならないので注意してください。
ADOのfilterプロパティで日付型のNullを判別するにはフィールド名 = Null
一方、ADOのfilterプロパティで日付型のデータがNullかどうかを判別にするには、
レコードセット.Filter = "フィールド名 = Null"
と記述します。
逆にNullでない、という条件であれば
レコードセット.Filter = "フィールド名 <> Null"
となります。
こちらは逆に空白を使って
レコードセット.Filter = "フィールド名 = ''"
や
レコードセット.Filter = "フィールド名 <> ''"
と記述すると以下のエラーになります。

日付型のNullを判別する実践例
では、実際のプロシージャでこの違いを見てみましょう。
サンプルテーブルとして以下のTRN_売上テーブルを準備しました。

このテーブルに対して、日付型のフィールドである売上日をもとに売上年月を付与するプロシージャをif ~ thenの条件分岐とADOのfilterプロパティの2種類の方法で作成します。
if ~ thenの条件分岐
まずはif ~ thenの条件分岐で作成したプロシージャです。
Public Sub uriage_nengetsu_huyo1()
'■■■売上日の空白をifで除外して、TRN_売上の売上日を元に売上年月を付与■■■
'変数にADOオブジェクトを代入
Set cnn1 = CurrentProject.Connection
Set rst1 = New ADODB.Recordset
rst1.CursorLocation = adUseClient
'レコードセットを取得
rst1.Open "TRN_売上", cnn1, adOpenKeyset, adLockOptimistic
If rst1.RecordCount = 0 Then
Exit Sub
End If
rst1.MoveFirst
Do Until rst1.EOF
If rst1!売上日 <> "" Then '正解
'If rst1!売上日 <> Null Then '誤り
Debug.Print rst1!売上ID & ":Not Null"
rst1!売上年月 = Year(rst1!売上日) & "/" & Format(Month(rst1!売上日), "00")
rst1.Update
End If
rst1.MoveNext
Loop
'終了処理
rst1.Close: Set rst1 = Nothing
cnn1.Close: Set cnn1 = Nothing
End Sub
中央部分にif ~ thenの条件分岐を作成しています。
If rst1!売上日 <> "" Then '正解
'If rst1!売上日 <> Null Then '誤り
とあえて2種類の条件分岐を記載し、誤りの方をコメントアウトしています。
プロシージャを実行してみましょう。

上記が結果です。
正しく売上年月の付与が行われており、売上日が空白の場合は処理がスキップされています。
逆に正解をコメントアウトし、誤りを生かした処理を行うと正しく処理が行われません。
コメントアウトを逆にして処理をした結果が以下です。

売上年月が更新されずに処理が終わってしまいます。
これは、条件式が不適切なためにすべてのレコードが条件未合致と判定されて、売上年月の更新処理ルーチンに入らなかったためです。
本来であれば条件式でNullが判定されてそのあとのDebug.Printによってイミディエイトウィンドウに文字が表示されるはずですが表示されずに処理が終了します。
このように、上記のパターンはエラーは出ずに処理結果が正しくないという非常に発見しにくい不具合なので注意してください。
ADOのfilterプロパティ
次にADOのfilterプロパティで抽出する方法です。
Public Sub uriage_nengetsu_huyo2()
'■■■売上日の空白をFilterで除外して、TRN_売上の売上日を元に売上年月を付与■■■
'変数にADOオブジェクトを代入
Set cnn1 = CurrentProject.Connection
Set rst1 = New ADODB.Recordset
rst1.CursorLocation = adUseClient
'レコードセットを取得
rst1.Open "TRN_売上", cnn1, adOpenKeyset, adLockOptimistic
rst1.Filter = "売上日 <> Null" '正解
'rst1.Filter = "売上日 <> ''" '誤り
If rst1.RecordCount = 0 Then
Exit Sub
End If
rst1.MoveFirst
Do Until rst1.EOF
rst1!売上年月 = Year(rst1!売上日) & "/" & Format(Month(rst1!売上日), "00")
rst1.Update
rst1.MoveNext
Loop
'終了処理
rst1.Close: Set rst1 = Nothing
cnn1.Close: Set cnn1 = Nothing
End Sub
こちらも以下のように2種類の処理方法を記述し、誤りをコメントアウトしています。
rst1.Filter = "売上日 <> Null" '正解
'rst1.Filter = "売上日 <> ''" '誤り
実行してみましょう。

上記のように正しく反映されます。
一方でコメントアウトを逆にして、誤りの方でプロシージャを実行してみます。

上記のようにエラーが出てしまいました。
このように、プロシージャの記述方法によって日付のNullを判別する方法が異なります。
日付型のフィールドは空白にすることができず、Nullにしかできない
なお、日付型のフィールドは空白にすることができず、Nullにしかできません。
通常、フィールドの値を空白にする際は以下のように記載します。
フィールド名 = ""
しかし、日付型のフィールドでこれを行うと以下のエラーが発生します。

そのため、日付型のフィールドには以下のようにNullを設定します。
フィールド名 = Null
空白とNullは異なるものですが、日付型のフィールドの場合は空白にできないのでNullを利用するしかありません。
詳しくは以下の記事をご覧ください。

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

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

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