【问题标题】:VBA Compare times correctlyVBA 正确比较时间
【发布时间】:2017-12-05 17:15:47
【问题描述】:

我正在使用 VBA 从电子表格中比较两次。 在我的示例中,表单的实际值是两个单元格中的 23:00。我将它们用于 if 语句,这些值都来自 Variant 类型的两个不同数组。

if dataArr(v1) = rowArr(v2) Then

如果我调试这两个值,它会像这样显示这两个值

0,958333333333333 / 0,958333333333333

它们看起来相同,但 if 语句中的比较返回 false

所以我把这两个值相减,看看结果是否为零。

dataArr(v1) - rowArr(v2)

在这种情况下,结果不是零,而是

3,33066907387547E-16

所以表示时间的比较或两个双精度值有问题。

我找到的唯一可行的解​​决方案是将它们转换为字符串值

CStr(dataArr(v1)) = CStr(rowArr(v2))

它应该返回 true。

我不是很喜欢这个解决方案,因为它不是真正应该如何工作的。我还调查了这些值在比较之前会发生什么,但我找不到任何错误。实际上,dataArr 中的所有值都来自电子表格 (ListObject.DataBodyRange.Value),然后某些值从 dataArr 复制到 rowArr,因此它确实应该是相同的值。

有什么建议吗?谢谢!

【问题讨论】:

  • 如何加载数组中的值?在您的示例中它是一维的,所以我猜您不是从范围读取到数组。显示加载过程。
  • 由于代码非常复杂,示例被简化。我刚刚用 CStr 测试了代码,结果证明,如果我手动将时间添加到单元格中,它就可以工作。我首先使用的值也被一个子复制。所以我认为问题在于单元格中的值。即使看起来相同并且具有相同的单元格格式。
  • double 的精度为 17 位,但表示仅为 15。因此,两个 double 可以不同,即使它们在转换为字符串后看起来相同。所以结果没有问题。要比较两个日期的相等性,您需要四舍五入到 24 小时 x 60 分钟 x 60 秒的精度:Round(date1 * 86400) = Round(date2 * 86400).

标签: excel vba if-statement compare double


【解决方案1】:

如果单元格的格式实际上是时间而不是字符串,我会将数组的定义设为“日期”而不是“变体”。

然后您将拥有 VBA 中与日期/时间相关的所有功能(如 DateDiff() )。

【讨论】:

  • 我的桌子是供员工处置的。所以有日期、时间、字符串和整数的列。我需要将它用作变体。但就像我在上面的 cmets 中所说:我认为问题出在细胞本身。当我手动将时间写入单元格时,它可以工作。就像我使用 makro 将其写入单元格一样。
  • 所以,我从这些信息中假设您将工作表的全部内容存储在一个数组中。您可以将数组标注为用户定义的类型,并在其中每列有不同的项目。每个项目都有不同的简单类型以匹配列的数据类型。
【解决方案2】:

有时浮点数不准确会蔓延。如果您想比较,则取减法的绝对值 (ABS),看看它是否低于容差水平,例如 1E-7(百万分之一)。

【讨论】:

    【解决方案3】:

    感谢 Florent B,我得到了一个可行的解决方案!

    Florent B:要比较两个日期的相等性,您需要四舍五入到 24hrs x 60min x 60 sec 的精度

    所以解决办法是:

    If Round(dataArr(v1) * 86400) = Round(rowArr(v2) * 86400) Then
    

    这很有意义。非常感谢!

    【讨论】:

      猜你喜欢
      • 2016-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多