将日期格式更改为 yyyy-mm-dd
Posted
技术标签:
【中文标题】将日期格式更改为 yyyy-mm-dd【英文标题】:Changing the date format to yyyy-mm-dd 【发布时间】:2011-10-29 16:37:02 【问题描述】:我有一个包含混合格式日期的日期列。例如:
一个 21.03.1990 1990 年 3 月 21 日
所以,基本上一列中有两种不同的格式:dd.mm.yyyy
和 mm/dd/yyyy
。我正在尝试编写一个 VBA 脚本来将列中所有日期的格式更改为yyyy-mm-dd
。这就是我到目前为止所得到的:
Sub changeFormat()
Dim rLastCell As Range
Dim cell As Range, i As Long
Dim LValue As String
i = 1
With ActiveWorkbook.Worksheets("Sheet1")
Set rLastCell = .Range("A65536").End(xlUp)
On Error Resume Next
For Each cell In .Range("A1:A" & rLastCell.Row)
LValue = Format(cell.Value, "yyyy-mm-dd")
.Range("B" & i).Value = LValue
i = i + 1
Next cell
On Error GoTo 0
End With
End Sub
我知道这不是一段优雅的代码,但我是 VBA 的初学者,所以请原谅我。
该代码的问题在于它只是将未更改的 A 列重写为 B 列,当我将 Format 函数中的参数从 yyyy-mm-dd
更改为 dd/mm/yyyy
它有效,但仅适用于格式为 mm/dd/yyyy
的日期,并留下 dd.mm.yyyy
原封不动。如有任何建议,我将不胜感激。
【问题讨论】:
据我所知“21.03.1990”不是日期格式,它只是以这种方式输入的文本。您可以检查单元格格式并确认吗?如果是文本,则更改日期格式不会对内容产生任何影响。 恕我直言,VBA 可能比它的价值更麻烦。这个任务可以用一个相当简单的 Excel 公式来完成。 【参考方案1】:这是一个简单的解决方案:
Sub ChangeFormat1()
Dim ws as Worksheet
Set ws = Thisworkbook.Sheets("Sheet1")
LR = ws.cells(rows.count,1).End(Xlup).Row
with ws
For I = 1 to LR
.cells(I,2).value = .cells(I,1).value
Next
End with
ws.range("B1:B" & LR).numberformat = "yyyy-mm-dd"
End Sub
【讨论】:
【参考方案2】:@Jean-François Corbett 有一个有效的公式解决方案,但通过前面的错误消息(基于#VALUE!
提供信息)和另一个 IF,两个日期,应用 IFERROR 而不是比 ISERROR 和 SUBSTITUTE 代替一组 LEFT、MID、RIGHT:
=IFERROR(1*(MID(A1,4,3)&LEFT(A1,3)&RIGHT(A1,4)),1*SUBSTITUTE(A1,".","/"))
这会将@Issun 在评论中提到的解释应用于 OP,并假设输出将是格式化为yyyy-mm-dd
的单元格。
可以用这样的子程序编写:
Sub Macro1()
Range("B1:B10").Formula = "=IFERROR(1*(MID(A1,4,3)&LEFT(A1,3)&RIGHT(A1,4)),1*SUBSTITUTE(A1,""."",""/""))"
End Sub
【讨论】:
【参考方案3】:更新:新答案
这是一个可以完成这项工作的解决方案!子例程包含一个执行替换的函数(该函数本身非常有用!)。运行子程序,A 列中的所有事件都将得到修复。
Sub FixDates()
Dim cell As range
Dim lastRow As Long
lastRow = range("A" & Rows.count).End(xlUp).Row
For Each cell In range("A1:A" & lastRow)
If InStr(cell.Value, ".") <> 0 Then
cell.Value = RegexReplace(cell.Value, _
"(\d2)\.(\d2)\.(\d4)", "$3-$2-$1")
End If
If InStr(cell.Value, "/") <> 0 Then
cell.Value = RegexReplace(cell.Value, _
"(\d2)/(\d2)/(\d4)", "$3-$1-$2")
End If
cell.NumberFormat = "yyyy-mm-d;@"
Next
End Sub
将此函数放在同一个模块中:
Function RegexReplace(ByVal text As String, _
ByVal replace_what As String, _
ByVal replace_with As String) As String
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
RE.pattern = replace_what
RE.Global = True
RegexReplace = RE.Replace(text, replace_with)
End Function
它是如何工作的:我有一个漂亮的 RegexReplace 函数,它允许您使用正则表达式进行替换。 sub early 循环通过您的 A 列,并为您提到的这两种情况进行正则表达式替换。我首先使用 Instr() 的原因是确定它是否需要替换,以及哪种替换。从技术上讲,您可以跳过此步骤,但对不需要它的单元进行替换确实非常昂贵。最后,我将单元格格式化为您的自定义日期格式,无论里面有什么安全措施。
如果您不熟悉 Regex(参考:http://www.regular-expressions.info/),我使用的表达式是:
() 中的每个项目都是捕获组 - 也就是您想要弄乱的东西 \d 代表数字 [0-9]。 2 表示 2 个,4 表示 4 个。为了安全起见,我在这里一直很明确。 . 之前的 \。在第一个替换中是需要的,因为“。”有特殊意义。 在 VBA 正则表达式中,您使用 $ + no 来引用捕获组。的组。这就是我翻转 3 个项目的顺序的方式。【讨论】:
尝试 IF ISTEXT(cell) AND INSTR(1,cell.text,".") THEN cell.value = DATESERIAL(RIGHT(cell.TEXT,4), MID(cell.TEXT,4 ,2), 左(cell.TEXT,2))。这应该转换为真正的 Excel 数据格式,之后您可以应用单元格格式。【参考方案4】:月(日)&“-”&日(日)&“-”&年(日)
【讨论】:
【参考方案5】:您实际上并不需要 VBA。这个单行工作表公式可以解决问题:
=IF(ISERROR(FIND(".",A1)),IF(ISERROR(FIND("/",A1)),"invalid format",
DATE(RIGHT(A1,4),LEFT(A1,2),MID(A1,4,2))),
DATE(RIGHT(A1,4),MID(A1,4,2),LEFT(A1,2)))
这假设日期和月份总是以两位数的形式给出(例如,总是 03 而不仅仅是 3)并且年份有四位数字(即“限制”为 1000-9999 年)。但如果您不是这种情况,则可以轻松调整公式以适合您的目的。
【讨论】:
+1 非常好!我倾向于在 VBA 中编写一些代码(主要是因为我有错误输入长公式的坏习惯),但这是最有效的方法。【参考方案6】:看看这是否符合您的要求。您可能需要根据自己的应用程序对其进行一些调整。
希望这会有所帮助!
Sub convertDates()
Dim rRng As Range
Dim rCell As Range
Dim sDest As String
Dim sYear, sMonth, sDay, aDate
'Range where the dates are stored, excluding header
Set rRng = Sheet1.Range("A2:A11")
'Column name of destination
sDest = "B"
'You could also use the following, and just select the range.
'Set rRng = Application.selection
For Each rCell In rRng.Cells
sYear = 99999
If InStr(rCell.Value, ".") > 0 Then
aDate = Split(rCell.Value, ".")
If UBound(aDate) = 2 Then
sDay = aDate(0)
sMonth = aDate(1)
sYear = aDate(2)
End If
ElseIf InStr(rCell.Value, "/") > 0 Then
aDate = Split(rCell.Value, "/")
If UBound(aDate) = 2 Then
sDay = aDate(1)
sMonth = aDate(0)
sYear = aDate(2)
End If
End If
With rCell.Range(sDest & "1")
If sYear <> 99999 Then
On Error Resume Next
.Value = "'" & Format(CDate(sMonth & "/" & sDay & "/" & sYear), "YYYY-MM-DD")
'If it can't convert the date, just put the original value in the dest
'cell. You can tailor this to your own preference.
If Err.Number <> 0 Then .Value = rCell.Value
On Error GoTo 0
Else
.Value = rCell.Value
End If
End With
Next
End Sub
【讨论】:
以上是关于将日期格式更改为 yyyy-mm-dd的主要内容,如果未能解决你的问题,请参考以下文章
将数据框日期列的 dd-mm-yyyy 日期格式更改为 yyyy-mm-dd [重复]
如何将毫秒更改为 yyyy-MM-dd HH:mm:ss 格式的日期对象 [重复]
将python中索引的日期格式从yyyy-dd-mm更改为yyyy-mm-dd