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