我有一个包含许多日期的电子表格。这些通常显示在mm/dd/yyyy
或mm/dd/yyyy hh:mm
。
问题是日期并不总是正确放入,我想要检查以确保它们是代码中的日期。
我最初的想法是使用IsDate
来检查或CDate
但这似乎不起作用:它仍然是返回字符串而不是日期。
我已经设置了一个小实验,表明这些功能不像我期望的那样工作。方法是:
=DATE(2013,10,28)
=A1*1
应该等于数字(41575)运行这个小脚本
Sub test()
MsgBox ("Start:" & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
ActiveCell.Value = Format(ActiveCell.Value, "mm/dd/yyyy")
MsgBox ("After format: " & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
ActiveCell.Value = CDate(ActiveCell.Value)
MsgBox ("After Cdate: " & TypeName(ActiveCell.Value) & " " & IsDate(ActiveCell.Value))
End Sub
当脚本启动时,单元格的类型为日期,IsDate
返回true。在Format
运行后,它的类型为字符串,但IsDate
仍然返回true。 CDate
也会将单元格转换为字符串。单元格B1现在也将返回0(因为它是一个字符串* 1)。
所以我想总结一下问题:
Format
和CDate
将我的单元格更改为字符串?答案 0 :(得分:17)
通过VBA区分单元格的内容,显示格式,数据类型读取非常重要,< em>数据类型写入到VBA中的单元格以及Excel如何自动解释这一点。 (参见例如this previous answer。)这些之间的关系可能有点复杂,因为Excel会将一种类型的值(例如字符串)解释为某种其他数据类型(例如日期),然后自动更改基于此的显示格式。你最安全的赌注它明确地做了一切,而不是依赖这种自动的东西。
我进行了实验,但我得到的结果与你没有相同。我的单元格A1一直保持日期,B1保持41575.所以我无法回答你的问题#1。结果可能取决于您的Excel版本/设置如何根据其内容自动检测/更改单元格的数字格式。
问题#2,“如何确保单元格将返回日期值”:好吧,不确定“返回”日期值是什么意思,但如果你想要包含 显示的数值作为日期,根据您从VBA写入的内容,然后您可以:
向单元格写入一个字符串值,希望Excel自动将其解释为日期和格式。交叉手指。显然这不是很强大。或者,
从VBA向单元格写入一个数值(显然,Date类型是预期类型,但Integer,Long,Single或Double也可以这样做)并明确将单元格的数字格式设置为使用.NumberFormat
属性(或在Excel中手动)所需的日期格式。这更加强大。
如果您想检查现有的单元格内容是否可以显示为日期,那么这是一个有用的功能:
Function CellContentCanBeInterpretedAsADate(cell As Range) As Boolean
Dim d As Date
On Error Resume Next
d = CDate(cell.Value)
If Err.Number <> 0 Then
CellContentCanBeInterpretedAsADate = False
Else
CellContentCanBeInterpretedAsADate = True
End If
On Error GoTo 0
End Function
使用示例:
Dim cell As Range
Set cell = Range("A1")
If CellContentCanBeInterpretedAsADate(cell) Then
cell.NumberFormat = "mm/dd/yyyy hh:mm"
Else
cell.NumberFormat = "General"
End If
答案 1 :(得分:2)
Format
将值转换为字符串。 IsDate
仍然返回true,因为它可以解析该字符串并获得有效日期。
如果您不想将单元格更改为字符串,请不要使用Format
。 (IOW,首先不要将它们转换为字符串。)使用Cell.NumberFormat
,并将其设置为您想要显示的日期格式。
ActiveCell.NumberFormat = "mm/dd/yy" ' Outputs 10/28/13
ActiveCell.NumberFormat = "dd/mm/yyyy" ' Outputs 28/10/2013
答案 2 :(得分:1)
感谢您的投入。我很明显看到一些没有在其他机器上复制的问题。根据Jean的回答,我提出了不太优雅的解决方案,似乎有效。
因为如果我直接从cdate传递一个值,或者只是将它格式化为数字,它将单元格值保留为字符串,我必须将日期值传递给数字变量,然后再将该数字传递回细胞。
Function CellContentCanBeInterpretedAsADate(cell As Range) As Boolean
Dim d As Date
On Error Resume Next
d = CDate(cell.Value)
If Err.Number <> 0 Then
CellContentCanBeInterpretedAsADate = False
Else
CellContentCanBeInterpretedAsADate = True
End If
On Error GoTo 0
End Function
使用示例:
Dim cell As Range
dim cvalue as double
Set cell = Range("A1")
If CellContentCanBeInterpretedAsADate(cell) Then
cvalue = cdate(cell.value)
cell.value = cvalue
cell.NumberFormat = "mm/dd/yyyy hh:mm"
Else
cell.NumberFormat = "General"
End If
答案 3 :(得分:0)
侧面使用value(cellref)
来评估细胞。字符串将产生&#34; #Value&#34;错误,但日期解析为数字(例如43173
)。
答案 4 :(得分:0)
要确保单元格将返回日期值而不仅仅是一个看起来像日期的字符串,首先必须将NumberFormat属性设置为Date格式,然后将实际日期放入单元格的内容中。
Sub test_date_or_String()
Set c = ActiveCell
c.NumberFormat = "@"
c.Value = CDate("03/04/2014")
Debug.Print c.Value & " is a " & TypeName(c.Value) 'C is a String
c.NumberFormat = "m/d/yyyy"
Debug.Print c.Value & " is a " & TypeName(c.Value) 'C is still a String
c.Value = CDate("03/04/2014")
Debug.Print c.Value & " is a " & TypeName(c.Value) 'C is a date
End Sub