【问题标题】:Excel VBA convert Date with timeExcel VBA将日期与时间转换
【发布时间】:2019-04-16 02:36:07
【问题描述】:

我有 2 个单元格的时间数据格式如下:

"A1" = Sep 01 2018 00:01:33.707 
"A2" = Sep 01 2018 00:01:49.917

我需要在 Excel VBA 中创建一个按钮和方法,如果时间“A2”比“A1”多 90 秒,则将“A3”单元格设置为 true。 这是我到目前为止所拥有的,但它不起作用:

Sub Macro2()
    Dim str1 As String, str2 As String

    With Worksheets("sheet5")

        str1 = .Cells(1, "A").Text
        str2 = .Cells(2, "A").Text

        'greater than 90m seconds in A3
        .Cells(3, "A") = CBool(Abs((DateValue(Left(str1, 6) & "," & Mid(str1, 7, 5)) + _
                                    TimeValue(Mid(str1, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str1, 4))) - _
                                   (DateValue(Left(str2, 6) & "," & Mid(str2, 7, 5)) + _
                                   TimeValue(Mid(str2, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str2, 4)))) > _
                                   TimeSerial(0, 0, 90))
        'actual absolute difference in A4
        .Cells(4, "A") = Abs((DateValue(Left(str1, 6) & "," & Mid(str1, 7, 5)) + _
                                    TimeValue(Mid(str1, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str1, 4))) - _
                                   (DateValue(Left(str2, 6) & "," & Mid(str2, 7, 5)) + _
                                    TimeValue(Mid(str2, 13, 8)) + TimeSerial(0, 0, 1) * CDbl(Right(str2, 4))))
    End With End Sub

上面给出了错误,因为日期函数适用于系统语言环境,在我的例子中是希伯来语,而数据是英语。

另一种可能有帮助的方法是将所有“A”列(包含日期)转换为可与 VBA 上的日期和时间函数一起使用的系统本地日期(不知道该怎么做)。

请帮忙

【问题讨论】:

  • A1 和 A2 中的值是真实日期还是看起来像日期的字符串?
  • @FunThomas 它们是来自另一个系统的真实日期,以字符串形式导出

标签: excel vba


【解决方案1】:

我已将您的任务分为 3 个功能。

a) 辅助函数将月份的 3 个字符转换为整数。看起来有点笨拙,可能还有其他方法,但使用大号 Select Case 的好处是,如果出现不同语言的月份名称,它很容易理解和适应:

Function getMonthFromName(monthName As String) As Integer

    Select Case UCase(monthName)
        Case "JAN": getMonthFromName = 1
        Case "FEB": getMonthFromName = 2
        Case "MAR": getMonthFromName = 3
        Case "APR": getMonthFromName = 4
        (...)
        Case "SEP": getMonthFromName = 9
        (...)
    End Select

End Function

b) 将字符串转换为日期的函数。它采用您提供的形式的日期格式,但如果格式发生变化,它很容易适应(为简单起见,秒是四舍五入的)

Function GetDateFromString(dt As String) As Date

    Dim tokens() As String
    tokens = Split(Replace(dt, ":", " "), " ")

    Dim day As Integer, month As Integer, year As Integer
    month = getMonthFromName(CStr(tokens(0)))
    day = Val(tokens(1))
    year = Val(tokens(2))

    Dim hour As Integer, minute As Integer, second As Double
    hour = Val(tokens(3))
    minute = Val(tokens(4))
    second = Round(Val(tokens(5)), 0)

    GetDateFromString = DateSerial(year, month, day) + TimeSerial(hour, minute, second)
End Function

c) 以秒为单位计算两个日期之差的函数。 VBA(和许多其他环境)中的日期存储为Double,其中日期部分是整数部分,日期是余数。这使得使用日期值进行计算变得容易。

Function DateDiffInSeconds(d1 As String, d2 As String) As Long
    Dim diff As Double
    diff = GetDateFromString(d2) - GetDateFromString(d1)
    DateDiffInSeconds = diff * 24 * 60 * 60
End Function

更新以处理毫秒:更改GetDateFromString-函数。在这种情况下,DateDiffInSeconds 应该返回 double 而不是 long

Function GetDateFromString(dt As String) As Date

    Const MillSecPerHour As Long = 24& * 60 * 60 * 1000

    Dim tokens() As String
    tokens = Split(Replace(Replace(dt, ".", " "), ":", " "), " ")

    Dim day As Integer, month As Integer, year As Integer
    month = getMonthFromName(CStr(tokens(0)))
    day = Val(tokens(1))
    year = Val(tokens(2))

    Dim hour As Integer, minute As Integer, second As Integer, milli As Integer
    hour = Val(tokens(3))
    minute = Val(tokens(4))
    second = Val(tokens(5))
    milli = Val(tokens(6))

    GetDateFromString = DateSerial(year, month, day) _
                      + TimeSerial(hour, minute, second) _
                      + milli / MillSecPerHour
End Function

【讨论】:

  • 感谢您提供出色的完整解决方案,效果很好!我将尝试通过使用带有月份名称的数组并返回正确月份的索引来使第一个函数更快。是否也将毫秒计入计算中?
  • 我已经更新了我的答案,以展示一种处理毫秒的方法。
  • 如果只是为了速度:别想把它改成数组了:这个函数太快了,你永远无法测量它。
【解决方案2】:

为了您的信息,我以稍微不同(且更简单)的方式完成了您正在做的事情:

在单元格 B2 中,我输入了值 13/11/2018 11:44:00
在单元格 B3 中,我输入了值 13/11/2018 11:45:01
(对于这两个单元格,单元格格式都设置为d/mm/jjjj u:mm:ss)。

在另一个单元格中,我输入了以下公式:

=IF((B3-B2)*86400>90;TRUE;FALSE)

公式是基于设置一个日期时间值的思想,基于一天等于1的思想,一天有86400秒。

这样,你可以计算时间差而不需要 VBA。

【讨论】:

  • 谢谢,但我真的需要它在 VBA 上,因为它将成为更大宏的一部分。另外,我看到您更改了单元格的值,我没有更改它的选项,因为它们是按原样导入的,这就是我需要转换解决方案的原因...
  • @user1610208:我的想法是基于日期的自动转换。我刚刚在 Excel 工作表中输入了“01/04/2014”,它会自动转换为日期。如果您能找到一种将单元格值自动转换为日期的方法,那么您的问题可能会得到解决。你能摆脱我的回答的否决吗?
【解决方案3】:

我认为你过于复杂了,试试这个来了解如何去做:

Sub Macro2()
    Dim str1 As String, str2 As String

    With Worksheets("sheet5")

        .Range("b1:e1") = Split(Range("A1"), " ")
        .Range("B2:e2") = Split(Range("A2"), " ")


End Sub

【讨论】:

  • 这不考虑日期本身(月、日或年),我也需要包括它们...
  • 不,它没有。抱歉,如果您按照建议的方式拆分字符串,您可以使用查找月份值来重新创建日期。
  • 你能提供一个完整的解决方案吗?
  • 使用=DATE(D1,MATCH(B1,{"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"},0),C1)之类的东西将字符串转换为日期,加上时间值,剩下的应该很简单。
  • 我需要在 VBA 脚本上使用它,因为我有很多工作表
【解决方案4】:

使用 UDF。

Sub Macro2()
    Dim str1 As String, str2 As String
    Dim mySecond As Double, t1 As Double, t2 As Double, t3 As Double
    mySecond = TimeSerial(0, 0, 90)

    With Worksheets("sheet5")
        str1 = .Cells(1, "A").Text
        str2 = .Cells(2, "A").Text
        t1 = ConvertTime(str1)
        t2 = ConvertTime(str2)
        t3 = t2 - t1
        .Cells(3, "a") = Abs(t3) >= mySecond
    End With

End Sub
Function ConvertTime(s As String)
    Dim vS
    vS = Split(s, " ")
    ConvertTime = DateValue(vS(0) & "-" & vS(1) & "-" & vS(2)) + TimeValue(Split(vS(3), ".")(0))
End Function

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2016-12-18
    • 2022-01-06
    • 1970-01-01
    • 1970-01-01
    • 2021-09-13
    • 2015-10-25
    相关资源
    最近更新 更多