在Excel中强制date格式

我有一个列以正确的格式包含date:

dd.MM.yyyy hh:mm:ss

我想先改变“。” 到“/”哪个工作正常,下面的代码,但它会自动修改date格式,并确认一天如果12岁以下的月份。

dd / MM / yyyy hh:mm:ss

'2) Replace "." by "/" 'Range("C:C").NumberFormat = "@" ' I tried with AND without this line...no difference 'Range("C:C").NumberFormat = "dd.mm.yyyy hh:mm:ss" ' if I add this then only "." starting from 13th of January are reaplced by "/" 'Range("C:C").NumberFormat = "dd/mm/yyyy hh:mm:ss" ' no differences at all neither Columns("C:C").Select Selection.Replace What:=".", Replacement:="/", LookAt:=xlPart, _ SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=False, _ ReplaceFormat:=False 

所以烦人…任何想法如何解决这个问题?

如果您不介意循环访问数据,则可以执行以下操作:

 Sub Test() Dim ws As Worksheet Set ws = ThisWorkbook.Sheets("SheetName") For Each Cell In ws.Range("C2:C" & ws.Cells(ws.Rows.Count, "C").End(xlUp).Row) Cell.Value = CDate(Replace(Cell.Value, ".", "/")) Next Cell End Sub 

或者,如果你想要,你可以使用一个帮手列,并使用下面的公式:

 =TEXT(DATE(MID(C2,SEARCH(".",C2,SEARCH(".",C2,1)+1)+1,4),MID(C2,SEARCH(".",C2,1)+1,2),MID(C2,1,2))+TIMEVALUE(RIGHT(C2,8)),"dd/mm/yyyy hh:mm:ss") 

此代码采用Sheet1 C2:C25 ,将其转换为内存数组,遍历该数组并将所有值转换为实际date ,然后将转换的值转储到Sheet1上的D2:D25 ,在D列中应用所需的NumberFormat ,然后调整列的大小以适应。

输出结果

结果是正确处理date的date,自定义格式:

 Public Sub ConvertToDate() Dim target As Variant target = ToArray(Sheet1.Range("C2:C25")) 'todo: adjust to desired range Dim i As Long For i = LBound(target) To UBound(target) target(i) = ToDate(target(i)) Next 'here you'd probably dump the result in C2: Sheet1.Range("D:D").NumberFormat = "dd.MM.yyyy hh:mm:ss" Sheet1.Range("D2").Resize(UBound(target), 1).value = Application.WorksheetFunction.Transpose(target) Sheet1.Range("D:D").EntireColumn.AutoFit End Sub Private Function ToDate(ByVal value As String) As Date ' make sure our assumptions are correct before going any further: Debug.Assert value Like "##.##.#### ##:##:##" Dim datetimeParts As Variant datetimeParts = Strings.Split(value, " ") Dim dateParts As Variant dateParts = Strings.Split(datetimeParts(0), ".") Dim datePart As Date datePart = DateTime.DateSerial(dateParts(2), dateParts(1), dateParts(0)) Dim result As Date result = CDate((CStr(datePart) & " " & datetimeParts(1))) ToDate = result End Function 

ToArray帮助函数是这个(从这篇文章改编的 ):

 Private Function ToArray(ByVal target As Range) As Variant Select Case True Case target.Rows.Count = 1 'horizontal 1D range ToArray = Application.WorksheetFunction.Transpose(Application.WorksheetFunction.Transpose(target.value)) Case target.Columns.Count = 1 'vertical 1D range ToArray = Application.WorksheetFunction.Transpose(target.value) Case Else '2D array: let Excel to the conversion itself ToArray = target.value End Select End Function 

您应该能够轻松地调整此代码以处理您的工作表和数据。

这应该足够你需要的东西。 我不在乎这里的.Range("C:C") ,但只要列C中只有这个数据,这应该没问题。 使用的问题。 Range("C:C")是它总是会修改和加载整个列,这可能会降低性能。 如果我有机会,不好编辑代码使用更优雅的解决scheme,我只是想先得到一个工作的答案,让你开始。

无论如何,这是代码:

 Sub FixDateFormatting() Dim ArrayDates() As Variant ' Load all the dates into an array for modification ArrayDates = ThisWorkbook.Sheets(1).Range("C:C").Value ' Edit the format of the destination to be text based. This will prevent Excel from assuming format ' Note: This must be done after the values are put into the array, otherwise you could load values in the ' wrong format. ThisWorkbook.Sheets(1).Range("C:C").NumberFormat = "@" Dim i As Long ' Loop through the array and properly format all of the data For i = LBound(ArrayDates, 1) To UBound(ArrayDates, 1) ArrayDates(i, 1) = Format(CStr(Replace(ArrayDates(i, 1), ".", "/")), "dd/mm/yyyy hh:mm:ss") Next ' Output the modified data ThisWorkbook.Sheets(1).Range("C:C").Value = ArrayDates End Sub 

ThisWorkbook.Sheets(1)replace为正在修改的工作表的适当引用。 如果目标工作表是运行代码的工作簿中的第一个工作表,则不必如此。

这应该比一个循环好得多。 这种方法唯一的缺点是,为了从这些单元格中检索值并对它们执行操作(使用dd-mm-yyyy格式),您必须在另一个数组中检索和操作这些值。 如果您尝试使用这些值的Excel公式,您将不会得到预期的结果。 这是不可避免的(至less据我所知),当你使用非标准的date格式。

如果您有任何问题,请告诉我。

保重,

布兰登

编辑:

这是一个稍微更优雅的解决scheme,应该稍微提高性能。 我(有希望)更容易设置正确的目标工作表。 我也调整了范围只包括必要的行数。 见下文:

 Sub FixDateFormatting() Dim TargetSheet As Worksheet ' Set the correct target sheet here: Set TargetSheet = ThisWorkbook.Sheets(1) Dim LastColRow As Long ' Store the absolute last row within a long variable for later use LastColRow = TargetSheet.Range("C1048576").End(xlUp).Row Dim TargetRange As Range ' Assumes your data starts in cell 2 (has a header row). Change the 2 as needed. Set TargetRange = TargetSheet.Range("C2:C" & LastColRow) Dim ArrayDates() As Variant ' Load all the dates into an array for modification ArrayDates = TargetRange.Value ' Edit the format of the destination to be text based. This will prevent Excel from assuming format ' Note: This must be done after the values are put into the array, otherwise you could load values in the ' wrong format. TargetRange.NumberFormat = "@" Dim i As Long ' Loop through the array and properly format all of the data For i = LBound(ArrayDates, 1) To UBound(ArrayDates, 1) ArrayDates(i, 1) = Format(CStr(Replace(ArrayDates(i, 1), ".", "/")), "dd/mm/yyyy hh:mm:ss") Next ' Output the modified data TargetRange.Value = ArrayDates End Sub 

编辑(再次):

这最后一个解决scheme是更加优雅,并保留“date”格式。 您可以根据需要编辑单元格。 这使用了一个UDF(用户定义的函数)。 您只需键入要修复date的function作为目标。 它会输出一个date,然后您可以修改为您需要的格式:

 Public Function FixDateFormat(InputDate As String) As Date ' This will ensure that the string being input is appropriate for this function ' Modify the pattern as needed. If InputDate Like "##.##.#### ##:##:##" Then Dim DateTime As Variant DateTime = Split(InputDate, " ") Dim DateInfo As Variant DateInfo = Split(DateTime(0), ".") Dim HolderString As String HolderString = Format(DateInfo(1), "00") & "/" & Format(DateInfo(0), "00") & "/" & Format(DateInfo(2), "0000") & " " & DateTime(1) Debug.Print HolderString Dim OutputDate As Date OutputDate = CDate(HolderString) FixDateFormat = OutputDate Else ' Comment out this line to return a "#VALUE" error instead FixDateFormat = vbNullDate Exit Function End If End Function 

无需手动修改区域设置,您必须使用循环。

 LastRow = Cells(Rows.Count, "C").End(xlUp).Row Set r = Range(Cells(1, "C"), Cells(LastRow, "C")) t = r.Value For i = 1 To UBound(t) t(i, 1) = Replace(t(i, 1), ".", "/") Next r.NumberFormat = "" r.FormulaLocal = t 

有很多种处理方法,最明显的是调整你的NumberFormat属性。 尝试用各种格式logging一些macros,看看它如何为你工作。 在你的情况下,代码可能是这样的:

 Sheet1.Columns("C:C").NumberFormat = "mm/dd/yyyy" 

那么这样的事情呢?

 Sub Makro3() Columns("C:C").Select Selection.NumberFormat = "dd\/mm\/yyyy hh:mm:ss" End Sub 

新增hh:mm:ss