如何检查单元格中的日期是实际日期还是字符串日期?
How to check if the date in a cell is an actual date or a string date?
在工作中,我们使用 Office 365 Excel 的文件作为预订系统。每个站点都有多个选项卡,每个记录都有一个预订日期。存在日期格式问题 - 基本上默认区域设置为 "mm/dd/yyyy"
,但日期显示为 "dd/mm/yyyy"
。当人们手动添加行(通常每天自动生成预订时段)并且只是以错误的格式输入日期而不是从它显示正确的相邻单元格复制日期值时,但顶部栏中的单元格值不同,但是在 Desktop App
中打开此文件时,它根本不会将其视为不同的值。只有在应用过滤器时,才有日期和字符串日期值可以作为过滤依据。这会导致某些日期在创建报告或基于日期导入数据时未被宏选取。
我一直在考虑编写一个实用程序宏,根据当前日期前后的日期清理所有日期,但是我不确定这是否是最好的方法。我不认为我可以只更改所有用户的语言环境设置,就像我在文档中阅读的那样,这只会对单个用户设置进行更改,我不确定这将如何影响整个系统的整体功能。有什么方法可以比解析这个庞大的文件或手动查找这个日期更容易完成吗?
这真的很痛苦,因为这个文件是在我加入团队之前很久就设计的,现在我正努力让它更不容易出错。
提前感谢您提供任何线索!
实际日期是数字。所以你可以检查 IsNumeric
If IsNumeric(Range("A1").Value2) Then
Debug.Print "date"
Else
Debug.Print "string"
End If
请注意,您需要检查 .Value2
而不是 .Value
看来您的问题源于人们输入的日期无效。
您可以尝试对单元格应用数据验证以在数据输入期间进行清理。
数据验证允许将单元格设置为日期,然后您可以指定日期范围。因此只允许该范围内的有效日期。
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
在工作中,我们使用 Office 365 Excel 的文件作为预订系统。每个站点都有多个选项卡,每个记录都有一个预订日期。存在日期格式问题 - 基本上默认区域设置为 "mm/dd/yyyy"
,但日期显示为 "dd/mm/yyyy"
。当人们手动添加行(通常每天自动生成预订时段)并且只是以错误的格式输入日期而不是从它显示正确的相邻单元格复制日期值时,但顶部栏中的单元格值不同,但是在 Desktop App
中打开此文件时,它根本不会将其视为不同的值。只有在应用过滤器时,才有日期和字符串日期值可以作为过滤依据。这会导致某些日期在创建报告或基于日期导入数据时未被宏选取。
我一直在考虑编写一个实用程序宏,根据当前日期前后的日期清理所有日期,但是我不确定这是否是最好的方法。我不认为我可以只更改所有用户的语言环境设置,就像我在文档中阅读的那样,这只会对单个用户设置进行更改,我不确定这将如何影响整个系统的整体功能。有什么方法可以比解析这个庞大的文件或手动查找这个日期更容易完成吗?
这真的很痛苦,因为这个文件是在我加入团队之前很久就设计的,现在我正努力让它更不容易出错。
提前感谢您提供任何线索!
实际日期是数字。所以你可以检查 IsNumeric
If IsNumeric(Range("A1").Value2) Then
Debug.Print "date"
Else
Debug.Print "string"
End If
请注意,您需要检查 .Value2
而不是 .Value
看来您的问题源于人们输入的日期无效。 您可以尝试对单元格应用数据验证以在数据输入期间进行清理。 数据验证允许将单元格设置为日期,然后您可以指定日期范围。因此只允许该范围内的有效日期。
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