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


1

从这个和其他网站的先前问题,我得到了一个功能,可以解析和查找文本字符串或单元格中的日期。这是功能:

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”。

这个功能在哪里崩溃?

更新问题的澄清:

我在几个宏中使用此函数,这些宏作用于从报表生成工具(Business Objects)导出的数据。可以手动编辑输入文件中的日期,但这可能会破坏宏的用途,因此不应被视为选项。

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

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

Answers:


3

您的 Mid(strInput, intPosition, intDateLength) 不适合你。 2011年9月1日,您正在匹配 DateFormat(6) = "*#[-/]#[-/]##*"。所以 Mid(strInput, intPosition, intDateLength) = Mid("9/1/2011", 1, 6) 并返回“9/1/20”而不是“9/1/2011”。

基于上面的示例,我认为您需要再添加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) = "*#[-/]#[-/]##*"

那是因为一位数的日子吗?
music2myear

是。 DateFormat(6)是有效的 米/ d / yy的 ,这是9/1/2011匹配的唯一一个。其他格式都需要2位数的日期或月份。因此,如果您在2011年9月1日投入使用,它将正常工作
Rhys Gibson

1
如果你能告诉我你想要达到的目标,我可以为你简化这项功能。我认为其中有一些冗余位,特别是如果所有日期都是相同的格式。
Rhys Gibson

我已经添加了关于GetDate()处理什么类型的字符串以及它对我的使用的要求的澄清。
music2myear

查看您添加的DateFormats,数字6和7是否应该颠倒?数字2和3从6和7看起来是相反的顺序。哪个是正确的(或者它们应该按照你给它们的顺序)?
music2myear

0

我写了一个较短的宏,应该做你想要的。它通过空格字符将字符串拆分为数组。然后宏遍历数组查找日期。如果日期附加了额外的字符,则会失败。但是,如果日期是它的“自己的单词”,两端间隔开,那就完美了。根据您的需要,可能需要稍微修改一下。

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

它似乎处理日期后跟句点,对吗?但是其他字符如逗号和其他标点符号可能会导致问题?
music2myear

对。在我的简单测试中,我有一段时间。您可以在最后测试每个字符串中的数字,如果不是则删除。在不知道他的确切要求的情况下,不可能有效地编写代码。
wbeard52
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.