質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Q&A

解決済

2回答

4795閲覧

IF文が正しく判定されない。

shinchan0424

総合スコア26

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

0グッド

0クリップ

投稿2020/06/29 00:34

前提・実現したいこと

記憶している年月日時分秒がきちんと次の秒のデータを読み込んでいるかを判定したい

発生している問題・エラーメッセージ

エラーメッセージはありません。
IF文がうまく判定してくれません。

該当のソースコード

ExcelVBA

1 2  If data(i).date = DateAdd("s", 1, data(i - 1).date) Then 3  i = i + 1 4 Else 5  MsgBox "データが正しくありません。" 6 Unload Standbyscreen 7 Exit Sub 8 End If

(問題が発生している文のみ張り付けています)

試したこと

解決法が全く分からず手付かずの状態です…

今記憶した年月日時分秒が一つ前に記憶した日付に1秒足した値と等しければ、次の値へ進む
もし違うようなら、データが正しくありませんとだし、処理を終了させる。

といった流れになっています。

このIF文が左右同じ値なのにelse文のほうに入ってしまい、困っています。。
数値はすべてこの表記です。 2020/3/1 7:18:04

このエラーのわけのわからないところは、秒数によって進むほうが違うということです。
2020/3/1 7:18:04ではelseに行くのに対して、次の2020/3/1 7:18:05では普通に動きます。
2020/3/1 7:18:06も普通に動き、2020/3/1 7:18:07ではまたelseのほうに進みます。

ウォッチウィンドウで見た値を張っておきます。
イメージ説明
データが違うデータのため、上記の時間とは違います。

補足情報(FW/ツールのバージョンなど)

元々のデータはCSVファイルで、string型なので、data(i).dateに記憶させる際に、Date型に変換しています。
デバッグツールを利用して中の数値を見ても全く同じです。
見かけ上は同じでも実際には違うということでしょうか…?

回答よろしくお願いします…!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mdj

2020/06/29 01:25

おそらくミリ秒で差異があるのではないかと。
guest

回答2

0

ベストアンサー

下記のようなコードで確認してみました。
確かにDateAddの結果と比較するとFalseになりますね。

vba

1 Dim d1 As Date, d2 As Date 2 d1 = #1/1/2020 12:45:30 PM# 3 d2 = #1/1/2020 12:45:31 PM# 4 5 Debug.Print d2 = DateAdd("s", 1, d1)

DateAddの戻り値がVariant型が影響しているのかとCDateで変換してみたり、結果をDate型変数に格納してから比較してみてもFalseになりました。

ちょっと原因不明です。バグといってもいいかも知れません。

解決策としては、DateDiff で秒差を求めてそれで判断すればTrueが返りました。

vba

1 Debug.Print DateDiff("S", d1, d2) = 1

投稿2020/06/29 01:18

hatena19

総合スコア34075

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

macof

2020/06/29 01:40

解決に繋がるコメントでなくすいません。 VBAと言いますかCOMのDate型は内部表現が倍精度浮動小数点であり、 時刻は小数部に格納されているはずです。 そのため、問題としては一般的な浮動小数点型の誤差の話と同様と考えられます。 私は時刻の比較が発生する場合は文字列に変換するなどして行うようにしています。
hatena19

2020/06/29 01:57 編集

Date型は内部表現が倍精度浮動小数点だというのは承知しております。 たぶん演算誤差が原因だろうというのも想像がつきますが、断定はできません。(内部的なものなので) そのうえでDateAddにより1秒加算するときに誤差がでるのは、DateAdd関数の仕様からみるとバグといえるのではないでしょうか。 私の提示したDateDiffでの解決法や、文字列に変換して比較するというのも一つ解決策ですね。
ozwk

2020/06/29 01:59 編集

https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/date-data-type > 日付変数は、1月 1 100 日から 5 9999 月31日までの日付、および0:00:00 から23:59:59 までの時間を表す IEEE 64 ビット (8 バイト) 浮動小数点数として格納されます。 というわけでd1, d2をdoubleに変換するとたしかに誤差がありました (なんで64ビット整数じゃなくて浮動小数点数で持っているのか...) --- 失礼、かぶりました
macof

2020/06/29 02:35

失礼いたしました。 正直hatenaさんならご存知だろうなとは思いつつではありました… 元々誤差含みである以上、入力値に応じて加算する値を変える(DateAdd側で秒までの値かどうかを判断する)というのもそれはそれで違和感のある仕様ですし難しいですね。 そもそも表現する日付によって時刻部分の精度が(問題ないレベルで)変わるというのが、 中身を知らないと受け入れ難いところがあります。
DreamTheater

2020/06/29 02:52

なぜ整数値で保持してないんでしょうね? といっても始まらないので、hatena19さんの代替案(datediffで差を求める)に1票を投じます。
shinchan0424

2020/06/30 00:09

皆様回答解説ありがとうございます!! とても参考になりました! 私初心者で、日付が整数部、時刻が小数部に保持しているのを知らなかったです…! falseになる理由も理解ができました! ありがとうございました!
guest

0

少数以下の演算誤差が発生する仕様だと思いますので、
Formatで比較してみてはいかがでしょうか。
Format(data(i).Date, "yyyy/mm/dd hh:mm:ss") = Format(DateAdd("s", 1, data(i - a).Date), "yyyy/mm/dd hh:mm:ss")

投稿2020/06/29 01:34

radames1000

総合スコア1925

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shinchan0424

2020/06/30 00:10

回答ありがとうございます! 一度文字列に変換するんですね、、 確かにそれだと誤差も考えなくていいですね…! ありがとうございました!!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問