Excel VBA日期格式

时间:2013-11-06 00:06:16

标签: excel vba date excel-vba

我有一个包含许多日期的电子表格。这些通常显示在mm/dd/yyyymm/dd/yyyy hh:mm

问题是日期并不总是正确放入,我想要检查以确保它们是代码中的日期。

我最初的想法是使用IsDate来检查或CDate但这似乎不起作用:它仍然是返回字符串而不是日期。

我已经设置了一个小实验,表明这些功能不像我期望的那样工作。方法是:

  1. 在单元格A1中输入公式=DATE(2013,10,28)
  2. 单元格B1公式=A1*1应该等于数字(41575)
  3. 运行这个小脚本

    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
    
  4. 当脚本启动时,单元格的类型为日期,IsDate返回true。在Format运行后,它的类型为字符串,但IsDate仍然返回true。 CDate也会将单元格转换为字符串。单元格B1现在也将返回0(因为它是一个字符串* 1)。

    所以我想总结一下问题:

    1. 为什么FormatCDate将我的单元格更改为字符串?
    2. 如何确保单元格将返回日期值而不仅仅是一个看起来像日期的字符串?

5 个答案:

答案 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