目次
はじめに
VBAで日付を扱うマクロを作成していたとき、Date関数で今日の日付を取得したはずなのに、変数には「1900/1/1」が格納されていて困ったことがありました。いろいろ調べた結果、VBA.Dateと明示的に書くことで問題が解決したので、その経験を共有します。
遭遇した問題と原因
【問題が発生した状況】
マクロを作成していたときに、不思議な現象に遭遇しました。今日の日付を代入しているはずの変数に「1900/1/1」が入っていたんです。
Dim DateValue As Date
DateValue = Date
Debug.Print DateValue ' → 1900/1/1 と表示される
F8キーでステップ実行(1行ずつ処理を進める実行方法)してイミディエイトウィンドウ(実行結果を表示する画面)を確認しても、やはり「1900/1/1」と表示されます。
最初は何が原因なのかまったくわかりませんでした。Dateの書き方が間違っているのか、変数の型に問題があるのか、もしかしたらExcelの設定やシステム日付がおかしいのかもしれないと考えました。
【原因の推測】
他のマクロではDateが正常に動作していますし、システム日付も正しく設定されています。しかし、なぜこのマクロだけ「1900/1/1」になるのか、詳しい原因は特定できませんでした。
何らかの理由でDateという名前が競合していた可能性がありますし、VBAの内部的な処理で予期しない動作が起きていたのかもしれません。
解決方法
【VBA.を付けて明示する】
VBA.Dateとライブラリ名(標準機能の提供元)を明示して書くことで、問題が解決しました。
Dim DateValue As Date
DateValue = VBA.Date
Debug.Print DateValue ' → 2024/12/3 と表示される(実行日の日付)
VBA.という接頭辞を付けるだけで、正常に今日の日付を取得できるようになりました。
この表記により「VBA標準ライブラリのDate関数を呼び出す」と明示できます。プロジェクト内に同名の変数やプロシージャがあっても、確実に標準のDate関数が使われるようになります。
【なぜこの対策が有効なのか】
VBAでは、関数を呼び出すときに名前の解決(どの機能を指しているか判断すること)が行われます。単にDateと書くと、まずプロジェクト内に同名のものがないか探され、見つかればそちらが優先されます。
一方、VBA.Dateと書くと、VBA標準ライブラリから直接Date関数を呼び出すため、名前の競合が起こりません。この対策は、意図しない名前の競合を避けるための確実な方法です。
他の日付時刻関数への応用
VBA.表記はDateだけでなく、他の日付時刻関数でも使えます。同じような問題を避けるために、日付時刻関数ではVBA.を付ける習慣を付けておくと安全です。
【主な日付時刻関数の例】
Debug.Print VBA.Now ' 現在の日付と時刻
Debug.Print VBA.Time ' 現在の時刻のみ
Debug.Print VBA.DateSerial(2024, 12, 3) ' 指定した日付
Debug.Print VBA.TimeSerial(10, 30, 0) ' 指定した時刻
これらの関数も、プロジェクト内に同名の変数やプロシージャがあると意図しない動作をする可能性があります。特にNowやTimeは変数名として使われやすいため、注意が必要です。
日付時刻関数を使うときには、最初からVBA.を付けておくことで、後から問題が起きるリスクを減らせます。少し長くなりますが、コードの安全性が高まります。
まとめ
VBAのDateを使って今日の日付を取得しようとしたとき、プロジェクト内の名前の競合により「1900/1/1」が返ってくることがあります。VBA.Dateと明示的に書くことで、VBA標準ライブラリの関数を確実に呼び出せるため、この問題を回避できます。
NowやTimeなど他の日付時刻関数でも同じ対策が使えます。日付時刻関数を使うときには、最初からVBA.を付けておくと安全です。
もし同じ現象に遭遇したことがある方や、この動作の仕組みについてさらに詳しい情報をお持ちの方がいらっしゃいましたら、コメント欄で教えていただけると嬉しいです。