2016-12-23 106 views
0

感謝您的期待,Excel VBA時間問題

我有一個問題與下面的VBA代碼。可能有些簡單。

如果我輸入時間23:30它會自動更改爲23:29

如果我進入的2330,因爲它應該變爲23:30。

那麼爲什麼當我輸入23:30時它會變成23:29?它應該保持23:30

感謝

Private Sub Worksheet_Change(ByVal Target As Excel.Range) 
    Dim xStr As String 
    Dim xVal As String 
    Set rng1 = Range("J:J") 
    Set rng2 = Range("P:P") 
    Set rng3 = Range("S:S") 
     On Error GoTo EndMacro 
    If Application.Intersect(Target, Union(rng1, rng2, rng3)) Is Nothing Then Exit Sub 
    If Target.Count > 1 Then Exit Sub 
    If Target.Value = "" Then Exit Sub 
    If Target.Row < 5 Then Exit Sub 
    Application.EnableEvents = False 
    With Target 
     If Not .HasFormula Then 
      Target.Value = Replace(Target.Value, ";", ":") 
      Target.Value = Left(Target.Value, 5) 
      xVal = .Value 
      Select Case Len(xVal) 
       Case 1 ' e.g., 1 = 00:01 AM 
        xStr = "00:0" & xVal 
       Case 2 ' e.g., 12 = 00:12 AM 
        xStr = "00:" & xVal 
       Case 3 ' e.g., 735 = 07:35 AM 
        xStr = "0" & Left(xVal, 1) & ":" & Right(xVal, 2) 
       Case 4 ' e.g., 1234 = 12:34 
        xStr = Left(xVal, 2) & ":" & Right(xVal, 2) 
       Case 5 ' e.g., 12:45 = 12:45 
        xStr = Left(xVal, 2) & Mid(xVal, 2, 1) & Right(xVal, 2) 
       Case Else 
        Err.Raise 0 
      End Select 
      .Value = Format(TimeValue(xStr), "hh:mm") 
     End If 
    End With 
    Application.EnableEvents = True 
    Exit Sub 
EndMacro: 
    Application.EnableEvents = True 
End Sub 
+0

什麼時候「更改」?在工作表中,當你查看它或代碼中的某個位置時? – mountainclimber

回答

1

這是因爲Excel將時間字段視爲一天的分數。

例如:

  • 24小時= 1
  • 12小時= 0.5
  • 6小時= 0.25

在你的情況:23h30 = 0,979166666 ...

但你只能得到前5個字符:Left(Target.Value, 5) ' "0.979"

並將此新值(0.979)作爲當前值傳遞給單元格Target.Value = Left(Target.Value, 5)

於是就行xStr = Left(xVal, 2) & Mid(xVal, 2, 1) & Right(xVal, 2),你的代碼實際上正在做的是:

Left(0.979, 2) ' -> "0."

Mid(xVal, 2, 1) ' -> "."

Right(xVal, 2) ' -> "79"

所以,當你加入,結果如下:

"0." & "." & "79" = "0..79"

"0..79"不是該單元的有效值。然後發生錯誤,並且功能最終保持0.97923:29的值。

我的建議是,如果它已經小於1,請不要更改單元格的值。因爲它表明它已經是時候了。

  1. 刪除線:Target.Value = Left(Target.Value, 5)
  2. 直接分配xval的價值:xVal = Left(Target.Value, 5)
  3. 改變 「案5」 條件如下:xStr = Format(Target.Value, "hh:mm")

完整的代碼如下所示:

Private Sub Worksheet_Change(ByVal Target As Excel.Range) 
    Dim xStr As String 
    Dim xVal As String 
    Set rng1 = Range("J:J") 
    Set rng2 = Range("P:P") 
    Set rng3 = Range("S:S") 
    On Error GoTo EndMacro 

    If Application.Intersect(Target, Union(rng1, rng2, rng3)) Is Nothing Then Exit Sub 
    If Target.Count > 1 Then Exit Sub 
    If Target.Value = "" Then Exit Sub 
    If Target.Row < 5 Then Exit Sub 
    Application.EnableEvents = False 
    With Target 
     If Not .HasFormula Then 
      Target.Value = Replace(Target.Value, ";", ":") 
      xVal = Left(Target.Value, 5) ' CHANGED! 
      Select Case Len(xVal) 
       Case 1 ' e.g., 1 = 00:01 AM 
        xStr = "00:0" & xVal 
       Case 2 ' e.g., 12 = 00:12 AM 
        xStr = "00:" & xVal 
       Case 3 ' e.g., 735 = 07:35 AM 
        xStr = "0" & Left(xVal, 1) & ":" & Right(xVal, 2) 
       Case 4 ' e.g., 1234 = 12:34 
        xStr = Left(xVal, 2) & ":" & Right(xVal, 2) 
       Case 5 ' e.g., 12:45 = 12:45 
        xStr = Format(Target.Value, "hh:mm") ' CHANGED! 
       Case Else 
        Err.Raise 0 
      End Select 
      .Value = Format(TimeValue(xStr), "hh:mm") ' CHANGED! 
     End If 
    End With 
    Application.EnableEvents = True 
    Exit Sub 
EndMacro: 
    Application.EnableEvents = True 
End Sub 
+0

感謝似乎正在工作。 – jynxy

0

看來你正在嘗試做的事情日期走錯了路,因爲通常和推薦的方式格式化日期是使用Format聲明。

但是,如果你要處理的日期/時間作爲字符串,你需要做一些改變你的代碼中,3線正好經過測試:

If Not .HasFormula Then 
     .Value = Replace(.Text, ";", ":") ' <-- use .Text 
     .Value = Left(.Text, 5)   ' <-- 
     xVal = .Text      ' <-- 

或者更好的,直接分配XVAL:

If Not .HasFormula Then 
     xVal = Left(Replace(.Text, ";", ":"), 5) ' <-- 

在另一方面,你用.Value越來越被編碼的日期,這通常是編碼爲一個數字,然後你被截斷的日期到最左邊的5個位數,這自然會導致一些不精確。