2016-01-18 125 views
1

我試圖以按時間順序而不是由它們在列值升序給定範圍內的如何排序的範圍按時間順序VBA

下面的代碼檢查,如果任何值在列改變的B到Z並將日期和時間放在列A的相應單元格行中。

該宏的目標是將最後編輯的行放在表格的底部。

enter image description here

Option Explicit 

Private Sub Worksheet_Change(ByVal Target As Range) 

    Dim Cel As Range 
    Dim m As Long 
    Dim DataRange As Range 
    Dim keyRange As Range 
    Set DataRange = Range("A2:Z1048567") 
    Set keyRange = Range("A2") 

    Application.ScreenUpdating = False 
     For Each Cel In Target 
     If Not Intersect(Target, Cel) Is Nothing And Cel.Column > 1 And Cel.Column <= 26 Then 
      m = Cel.Row 
      With ActiveSheet.Range("A" & m) 
       .Value = Date & " " & Time 
       .NumberFormat = "dd/mm/yyyy hh:mm AM/PM " 
      End With 
      DataRange.Sort Key1:=keyRange, Order1:=xlAscending 
      Application.ScreenUpdating = True 
      Exit Sub 
     End If 
     Next Cel 

Application.ScreenUpdating = True 
End Sub 
+0

我可能完全錯過了問題的要點,但無論如何(npi),在改變[Worksheet_Change](https://msdn.microsoft.com/)中的任何數據之前,總是使用'Application.EnableEvents = False' en-us/library/office/ff839775.aspx)事件宏。如果沒有它,你將冒着觸發另一個事件的風險,並且該過程將在其本身之上運行,可能會觸發另一個事件和級聯失敗。請記得在退出過程之前使用'Application.EnableEvents = True'。 – Jeeped

回答

2

除非你有強制左單元格對齊方式,在A列中的日期時間實際上是 '文本是-看起來樣-A-日期時間'。最重要的是,它們處於DMY配置,VBA非常以美國爲中心(即MDY),無論計算機的區域系統設置是爲日期設置的。

您可以使用轉換程序,如CDate但結果不可靠。在明確的日期如18/01/2016 10:08:52 AM的情況下,轉換將是正確的。但是,如果您的日期時間模糊不清,如06/01/2016 10:08:52 AM,則CDate轉換很可能會返回01-Jun-2016 10:08:52而不是「正確」06-Jan-2016 10:08:52。時間需要分成一個未使用的列,然後結合到修復的日期。

使用Range.TextToColumns method命令並強制使用xlColumnDataType進行正確的DMY日期轉換。

首先選擇所有日期,對現有數據運行此例程。不要包含列標題標籤,因爲它比日期的第一個分割點長。首先選擇A2然後點擊Ctrl + Shift + 應該做得很好。

Sub repair_Dates_by_Selection() 
    Dim dt As Range 
    With Intersect(Selection, Selection.Parent.UsedRange) 
     .Columns(1).Offset(0, 1).EntireColumn.Insert 
     .TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, _ 
         FieldInfo:=Array(Array(0, 4), Array(10, 1)) 
     For Each dt In .Cells 
      dt = dt.Value2 + dt.Offset(0, 1).Value2 
     Next dt 
     .Columns(1).Offset(0, 1).EntireColumn.Delete 
     .NumberFormat = "dd/mm/yyyy hh:mm AM/PM" 
    End With 
End Sub 

完成此操作後,A列中的日期時間應該是以DMY配置格式化的實時日期。

Worksheet_Change

Private Sub Worksheet_Change(ByVal Target As Range) 

    If Not Intersect(Target, Columns("B:Z")) Is Nothing Then 
     On Error GoTo bm_Safe_Exit 
     Application.EnableEvents = False 
     Application.ScreenUpdating = False 
     Dim cel As Range 
     For Each cel In Intersect(Target, Columns("B:Z")) 
      With cel 
       Debug.Print "!" & cel.Address 
       If .Row > 1 Then 
        Intersect(Columns(1), cel.EntireRow).Value = Now 
        .NumberFormat = "dd/mm/yyyy hh:mm AM/PM_);@" 
       End If 
      End With 
     Next cel 
     With Cells(1, 1).CurrentRegion 
      .Cells.Sort Key1:=.Columns(1), Order1:=xlAscending, _ 
         Orientation:=xlTopToBottom, Header:=xlYes 
     End With 
    End If 

bm_Safe_Exit: 
    Application.EnableEvents = True 
    Application.ScreenUpdating = True 
End Sub 

上面添加事件禁用/啓用您的原始代碼。 Intersect method用於確定適用的單元格。 Now用於爲時間戳創建真正的日期時間,而不是文本 - 看起來是一個日期時間。前者可以按時間順序輕鬆分類,後者最多不可靠。