- ベストアンサー
エクセルVBAで日付計算
Sub test01() x = Date - 38383 '2005/01/31から今日まで何日 x = Format(x, "##") '数字であらわす MsgBox x & "日です。" End Sub 試行錯誤の結果、上記コードで特定の日から今日まで何日かわかるようになりましたが、とても不細工なコードだと思います。 もっとすんなりもとめるにはどうすればよいでしょうか?
- みんなの回答 (11)
- 専門家の回答
質問者が選んだベストアンサー
Excelには隠しで関数があります。 DateDiff 関数 2 つの指定した日付の時間間隔を表すバリアント型 (内部処理形式 Date の Variant) の値を指定します。 Sub Test() Dim a As Long '2005年1月31日から今日までの日数 a = DateDiff("d", "2005/01/31", Date) MsgBox a End Sub
その他の回答 (10)
- hana-hana3
- ベストアンサー率31% (4940/15541)
>だからFormatで数字に直したのですが。 プログラムがXの値を日付として処理したので、1900年+差の日数 =1900/09/24 と言う日付型の表示がされただけです。 #9さんが書かれたように変数Xの型を指定すると、日付では無くて数値として処理されますから、Format文は不要になります。 正しい答えが出るなら処理方法に誤りは無いといえますが、変数型を宣言して目的に合った値を格納できるようにする事が大切かと思います。
お礼
> 変数型を宣言して目的に合った値を格納できるようにする事が大切かと思います。 仰せのとおりでございました。 ありがとうございます。
- Wendy02
- ベストアンサー率57% (3570/6232)
こんにちは。Wendy02です。 >MsgBox Date - 38383 & "日です。" だけだと。「1900/09/24日です。」とでてしまうんです。だからFormatで数字に直したのですが。 それは、Date型にキャストされてしまっています。私が、DateDiffを選んだ理由は、片方の数字が、Date型だからです。データ型の変換をしなくて済むからです。別に、格好がよいとかいう理由ではありません。 引き算する場合は、Dateを一旦、Long型に変換をしてから、引き算をしたほうがよいですが、Date関数と、Clng関数が重なるのに、サンプル・コードとしては少し抵抗を感じました。関数式とは違いますから、データ型の推移をきちんと把握しながら、出力値に持ってきたほうがよいと考えました。あまり値のキャスト変換を暗黙的に使わないほうがよいですね。
お礼
何度もありがとうございます。 ほんとに変数の型の宣言はする習慣をつけたほうがよいですね。 おさわがせしました。
- mshr1962
- ベストアンサー率39% (7417/18945)
#1,8のmshr1962です。 >MsgBox Date - 38383 & "日です。"だけだと。「1900/09/24日です。」とでてしまうんです 整数、長整数にすればいいですね。 MsgBox CInt(Date - 38383) & "日です。" MsgBox CLong(Date - 38383 & "日です。" なら数値になります。 変数を使う場合は Dim X As Integer X= Date - 38383 MsgBox X & "日です。"
お礼
Dim X As Integerを宣言しなかったわたしがお馬鹿でした。 ありがとうございました。
- mshr1962
- ベストアンサー率39% (7417/18945)
#1のmshr1962です。 >シリアル値にして引かないといけないんだろうということ 他の方の回答でもでてますが DateSerialやDateValueの日付関数を使う方法と CDateというデータ型変換関数を使う方法があります。 DateSerial(2005,1,31) DateValue("2005/01/31") CDate("2005/01/31") は同じ日付のシリアル値になります。 >Formatを使わないと計算結果が数値にならないんだろうという 別段Format関数を使う必要はありません。 Formatは書式が必要な場合に使う関数です。 "0日です。"がOKであれば MsgBox (Date-DateValue("2005/01/31"))&"日です。" でもかまいません。 例の場合は、##なので0日の場合、"日です。"になります。
お礼
ありがとうございます。 >> Formatを使わないと計算結果が数値にならないんだろうという > 別段Format関数を使う必要はありません。 MsgBox Date - 38383 & "日です。" だけだと。「1900/09/24日です。」とでてしまうんです。だからFormatで数字に直したのですが。
- imogasi
- ベストアンサー率27% (4737/17069)
>不細工なコード どの行について感じたのか書かないと判りません。 全体というか、なんと無くもあるでしょうが。 雑感 (1)引き算説 DateDiffがかっこいいと言うのは反対。 せっかくエクセルが、引き算で日数を出せるように、シリアル値というすばらしいアイデアを採用したのに。 エクセル関数のように第3引数にy、m、dなどを指定する場合は威力を発揮するでしょうが。 (2)38383説 これは可視性が悪いですね。Dateserial(2002,3,23)とか#2002/3/23#の法がわかりやすい。 (3)その他雑感 私が感じたのは、エクセルVBAでありながら、MSGBOXを使っていること。セルにセットするのが本筋ではないでしょうか。そして セルの日付書式を設定する。手動でもNumberFormatをVBAで設定する方法もあります。 (4)X,Xと同じ変数を違う内容に割り当てている。 (5)Xの右辺を関数の中に組み込む方法あり。かえって不細工かも 知れませんが。 MsgBox Format(Date - 38383, "##") & "日です。"
お礼
ありがとうございます。
- bin-chan
- ベストアンサー率33% (1403/4213)
MsgBox Format(Date - #2005/01/31#, "##日です。") でもOKですね。
お礼
ありがとうございました。
- Wendy02
- ベストアンサー率57% (3570/6232)
merlionXX さん、こんばんは。 最初に、失礼な書き方に思えたらすみませんです。 merlionXXは、人に教えるレベルであって、そのコード自体が、私の目からは、「不細工」とはいえないと思います。いままで、merlionXXのご質問などのやり取りをみていて、ものすごく勘の良い方だなって思います。だから、なんとなく、感覚的に、そのようにされたのだろうなって思います。でも、何かが足りないと感じたのではありませんか? もし、そうだとすれば、なるべく簡単なコードでも、変数の型の宣言はする習慣をつけたほうがよいですね。そうすると、見えないものが見えると思います。 VBAやVBは、値が自動変換するとは言っても、やはり、値の移動の時にきちんと、定義づけるようにしたほうがよいと思います。 x = Date - 38383 '変数 x は、ここでは、数値ですね。 x = Format(x, "##") '次に、Variant になっていますね。 MsgBox x & "日です。" '文字列ですね。 それぞれ変数の型は変化しています。このように、変数の使い回しは、あまりしないほうがよいですね。では、コードを一本化させた良いかというと、それは違うようです。今度は、可読性の問題や修正時の問題が出てきます。 例えば、Format関数を使う場合、文字列に直すのでしたら、Format$を使います。 Format(x, "##") ↓ Format$(x, "##") か、CStr(x) とします。 私は、リテラル値を使って以下のように書きました。 VBAの場合は、代入する値は、なるべく変数として、外に出したほうがよいですね。ワークシートの書き方とは、ちょっと違う作法が必要のようです。VBAで作法というのもヘンですけれども。最近、基礎に戻って勉強中です。 Sub test02() Dim x As Long Dim FirstDate As Date FirstDate = #1/31/2005# x = DateDiff("d", FirstDate, Date) MsgBox CStr(x) & "日です。" End Sub
お礼
ありがとうございます。 ぜんぜん。勘なんてにぶいのですが。 勉強になりました。
- hana-hana3
- ベストアンサー率31% (4940/15541)
>わたしが不細工と感じたのは MsgBox DateDiff("d", "2005/1/31", Date) & "日"
お礼
No3さんとおなじですね。 ありがとうございました。
- bin-chan
- ベストアンサー率33% (1403/4213)
MsgBox Format(Date - datevalue("2005/01/31"), "##日です。") でよいですか?
お礼
なるほど、DateValueでシリアル値をもとめているんですね。 ありがとうございました。
- mshr1962
- ベストアンサー率39% (7417/18945)
単純に MsgBox Format(Date-38383,"##日です。") では駄目なのですか?
お礼
さっそくありがとうございました。 わたしが不細工と感じたのは まず、Date-38383の部分で、なんでわざわざシリアル値にして引かないといけないんだろうということとFormatを使わないと計算結果が数値にならないんだろうという点なんです。 これはどうしようもないのでしょうか?
お礼
な~んと、やはりこういう技があるんですね。 完璧です! ありがとうございました。