プロが教えるわが家の防犯対策術!

いつもお世話になっております。

VBA初心者です。

VBAを勉強中なのですが、私の使っている参考書に日付のコードに関して#3/19/2014#と日付リテラルで表記するようにとの記載がありました。
試に慣れ親しんでいる”2014/3/19”とコードを記載しても同様に動作しました。

参考書には何故?日付リテラル表記にするか記載がありませんでしたので、この場を借りて質問させていただきます。

日付リテラル表記にする理由とは何でしょうか?

初歩的な質問で申し訳ありませんが、よろしくお願いいたします。

A 回答 (6件)

#3の回答者です。



あくまでも、日付リテラル値「#3/19/2014#」は、VBEditor上にしか代入されません。従って、実際のプログラミングでは、日付リテラル値は使いません。

実際の入力に関して、「年,月,日」と明示的に分かるようにして入力させるのが正しいプログラミングの書き方です。VBAではそうした書法は言いませんが、VB6やVB.Netでは、使わないという約束事になっています。

アジア圏の場合は、概ね、"2014/3/19"(または、"2014/03/19")と書けばよいわけです。アメリカン・スタイルやヨーロッピアン・スタイルでは、また、これが変わります。これは、コントロールパネルの「地域と言語」のスタイルに合わせて入力をさせるのが書法です。

実際の場で、日付値を扱う時は、丁寧に書けば、以下のような対話型スタイルになりますが、対話型を省いたとしても、いくつかのチェック機能を備えるのが、実践のプログラミングの基本です。これは、常識的な話だと思いますが、ここの掲示板では、素に近いコードで済ませることも多いので、人によっては、避けるられるヒューマンエラーも、結果任せというかもしれません。それは、それで仕方がありません。

'//
Sub DateTest()
 Dim myDate As Variant
 Dim rtn As VbMsgBoxResult
 myDate = Application.InputBox(Prompt:="日付をyyyy/mm/ddのスタイルで入力してください.", Type:=2)
 If IsDate(myDate) = False Then '第1関門
  MsgBox "それは日付として認められません." & _
  vbCrLf & "やり直してください.", vbExclamation
  Exit Sub
 Else
  myDate = CDate(myDate)
  rtn = MsgBox("あなたが入力したのは、" & Format(myDate, "yyyy年M月d日") & "ですか?", vbOKCancel + vbQuestion) '第2関門
  If rtn = vbCancel Then
   MsgBox "もう一度入力し直してください."
   Exit Sub
  Else
  'continued....
  End If
 End If
End Sub
    • good
    • 2
この回答へのお礼

ありがとうございます。

お礼日時:2014/06/11 22:05

Excel2010での簡単なテスト(標準モジュールです)


Sub test1()
Dim t As Date
t = "2000/2/29"
MsgBox t + 1
End Sub

Sub test2()
Dim t As Date
t = #2/29/2000# ’入力直後に 2000/2/29 → 2/29/2000 になります
MsgBox t + 1
End Sub

Sub test3()
Dim t As Date
t = "2001/2/29"
MsgBox t + 1
End Sub

Sub test4()
Dim t As Date
t = #2/29/2001#
MsgBox t + 1
End Sub

2000/2/29 はうるう年です。
test1・2 ともにエラーにはなりません。
ちゃんと、2000/3/1 を返してくれます。

では、test3・4のように、2001/2/29 とした場合。(うるう年ではありません)
test3 ではコンパイルエラーにもなりません。
『実行した場合に初めて』、『型が一致しません』のエラーになります。
test4 では入力直後に、赤く表示されます。
また、コンパイルエラー(構文エラー)になります。
もちろん、うるう年だけではなく大の月小の月でもチェックされます。

実行されて初めてエラーが露見するのと予め教えてくれるのとどちらを選びますか?
ExcelやAccessのVBAが気を利かしてやってくれていますが、
(Date 型で宣言しているのに文字列の"2000/2/29"を渡しても
「ああ、多分日付じゃないかな、日付にしてしまおう」とVBAが行います。)
この『暗黙の型変換』に頼っていると思わぬ時にしっぺ返しを喰らいますよ。
    • good
    • 1
この回答へのお礼

ありがとうございます。

お礼日時:2014/06/11 22:05

こんにちは。



>私の使っている参考書に日付のコードに関して#3/19/2014#と日付リテラルで表記するようにとの記載がありました。

参考書の記載が、正確にはどう書かれてあったかは知りませんが、「日付リテラル値」で書けというのは、ありえません。そうだとしたら、基本的なことを知らない人だと思います。VB系のプロ用の書法では、リテラル値の禁止事項がありますが、一般ユーザーに対しても、それを使えという教えはないと思います。

そのまま入力すれば、日付値は、チェック機能が必要なことが多いのです。
最低限度、年数は適正か(入力された年数は、例えば、5年以内か)ということです。このように、二点の確認コードが必要になってしまいます。ただ、一般の人は、どうでもよいかもしれませんが、セミプロレベルになれば、そうは言えません。

もちろん、#14/3/19# というのは正しいリテラル値の表記ではありませんが、リテラル値で入力するれば自動的に変わるはずです。VBAは、基本的に米国方式になっていますから、#月/日/年# という順番になっていることが多いのですが、それが、アジア圏では正しいというわけではありません。期待した日付値になっているか、確認しなければならないという手間が生じてしまいます。

>試に慣れ親しんでいる”2014/3/19”とコードを記載しても同様に動作しました。
これが正しい入力方法だと思います。理由は、使用者や作成者が、入力した時点で視認できるからです。言い換えれば、可読性が高いのです。

VBAの場合は、(ユーザー)フォームやセルから、日付値を取りますが、セルの場合は、すぐさま確認できます。フォームの場合は、テキスト入力で、私達が慣れ親しんだ、「年/月/日」を入力するはずです。入力した値を、Date型変数に入れるか、CDateにして変換するかという方法を取れば良いわけです。

再度申しますが、VBEditor上で直接書く場合は別として、実務上、日付リテラル値をそのまま扱うということはありません。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2014/06/11 22:06

もう一つありました。



それは「実行環境のロケールを気にしなくて良い」と言う点です。

日付リテラルで書かくと、プログラムの内部コードには「日付シリアル値」で記録されます。

そのプログラムを「年/月/日で表記する環境」に持って行っても、「月/日/年で表記する環境」に持って行っても、表記が違って見える事はあっても、日付シリアル値になっているので誤解は生じません。

しかし「文字列で書いてしまう」と、環境によって「その文字列が正常に日付シリアル値に変換されるとは限らない」のです。

例えば、OSの「日付表現の設定」が変更されてて「月/日/年の表記しか許さない状態」になった環境に、文字列で"2014/3/19"と書かれたプログラムを持ってきて実行したら「実行時エラー」が出てしまう可能性があります。

文字列で書くと「環境に依存してしまい、他のパソコンで動かないかも知れない」ですが、日付リテラルで書けば「環境に依存しないので、他のパソコンで正常に動く可能性が高くなる」のです。

もちろん「書いたプログラムを自分のパソコンででしか使わない」と言うなら、環境依存性は気にしなくても良いですが、仕事で使うなら、そうも言っていられません。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2014/06/11 22:06

因みに、年月日に「誤解される余地のない値」を指定する場合、例えば



#2014/3/19#

のような場合「年/月/日」の順で書く事が可能です。

標準では「月/日/年」ですが、上記のように「最初の数字が年なのが明らかで、最後の数字が日なのが明らか」な場合に限り「年/月/日」と解釈されます。

但し

#12/1/2#

のように「月/日/年」と「年/月/日」のどっちにも解釈できてしまう場合は、予期しない値になるので注意が必要です。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2014/06/11 22:06

>日付リテラル表記にする理由とは何でしょうか?



実行時に文字列を日付シリアル値に変換する必要が無いからです。

文字列で指定した場合、実行時に、文字列を解釈して、日付シリアル値を生成してから、生成された値が使われます。

日付リテラルで書けば、この「文字列を解釈して、日付シリアル値を生成して」と言う処理は行われません。

1箇所くらいなら実行速度に影響は出ませんが、ループで10万回くらい実行される部分にあったら、実行速度に大きな差が出ます。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2014/06/11 22:06

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!