簡體   English   中英

意外日期結果 - Excel VBA - 日月年混淆

[英]Unexpected Date Results - Excel VBA - Day Month Year get mixed up

我有兩個日期范圍,我試圖將它們轉換為兩個字符串OldestDateNewestDate 但是,今天我遇到了問題,其中一個日期的格式為dd/mm/yyyy ,而另一個日期的格式為mm/dd/yyyy

這是我放在兩個單獨工作表上的示例數據: 注意,我復制了“日期”格式單元格旁邊的單元格內容以供視覺參考,但在我的實際數據中,只有“日期”列。

在此處輸入圖片說明

在此處輸入圖片說明

這是我用來轉換為字符串和調試輸出的代碼:

Public Sub Get_Date()
 
DateHeader = "A"

Set rng = Application.ActiveSheet.Range(DateHeader & "1:" & DateHeader & Cells(Rows.Count, 1).End(xlUp).Offset(1).Row)

OldestDate = Format(WorksheetFunction.min(rng), "dd/mm/yyyy")
Debug.Print OldestDate

NewestDate = Format(WorksheetFunction.Max(rng), "dd/mm/yyyy")
Debug.Print NewestDate

'20200908
'Sept 8, 2020

aDate = Split(OldestDate, "/")
If UBound(aDate) = 2 Then
 sDay = aDate(0)
 If Len(sDay) = 1 Then
  sDay = "0" & sDay
 End If
 sMonth = aDate(1)
 If Len(sMonth) = 1 Then
  sMonth = "0" & sMonth
 End If
 sYear = aDate(2)
End If
OldestDateStr = sYear & sMonth & sDay
Debug.Print OldestDateStr

aDate = Split(NewestDate, "/")
If UBound(aDate) = 2 Then
 sDay = aDate(0)
 If Len(sDay) = 1 Then
  sDay = "0" & sDay
 End If
 sMonth = aDate(1)
 If Len(sMonth) = 1 Then
  sMonth = "0" & sMonth
 End If
 sYear = aDate(2)
End If
NewestDateStr = sYear & sMonth & sDay
Debug.Print NewestDateStr

End Sub

控制台/調試:

7/10/2020 ' This is Correct
8/10/2020 ' This is Correct
20201007  ' This is Correct
20201008  ' This is Correct
8/17/2020 ' Incorrect
8/18/2020 ' Incorrect
20201708  ' Incorrect
20201808  ' Incorrect

我采取了一種解決方法與調試相比,只是刮掉了月/年,然后在第一天硬編碼 1 並使用函數EoMonth來獲得最后一天。 這被用來創建一個 URL 以根據日期進行查詢,查詢將花費更長的時間並有額外的數據,但是對我來說沒關系,我寧願擁有 100% 的可靠性。

這是新代碼,閱讀起來也不那么復雜:)

Public Sub Get_Date()
 
DateHeader = "A"

Set rng = Application.ActiveSheet.Range(DateHeader & "1:" & DateHeader & Cells(Rows.Count, 1).End(xlUp).Offset(1).Row)

Dim OldestDate As Date, NewestDate As Date

OldestDate = Format(WorksheetFunction.min(rng), "mm/yyyy")
Debug.Print OldestDate
NewestDate = Format(WorksheetFunction.Max(rng), "mm/yyyy")
Debug.Print NewestDate

'20200908
'Sept 8, 2020

'OldestDate
aDate = Split(OldestDate, "/")
sYear = aDate(2)
sMonth = aDate(0)
If Len(sMonth) = 1 Then
 sMonth = "0" & sMonth
End If
sDay = "01"
OldestDateStr = sYear & sMonth & sDay
Debug.Print OldestDateStr

'NewestDate
aDate = Split(NewestDate, "/")
sYear = aDate(2)
sMonth = aDate(0)
If Len(sMonth) = 1 Then
 sMonth = "0" & sMonth
End If
sDay = Day(Application.WorksheetFunction.EoMonth(NewestDate , 0))
NewestDateStr = sYear & sMonth & sDay
Debug.Print NewestDateStr

End Sub

調試:(注意我將一個日期更改為 Nov 只是為了測試)

10/1/2020 
11/1/2020 
20201001
20201130
8/1/2020 
8/1/2020 
20200801
20200830

Format 將一次性完成此操作:

OldestDateStr = Format(WorksheetFunction.min(rng), "yyyymmdd")
Debug.Print OldestDateStr

NewestDateStr = Format(WorksheetFunction.Max(rng), "yyyymmdd")
Debug.Print NewestDateStr

如果您的單元格值是格式化為“反向”美國格式mm/dd/yyyy 的文本日期,並且您不在美國環境中,則可以使用此函數將這些值轉換為真實的日期值:

' Converts a US formatted date/time string to a date value.
'
' Examples:
'   7/6/2016 7:00 PM    -> 2016-07-06 19:00:00
'   7/6 7:00 PM         -> 2018-07-06 19:00:00  ' Current year is 2018.
'   7/6/46 7:00 PM      -> 1946-07-06 19:00:00
'   8/9-1982 9:33       -> 1982-08-09 09:33:00
'   2/29 14:21:56       -> 2039-02-01 14:21:56  ' Month/year.
'   2/39 14:21:56       -> 1939-02-01 14:21:56  ' Month/year.
'   7/6/46 7            -> 1946-07-06 00:00:00  ' Cannot read time.
'   7:32                -> 1899-12-30 07:32:00  ' Time value only.
'   7:32 PM             -> 1899-12-30 19:32:00  ' Time value only.
'   7.32 PM             -> 1899-12-30 19:32:00  ' Time value only.
'   14:21:56            -> 1899-12-30 14:21:56  ' Time value only.
'
' 2018-03-31. Gustav Brock. Cactus Data ApS, CPH.
'
Public Function CDateUs( _
    ByVal Expression As String) _
    As Date
    
    Const PartSeparator As String = " "
    Const DateSeparator As String = "/"
    Const DashSeparator As String = "-"
    Const MaxPartCount  As Integer = 2

    Dim Parts           As Variant
    Dim DateParts       As Variant
    
    Dim DatePart        As Date
    Dim TimePart        As Date
    Dim Result          As Date
    
    ' Split expression into maximum two parts.
    Parts = Split(Expression, PartSeparator, MaxPartCount)
    
    
    If IsDate(Parts(0)) Then
        ' A date or time part is found.
        ' Replace dashes with slashes.
        Parts(0) = Replace(Parts(0), DashSeparator, DateSeparator)
        If InStr(1, Parts(0), DateSeparator) > 1 Then
            ' A date part is found.
            DateParts = Split(Parts(0), DateSeparator)
            If UBound(DateParts) = 2 Then
                ' The date includes year.
                DatePart = DateSerial(DateParts(2), DateParts(0), DateParts(1))
            Else
                If IsDate(CStr(Year(Date)) & DateSeparator & Join(DateParts, DateSeparator)) Then
                    ' Use current year.
                    DatePart = DateSerial(Year(Date), DateParts(0), DateParts(1))
                Else
                    ' Expression contains month/year.
                    DatePart = CDate(Join(DateParts, DateSeparator))
                End If
            End If
            If UBound(Parts) = 1 Then
                If IsDate(Parts(1)) Then
                    ' A time part is found.
                    TimePart = CDate(Parts(1))
                End If
            End If
        Else
            ' A time part it must be.
            ' Concatenate an AM/PM part if present.
            TimePart = CDate(Join(Parts, PartSeparator))
        End If
    End If
    
    Result = DatePart + TimePart
        
    CDateUs = Result

End Function

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM