Vba 与区域设置无关的文本到日期转换函数

Vba 与区域设置无关的文本到日期转换函数,vba,excel,Vba,Excel,我正在尝试将类似“MMM DD YYYY”(例如“2015年1月17日”)的字符串转换为Excel序列日期。 问题是:我运行的是一个Windows的国际版本,DATEVALUE和CDate()都无法识别这种格式(它们取决于系统语言环境)。此外,当我编写函数时,我不知道它将在哪个语言环境中使用。 这篇文章:提供了一个很好的解决方案(通过编程调用TextToColumns),但它对我没有用——我需要一个函数(或UDF)来处理公式中的字符串。这些“日期”是另一个计算的结果(实际上是regexps),所

我正在尝试将类似“MMM DD YYYY”(例如“2015年1月17日”)的字符串转换为Excel序列日期。
问题是:我运行的是一个Windows的国际版本,DATEVALUE和CDate()都无法识别这种格式(它们取决于系统语言环境)。此外,当我编写函数时,我不知道它将在哪个语言环境中使用。
这篇文章:提供了一个很好的解决方案(通过编程调用TextToColumns),但它对我没有用——我需要一个函数(或UDF)来处理公式中的字符串。这些“日期”是另一个计算的结果(实际上是regexps),所以我不能在这些单元格上使用texttocolumn,这会把它们弄乱

是的,我可以编写一个带有静态查找表的UDF,该表将数字输入DateSerial(),但也许有更好的方法

澄清这与确定付款交单/付款交单顺序无关。罪魁祸首是一个月的文本名称——它是英文的,所以国际版的Excel无法识别它。例如,二月在芬兰语中是“helmikuuta”,在波兰语中是“luty”:


答案哇,这么多有用的答案!到目前为止,我使用SO的(短期)经验相当消极——我问了一个问题,没有人说任何有建设性的话,最后我制定了一个解决方案,自己回答这个问题。然而,这一次,我惊喜地发现,我对人性的信心恢复了:)现在将回顾答案并对其进行评论…

假设您的原始文本日期为A1,此公式将为您提供所需的输出:

=DATE(RIGHT(A1,4),MONTH(DATEVALUE(LEFT(A1,3)&" 1")),MID(A1,5,2))
这就是它的工作原理:

1) 我们通过以下方式从字符串中提取日期部分:

右图(A1,4)给出了年份

MID(1,5,2)给你一天的时间

左(A1,3)给出了月份

2) 我们将月份转换为数字月份,并且仅将月份部分的日期值转换为数字月份

3) 最后我们将这些值传递给DATE函数


仅在当月使用Datevalue应适用于您的国际设置。

如果您需要自定义项,这可能会有所帮助

Public Function CONVERT_DATE(ByRef rng As Range) As Date

Dim MyDate As Variant
MyDate = Split(rng.Value, " ")


'month is always mydate(0). So we use select case
Select Case UCase(MyDate(0))
    Case "JAN"
        MyDate(0) = 1
    Case "FEB"
        MyDate(0) = 2
    Case "MAR"
        MyDate(0) = 3
    Case "APR"
        MyDate(0) = 4
    Case "MAY"
        MyDate(0) = 5
    Case "JUN"
        MyDate(0) = 6
    Case "JUL"
        MyDate(0) = 7
    Case "AUG"
        MyDate(0) = 8
    Case "SEP"
        MyDate(0) = 9
    Case "OCT"
        MyDate(0) = 10
    Case "NOV"
        MyDate(0) = 11
    Case "DEC"
        MyDate(0) = 12
End Select

'mydate(1) is day
'mydate(2) is year

CONVERT_DATE = CDate(Format(Join(MyDate, "/"), "dd/mm/yyyy"))

End Function
只有当您的数据总是

“2015年1月17日”

这是一个简单的UDF

Function repairDate(str As String)
    Dim arr As Variant, mnths As Variant

    mnths = Array("Jan", "Feb", "Mar", _
                  "Apr", "May", "Jun", _
                  "Jul", "Aug", "Sep", _
                  "Oct", "Nov", "Dec")
    arr = Split(str, Chr(32))
    repairDate = DateSerial(arr(2), _
                    Application.Match(arr(0), mnths, 0), _
                    arr(1))
End Function
这将返回序列日期。建议您使用以
*
开头的日期格式之一,因为它们是跨语言支持


如果您的日期在第5行开始的
A列中:

Sub CorrectDateArray ()
    Dim MySheet As Worksheet, DateRange As Range
    Dim lRow As Long, vArr(), i As Integer
    '    Designate your worksheet, where MySheet is your actual name
    Set MySheet = Thisworkbook.Worksheets("MySheet")
    '    Last row
    lRow = MySheet.Range("A" & MySheet.Rows.Count).End(xlUp).Row
    '    Designate DateRange
    Set DateRange = MySheet.Range("A5:A" & lRow)
    '    Put values of array formula into array
    vArr = Evaluate("=LEFT(REPLACE(" & DateRange.Address & ",1," & _
                        "FIND(" "," & DateRange.Address & ",1),"")," & _
                            "FIND(" ";REPLACE(" & DateRange.Address & ",1," & _
                                "FIND(" ",N2,1),""),1)) & " & _
                    "LEFT(" & DateRange.Address & ";FIND(" "," & DateRange.Address & ",1)) & " & _
                    "RIGHT(" & DateRange.Address & ",4)")
    '    Finaly, a correct array of dates
    For i = Lbound(vArr) To Ubound(vArr)
        vArr(i) = CDate(vArr(i))
    Next
End Sub

如果使用
Split()
字符串,您可以轻松地以熟悉的格式重建日期。像DD-MMM YYYY,它应该能够识别。你可以使用Excel内置函数(如
Left()
Right()
Mid()
)将日期值按正确的顺序排列。谢谢大家,但不幸的是它不起作用(请参见上面的“澄清”)(谢谢J\P,但不幸的是它不起作用(请参见“澄清”)(在我的问题中):(无论如何都要投票,因为你可能被我的问题误导了。谢谢你花时间回答!谢谢!最好把你的脸从:(改为:)因为澄清不在你原来的问题中,你后来在我的回答之后把它添加到问题中。:)谢谢AntiDrondert,但不幸的是它不起作用(参见“澄清”在我的问题中):(无论如何都要对此进行表决,因为您可能被我的问题误导了。感谢您花时间回答!感谢@Foxfire;不幸的是,最后的CDate()调用将失败,因为它希望我的区域设置以dd/mm/yyy格式获取日期(我们无法确定)…DateSerial()在这种情况下可以工作。无论如何,向上投票,谢谢你的时间和努力:)DIY编程有点像DIY脑外科手术:-)如果你要写的代码只解决非常有限的一组情况,为什么要用24行来写你能用1写的东西呢?例如MyDate(0)=InStr(“…一月/二月/三月/四月/五月/六月/七月/八月/九月/十月/十一月/十二月”,UCase(MyDate(0))/4@WarrenK,这正是我所需要的!这应该是公认的答案:)简洁、清晰,而且能完成任务。甚至是蟒蛇。遗憾的是我注定要成为VBA(现在),我错过了“propah”语言……这正是我所需要的:)虽然我曾认为可以有另一种方法,而不必编写UDF。我喜欢您干净、优雅和简单的方法,并且没有考虑使用Application.Match()来查找表。巧妙的技巧:)