将文本转换为日期?

31

我有一列以文本形式存储,在格式上为yyyy-mm-dd的日期(A列),我想将其转换为日期格式,从而可以对其进行查找。

我已经阅读了这里的一些主题,并尝试了一些建议,但是我无法让它们起作用。其中一个建议是使用:

Columns("A").Select
Selection.NumberFormat = "date"

这改变了单元格的格式为日期,但实际上并没有改变值的格式,它仍然被存储为文本。

我的理解是我需要使用CDate()函数将值的格式从文本更改为日期。我尝试过类似以下的操作:

Dim c As Range
For Each c In ActiveSheet.UsedRange.columns("A").Cells
    c.Value = CDate(c.Value)
Next c

我遇到了类型不匹配的错误。我想知道这是否是因为我试图将日期值保存回非日期格式的单元格,因此我尝试将其与上面的.NumberFormat = "date"组合在一起,但也没有起作用。

如果有任何建议,将不胜感激。


2
嗨 @user1300244,你找到值得采纳的答案了吗?回馈/评价答案总是很好的。 - sancho.s ReinstateMonicaCellio
类型不匹配错误通常意味着无效的日期,例如“1900-13-12”、“1900-02-29”、“10000-01-01”等。在“1899-12-30”之前的日期会导致一般性的“运行时错误 '1004':应用程序定义或对象定义错误”。 - Slai
11个回答

35

在这种情况下,您可以使用DateValue将字符串转换为日期。

Dim c As Range
For Each c In ActiveSheet.UsedRange.columns("A").Cells
    c.Value = DateValue(c.Value)
Next c

它可以直接将 yyyy-mm-dd 格式的字符串转换为本地Excel日期值。


1
顺便提一下,还有一些 TimeValue(...)Const ds = "31.12.19 16:00" 可以在德国时间格式环境中使用 DateValue(ds) + TimeValue(ds) - Andreas Covidiot
2
太好了,谢谢。即使过了7年,仍然很有用 :) - Geoff Griswald

34

您可以使用 VBA 相当于工作表的“数据”►“文本到列”命令,快速将类似日期的文本列转换为实际日期。

With ActiveSheet.UsedRange.Columns("A").Cells
    .TextToColumns Destination:=.Cells(1), DataType:=xlFixedWidth, FieldInfo:=Array(0, xlYMDFormat)
    .NumberFormat = "yyyy-mm-dd"   'change to any date-based number format you prefer the cells to display
End With

批量操作通常比循环单元格快得多,VBA的Range.TextToColumns方法非常快。它还允许您自由设置MDY vs. DMY或YMD转换掩码,这使得许多文本导入中日期格式与系统区域设置不匹配的问题得以解决。请参见TextFileColumnDataTypes属性,了解可用日期格式的完整列表。

注意事项:在导入文本时要小心,因为一些日期可能尚未转换。带有模糊月份和日期整数的基于文本的日期可能已经被错误地转换;例如,07/11/2015可能已根据系统区域设置被解释为07-Nov-2015或11-Jul-2015。在这种情况下,放弃导入并使用“数据”►“从文本获取外部数据”将文本重新导入,并在文本导入向导中指定正确的日期转换掩码。在VBA中,使用Workbooks.OpenText方法并指定xlColumnDataType。

DateValue函数的性能更佳,且使用的资源更少于TextToColumns。 - Geoff Griswald

15

除了其他选项外,我确认使用

c.Value = CDate(c.Value)

测试过了(刚用您的情况描述测试了Excel 2010)。至于您收到类型不匹配错误的原因,您可以检查一下(例如)这里

可能是地区设置的问题。


6
也许:
Sub dateCNV()
    Dim N As Long, r As Range, s As String
    N = Cells(Rows.Count, "A").End(xlUp).Row
    For i = 1 To N
        Set r = Cells(i, "A")
        s = r.Text
        r.Clear
        r.Value = DateSerial(Left(s, 4), Mid(s, 6, 2), Right(s, 2))
    Next i
End Sub

假设列A包含类似于2013-12-25的文本值,不带标题单元格。


5

我之前遇到过非常类似的问题。不幸的是,我看了这个帖子,没有找到一个让我满意的答案。希望这可以帮助其他人。

使用VBA.DateSerial(year,month,day),您可以克服Excel对美国日期格式的固有偏见。它还意味着您完全控制数据,这是我个人更喜欢的方法:

function convDate(str as string) as Date
  Dim day as integer, month as integer, year as integer
  year  = int(mid(str,1,4))
  month = int(mid(str,6,2))
  day   = int(mid(str,9,2))
  convDate = VBA.DateSerial(year,month,day)
end function

3

这段代码对我来说可用

Dim N As Long, r As Range
N = Cells(Rows.Count, "B").End(xlUp).Row
For i = 1 To N
    Set r = Cells(i, "B")
    r.Value = CDate(r.Value)
Next i

尝试更改列以适应您的表格。

这基本上与@Sam上面的答案相同,只是它使用For循环而不是ForEach循环。ForEach循环的好处有两个:首先,它自动将变量设置为等于所涉及的范围。其次,它消除了确定范围中存在多少单元格的需要。 - Grade 'Eh' Bacon
“xlUp”方法查找范围末尾对我来说很笨拙。如果您的范围之后有任何带值的单元格,它将失败。我更喜欢Sam答案中的“对于每个x在范围内”的逻辑。Excel已经知道范围中有多少单元格,我们不需要将其存储为变量。 - Geoff Griswald

1

虽然这是老问题,但我认为我找到了一个简单的答案。以下方法适用于我。我认为这相当于选择单元格,按F2,然后按回车键,使Excel将文本识别为日期。

Columns("A").Select
Selection.Value = Selection.Value

如果您有英国格式的日期(或可能是任何其他格式而不是美国格式),那么这样做通常会将以文本形式提供的英国日期转换为日期格式中的美国日期。在Sam的答案中使用DateValue方法比这个方法要好得多。 - Geoff Griswald

1
给楼主... 第一次运行你的子程序时,我也遇到了类型不匹配的错误。在我的情况下,是由于第一个单元格中存在非日期格式的数据(即标题)所致。 当我将标题单元格的内容更改为日期格式的文本以进行测试时,它就可以正常运行了...
希望这也能帮到你。

0

我通过以下代码解决了类型不匹配的问题:

Sub ConvertToDate()

Dim r As Range
Dim setdate As Range

'in my case I have a header and no blank cells in used range,
'starting from 2nd row, 1st column
Set setdate = Range(Cells(2, 1), Cells(2, 1).End(xlDown)) 

    With setdate
        .NumberFormat = "dd.mm.yyyy" 'I have the data in format "dd.mm.yy"
        .Value = .Value
    End With

    For Each r In setdate
        r.Value = CDate(r.Value)
    Next r

End Sub

但在我的特定情况下,我的数据格式为“dd.mm.yy”


0

对于 DD-MM-YYYY,这里有一个简单的解决方法来管理字符串和日期:

通过 DD-MMM-YYYY 将日期插入字符串中, 例如 01-11-2017 -> 01-Nov-2017

您可以使用 FORMAT(date, "dd-mmm-yyyy") 将日期从电子表格输入到字符串中。

稍后,当您从字符串输出时,它不会混淆天数和月份。


@GeoffGriswald,哪个答案是被采纳的答案? - Davesexcel
最受欢迎的答案抱歉。没有注意到它还没有被接受。 - Geoff Griswald

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接