Excel 宏日期解析器无法处理个位数的日期

Excel 宏日期解析器无法处理个位数的日期

从此网站和其他网站上的先前问题中,我获得了一个可以解析并查找文本字符串或单元格中的日期的函数。以下是该函数:

Function GetDate(strInput As String) As Date

    Dim DateFormat() As String
    Dim intDateLength As Integer
    Dim intMaxFormat As Integer
    Dim intFrmtCtr As Integer
    Dim intPosition As Integer

    intMaxFormat = 6
    ReDim DateFormat(1 To intMaxFormat)

    DateFormat(1) = "*##[-/]##[/-]####*"
    DateFormat(2) = "*#[-/]##[-/]####*"
    DateFormat(3) = "*##[-/]#[-/]####*"
    DateFormat(4) = "*##[-/]##[-/]##*"
    DateFormat(5) = "*#[-/]##[-/]##*"
    DateFormat(6) = "*#[-/]#[-/]##*"

    GetDate = Now

    For intFrmtCtr = 1 To intMaxFormat
        If strInput Like DateFormat(intFrmtCtr) Then
            intDateLength = Len(DateFormat(intFrmtCtr)) - 8
            strInput = Replace(strInput, " ", "")

            For intPosition = 1 To Len(strInput)
                If Mid(strInput, intPosition, intDateLength) Like DateFormat(intFrmtCtr) Then
                    GetDate = DateValue(Mid(strInput, intPosition, intDateLength))
                    Exit Function
                End If
            Next intPosition
        End If
    Next intFrmtCtr

End Function

然后通过引用单元格地址来调用它:

'Gets date from cell A2
    Range("A2").Select
    dateWork = GetDate(Selection)

然后我可以使用或类似方法格式化输出Format(dateWork, "mmddyy")

在上面的例子中,给定一个单元格,返回8/31/2011字符串的内容。08312011

但是,从单元格内容日期为一位数(即月初)开始,该函数开始返回年份的前两位数字,而不是后两位数字。突然间,日期开始看起来像是 2020 年的,而不是 2011 年的。

我已经能够使用其他方面相同的输入数据表对此进行测试,其中直到并包括的日期8/31/2011都正确返回,9/1/2011并且以“20”开头的日期都返回“20”作为年份。

这个功能是哪里出现故障了?

更新问题澄清:

我在多个宏中使用此功能,这些宏作用于从报告生成工具 (Business Objects) 导出的数据。可以手动编辑输入文件中的日期,但这违背了宏的目的,因此不应被视为一种选择。

可以调用 GetDate() 函数来查找任何字符串中的日期。字符串可以是各种格式的日期,也可以是文本和日期的组合,例如“截至 1977 年 9 月 13 日的总数”。

只要它保留上面列出的功能,我将非常感激您对该功能的简化或编辑。

答案1

您的Mid(strInput, intPosition, intDateLength)不适合您。对于 2011 年 9 月 1 日,您匹配 DateFormat(6) = "*#[-/]#[-/]##*"。因此Mid(strInput, intPosition, intDateLength) = Mid("9/1/2011", 1, 6)和 返回“9/1/20”而不是“2011 年 9 月 1 日”。

根据上面的例子,我认为你需要添加 2 个模式,以便涵盖 1 和 2 位月份/日期以及 2 和 4 位年份的所有组合。顺序很重要,因为你想先匹配 4 位年份(请注意,你遇到问题的原因是#/#/##匹配 9/1/2011,而实际上您只希望它匹配 9/1/11。因此代码更改如下所示。我尚未对所有日期格式进行详尽测试,但似乎没问题。

intMaxFormat = 8
ReDim DateFormat(1 To intMaxFormat)

DateFormat(1) = "*##[-/]##[/-]####*"
DateFormat(2) = "*#[-/]##[-/]####*"
DateFormat(3) = "*##[-/]#[-/]####*"
DateFormat(4) = "*#[-/]#[-/]####*"
DateFormat(5) = "*##[-/]##[-/]##*"
DateFormat(6) = "*##[-/]#[-/]##*"
DateFormat(7) = "*#[-/]##[-/]##*"
DateFormat(8) = "*#[-/]#[-/]##*"

答案2

为了接受 2 位和 4 位数字的年份(其中 2 位数字小于 1000),我使用了一行来检查所有有关日期的信息,即:

If IsDate(date) And Len(Trim(Year(date))) = 2 Or Len(Trim(Year(date))) = 4 Then
GoTo Action 'Continue with the macro
Else: "Your Message"
End If

答案3

我写了一个更短的宏,应该可以满足您的要求。它通过空格字符将字符串拆分为一个数组。然后,宏会遍历数组以查找日期。如果日期附加了多余的字符,则它会失败。但是,如果日期是其“自己的单词”,两端用空格隔开,则它会完美运行。根据您的需要,可能需要对其进行一些修改。

Function GetDate(strInput As String) As Date

 Dim strDate() As String, i As Long

  strDate = Split(strInput, " ")

 For i = 0 To UBound(strDate) - 1
    If Right(strDate(i), 1) = "." Then strDate(i) = Left(strDate(i), Len(strDate(i)) - 1)
    If IsDate(strDate(i)) Then
       GetDate = strDate(i)
       Exit For
    End If
 Next i

End Function

相关内容