【问题标题】:How to check if the date in a cell is an actual date or a string date?如何检查单元格中的日期是实际日期还是字符串日期?
【发布时间】:2021-07-04 04:05:38
【问题描述】:

在工作中,我们使用 Office 365 Excel 的文件作为预订系统。对于每个记录都有预订日期的每个站点,它都有多个选项卡。日期格式存在问题 - 基本上默认语言环境设置为"mm/dd/yyyy",但日期显示在"dd/mm/yyyy" 中。当人们手动添加行时(通常每天都会自动生成预订时段)并且只是以错误的格式输入日期而不是从相邻单元格复制日期值,它显示正确,但顶部栏中的单元格值不同,但是在Desktop App 中打开此文件时,它根本不会将其视为不同的值。只有在应用过滤器时,您才能过滤日期和字符串日期值。这会导致在创建报告或基于日期导入数据时,宏无法获取某些日期。

我一直在考虑编写一个实用程序宏,它会根据当前日期的前后日期来清理所有日期,但是我不确定这是否是最好的方法。我认为我不能只更改所有用户的语言环境设置,因为我在文档中阅读的内容只会更改单个用户设置,我不确定这将如何影响整个系统的整体功能。有什么方法可以比解析这个庞大的文件或手动查找日期更容易完成吗?

这是一个真正的痛苦,因为这个文件是在我加入团队之前很长时间设计的,现在我正在努力减少这个错误的发生率。

提前感谢任何线索!

【问题讨论】:

  • 对于VBA 有函数IsDate() 试试看。
  • @Harun24HR 小心 IsDate 只是告诉您字符串是否可以读取为日期。它确实告诉你单元格内容是否是一个真正的数字日期! IsDate 将返回 True,即使单元格包含看起来像日期的字符串。
  • @Pᴇʜ 哦,我的错!我不知道这些信息。
  • 不用担心 ;) 为了您的兴趣:IsDate function(请参阅那里的示例)。
  • 另一种可能性是让他们从日历中选择日期(日期选择器)。

标签: excel vba date locale


【解决方案1】:

实际日期是数字。所以你可以通过IsNumeric查看

If IsNumeric(Range("A1").Value2) Then
    Debug.Print "date"
Else
    Debug.Print "string"
End If

请注意,您需要检查.Value2 而不是.Value

【讨论】:

  • 太好了,这在实用程序宏过程中就像一个魅力!如果有人对解决方案感兴趣,我已经发布了代码
【解决方案2】:

Peh 的回答引导我找到正确的解决方案。如果有人遇到类似问题,这是整个代码:

Sub SanitizeDates()
    ' ---
    ' Utility macro that goes over all live sheets and checks all rows
    ' for the string dates that have been input manually
    ' and converts it to an actual Date values.
    ' ---

    Debug.Print "--- Log Start"
    
    Dim Prompt As String
    Dim Errors As Integer
    Dim TotalErrors As Integer
    TotalErrors = 0
    Errors = 0

    Dim Tracker As Workbook
    Dim WS As Worksheet
    
    Dim CurrentDateValue As Variant
    Dim NewDate As Date
    Dim RowCount As Long
    Dim nRow As Long
    
    Set Tracker = ThisWorkbook
    
    Application.ScreenUpdating = False
    
    For Each WS In Tracker.Worksheets
        If WS.Visible And Not WS.Name = "Matrix" Then ' if worksheet is not visible and not a Matrix
            If InStr(1, WS.Name, "Template", vbTextCompare) = 0 Then ' if worksheet is not a template
            
                Errors = 0
                
                RowCount = WS.ListObjects(1).DataBodyRange.Rows.Count
                
                'loop over all rows in table
                For nRow = 1 To RowCount
                    With WS.ListObjects(1).DataBodyRange
                    
                        ' check if the cell is a black bar / divider
                        If Not .Cells(nRow, 3).Interior.Color = RGB(0, 0, 0) Then
                            If Not IsNumeric(.Cells(nRow, 3).Value2) Then
                                                                
                                On Error GoTo SkipInvalid
                                NewDate = DateValue(.Cells(nRow, 3).Value2)
                                .Cells(nRow, 3).Value2 = NewDate
                                Errors = Errors + 1
                                
                                'Error logging
                                'Call LogError(.Cells(nRow, 5), .Cells(nRow, 15), "Date Format - dev")
                            End If
                        End If
                    End With
SkipInvalid:
                Next nRow
                
                TotalErrors = TotalErrors + Errors
                
                If Errors Then
                    Prompt = Prompt & "Found " & Errors & " errors in " & WS.Name & vbCrLf
                    Debug.Print "Found " & Errors & " errors in " & WS.Name
                End If
                
            End If
        End If
    Next WS
    
    Application.ScreenUpdating = True
    
    Debug.Print "--- Log End"
    
    If TotalErrors Then
        MsgBox (Prompt & vbCrLf & vbCrLf & _
            "Total of " & TotalErrors & " errors found. All data sanitized successfully.")
    Else
        MsgBox ("No errors found")
    End If
End Sub

【讨论】:

  • 请注意,DateValue 猜测基于操作系统 (Windows) 中设置的日期格式的字符串中的日期。如果你有一个像02/03/2021 这样的字符串,全世界没有计算机可以说它是dd/mm/yyyy 还是mm/dd/yyyy,那么只有字符串本身是不可能的。因此,您的代码可能会猜对或错,在最坏的情况下,您最终会在数据中找到错误的日期。唯一可靠的字符串日期是 ISO 8601 格式 yyyy-mm-dd (xkcd.com/1179),因为这里不会有任何混淆。
  • 因此,如果您知道您的字符串是哪种日期格式,最好不要让 Excel 猜测并拆分字符串并将其作为真实日期放在一起。例如,如果您确定所有字符串日期都是dd/mm/yyyy,则使用Part = Split(YourStringDate, "/") 并创建一个真实日期RealDate = DateSerial(Part(2), Part(1), Part(0))。这样您就可以告诉 Excel 要做什么,而不是让它猜测。
  • 有道理!我一定会纠正这个
【解决方案3】:

您的问题似乎源于人们输入的日期无效。 您可以尝试对单元格应用数据验证以在数据输入期间进行清理。 数据验证允许将单元格设置为日期,然后您可以指定日期范围。所以只允许该范围内的有效日期。

【讨论】:

  • 在所有日期单元格上都设置了数据验证,但是在某些情况下这没有帮助,例如必须手动添加额外的行或从外部来源(如预订)复制/粘贴数据形式
猜你喜欢
  • 1970-01-01
  • 2015-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-15
相关资源
最近更新 更多