【问题标题】:VBA Excel - Equal dates do not evaluate as equalVBA Excel - 相等的日期不评估为相等
【发布时间】:2013-10-21 23:53:42
【问题描述】:

Win7 上的 MS Excel Professional Plus v14。

我无法比较日期/时间的相等性。

两个看似相等的日期,2013 年 12 月 16 日下午 12:19:33 都被标注为日期。一个在日期数组中,另一个是日期变量。 arrPP 稍后会重新调整。当我执行 DateDiff("s",date1,date2) 时,它会产生 0。

Dim arrPP() As Date          ' During runtime shows type is Date(1 to 2, 1 to 1)
Dim dNextStartTime as Date

'...code removed ...

    If arrPP(iPP_START, lPP_index) <= dNextStartTime Then
        GoTo PP_OUT
    End If

即使它们是相等的,上面的评估结果为 false 并且采取了错误的路径。这很难追踪并导致意外/错误的结果。

是否有关于日期平等的官方“陷阱”?是否存在需要比较的隐藏毫秒,或者将比较限制到秒级别的方法?

我尝试了其他几种替代方法,包括将 CDate 放在数组元素的前面。

失败:

    If Not(arrPP(iPP_START, lPP_index) > dNextStartTime) Then
        GoTo PP_OUT
    End If

通过:(但谁会想到这样做呢?)

    If arrPP(iPP_START, lPP_index) <= dNextStartTime Or _
       DateDiff("s",arrPP(iPP_START,lPP_index),dNextStartTime) = 0 Then
        GoTo PP_OUT
    End If

【问题讨论】:

  • VBA Excel - Equal dates do not evaluate as equal 你是如何填写日期的?它对我有用。

标签: excel date-comparison vba


【解决方案1】:

这很可能是由于浮点精度问题。日期存储为双精度浮点数,其中整数部分为日期,小数部分为时间。

要测试arrPP(iPP_START,lPP_index) 是否在dNextStartTime 之前,最好使用

If DateDiff("s",dNextStartTime,arrPP(iPP_START,lPP_index)) <= 0 Then

请注意,当第一个日期参数早于第二个日期参数时,DateDiff 返回正数。

要演示两个明显相等的日期可能不相等,请尝试运行此

Sub demo()
    Dim d1 As Date, d2 As Date

    d1 = #12/17/1986 12:19:33 PM#

    d2 = #12/17/1986#
    d2 = d2 + 12# / 24#             ' Add 12 hour
    d2 = d2 + 19# / 60# / 24#       ' Add 19 minutes
    d2 = d2 + 33# / 60# / 60# / 24# ' Add 33 seconds

    Debug.Print d1; d2
    Debug.Print d1 = d2
    Debug.Print d1 - d2
End Sub

立即窗口输出

1986 年 17 月 12 日下午 12:19:33 1986 年 12 月 17 日下午 12:19:33
假的
3.63797880709171E-12

【讨论】:

  • 嗯。有趣的是 DateDiff() 为 0 但 a = b 为假。也许 DateDiff() 是为了处理不精确而构建的?看来这会给人们带来很多麻烦!
  • 底线,比较浮点值是否相等(无论它们代表什么)是个坏主意
  • 猜猜我将把我所有的日期比较都切换到 DateDiff()。谢谢!
  • + 1 很好的例子。顺便说一句,用#1/1/2001 12:19:33 PM# 试试你的代码;)
【解决方案2】:

VBA Excel - 相等的日期不会评估为相等

它对我有用。

我想这归结为您如何将日期存储在日期变量或日期数组中。你如何填充日期?

这是我所做的测试。如果我误解了您的查询,请告诉我。

Sub Sample()
    Dim dt As Date
    Dim MyAr(1, 1) As Date

    dt = #12/16/2013 12:19:33 PM#
    MyAr(1, 1) = #12/16/2013 12:19:33 PM#

    If (MyAr(1, 1) > dt) Then
        MsgBox "MyAr is greater"
    ElseIf (MyAr(1, 1) < dt) Then
        MsgBox "MyAr is lesser"
    Else
        MsgBox "They are equal" '<~~ This is what I get
        Debug.Print DateDiff("s", MyAr(1, 1), dt)
    End If
End Sub

【讨论】:

  • 即使我将第一个条件更改为 If (MyAr(1,1) = dt),您的示例也适用于我。它评估为真。如果我将日期放在单元格 $A$1 中并从那里读取它,它也可以工作。我的 arrPP 是通过读取工作表中日期格式的单元格来填充的。这些单元格中的日期看起来很正常。 dNextStartTime 初始化为“12:00”,通常重置为从日期格式单元格中的工作表读取的日期(看起来很正常)。 dNextStartTime 可能会从变体数组中的日期再次重置,但随后我使用 dNextStartTime = CDate(arrOther(x,y))。平等对于调度应用很重要。
【解决方案3】:

很可能在这么多年后你不需要答案,但如果有人愿意加入这个问题,也许它会很有用。

Function DateEqual(date1 As Date, date2 As Date) As Boolean
    'use should never compare as equal dates or any double values but if you really need to do it carefully use this function.
    'converting to integers to test if they are equal. if you need to test time values recorded with less then 1second DO NOT USE THIS FUNCTION.
    Dim day1, day2 As Date
    Dim time1, time2 As Date
    day1 = Int(date1)
    day2 = Int(date2)
    If day1 = day2 Then
        If Hour(date1) = Hour(date2) And Minute(date1) = Minute(date2) And Second(date1) = Second(date2) Then
            DateEqual = True: Exit Function
        Else
            DateEqual = False: Exit Function
        End If
    Else
        DateEqual = False: Exit Function
    End If
End Function

【讨论】:

    猜你喜欢
    • 2020-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-06
    • 2018-11-22
    • 1970-01-01
    • 2021-01-05
    相关资源
    最近更新 更多