将日期格式更改为 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.yyyymm/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的主要内容,如果未能解决你的问题,请参考以下文章

如何将格式日期选择器更改为 YYYY-MM-DD

将数据框日期列的 dd-mm-yyyy 日期格式更改为 yyyy-mm-dd [重复]

如何将毫秒更改为 yyyy-MM-dd HH:mm:ss 格式的日期对象 [重复]

将python中索引的日期格式从yyyy-dd-mm更改为yyyy-mm-dd

如何将chrome,YYYY-MM-DD上的打印预览标题的日期格式更改为DD / MM / YYYY

Dart - 如何将 yyyy-MM-dd 中的简单日期字符串的格式更改为 dd-MM-yyyy