将日期格式更改为yyyy-mm-dd

时间:2011-08-18 10:53:06

标签: excel vba date format

我有一个日期列,其中包含混合格式的日期。例如:

  

一个   
1990年3月21日   
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列,当我将格式函数中的参数从yyyy-mm-dd更改为dd/mm/yyyy时,它可以正常工作,但仅适用于格式为mm/dd/yyyy的日期,并且dd.mm.yyyy叶未被触及。我很感激任何建议。

6 个答案:

答案 0 :(得分:8)

更新:新答案

这是一个可以完成这项工作的解决方案!子例程包括一个替换函数(函数本身非常有用!)。运行sub,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, _
        "(\d{2})\.(\d{2})\.(\d{4})", "$3-$2-$1")
    End If
    If InStr(cell.Value, "/") <> 0 Then
        cell.Value = RegexReplace(cell.Value, _
        "(\d{2})/(\d{2})/(\d{4})", "$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 mearly循环通过你的A列,并为你提到的那两个案例做一个正则表达式替换。我首先使用Instr()的原因是为了阻止它是否需要替换,以及哪种类型。从技术上讲,你可以跳过这个但是对不需要它的单元进行替换是非常昂贵的。最后,我将单元格格式化为您的自定义日期格式,无论内部是什么安全措施。

如果你不熟悉Regex(对于ref:http://www.regular-expressions.info/),我使用的表达式是:

  • ()中的每个项目都是捕获组 - 也就是你要弄乱的东西
  • \ d代表数字[0-9]。
  • {2}表示2,而{4}表示4。我在这里明确表示安全。
  • 之前的\。在第一次更换时需要“。”有特殊意义。
  • 在VBA正则表达式中,您使用$ + no来引用捕获组。小组这就是我翻转3个项目的顺序。

答案 1 :(得分:4)

你真的不需要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年)。但如果您不是这种情况,那么可以很容易地调整公式以适合您的目的。

答案 2 :(得分:3)

看看这是否符合您的要求。您可能需要根据自己的应用进行一些定制。

希望这有帮助!

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

答案 3 :(得分:1)

@ Jean-FrançoisCorbett有一个有效的公式解决方案,但可以通过上述错误消息(基于#VALUE!提供信息)和另一个IF,两个DATE,应用可缩短一半以上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  

答案 4 :(得分:0)

以下是一个简单的解决方案:

     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

答案 5 :(得分:-1)

月(日期)&amp; “ - ”&amp;日(日期)&amp; “ - ”&amp;年份(日期)