拆分字符串并在Access VBA中转换为Datetime

时间:2016-08-10 04:43:12

标签: vba ms-access access-vba access

您好我的Access database中有一个列,我从日志文件导入。我在日志文件中的日期和时间格式如下: 2016:6:28:10:15:0:390000000基本上是: yyyy:mm:dd:hh:mm:ss:ms

当我在访问中导入日志文件时,它将其作为文本读取为一列。但是,我希望将其分为两列,并将其读作: column1:yyyy:mm:dd 第2栏:hh:mm:ss

格式为Datetime而不是文字。我需要使用Excel VBA执行此操作。我无法找到解决方案。请帮忙!

2 个答案:

答案 0 :(得分:1)

由于字符串的长度可变,这有点棘手。

但是这样做:切断毫秒,替换datepart的分隔符以及datepart和timepart之间的间隔。然后转换为日期或时间:

DateColoumn = DateValue(Replace(Replace(Left([DateTimeText], Len([DateTimeText]) - 10), ":", "-", , 2), ":", " ", , 1))
TimeColoumn = TimeValue(Replace(Replace(Left([DateTimeText], Len([DateTimeText]) - 10), ":", "-", , 2), ":", " ", , 1))

如果这是针对数据库表, Rene的建议是正确的:仅使用一个字段:

LogTime = CDate(Replace(Replace(Left([DateTimeText], Len([DateTimeText]) - 10), ":", "-", , 2), ":", " ", , 1))

编辑:

组合值也可以通过用户显示的 Split 获得,但我会稍微简化一下:

LogTime = ConvertLog([DateTimeText])

使用这样的函数:

Public Function ConvertLog(ByVal Entry As String) As Date

    Dim Parts   As Variant
    Dim LogTime As Date

    Parts = Split(Entry, ":")

    LogTime = DateSerial(Parts(0), Parts(1), Parts(2)) + TimeSerial(Parts(3), Parts(4), Parts(5))

    ConvertLog = LogTime

End Function

答案 1 :(得分:0)

这种表示法对于非常大的日志来说是典型的,并且通过非常慢的字符串函数解析它,就像Gustav解决方案一样,并不好。更多 - 它没有考虑部分秒数部分

Sub sb_SplitDate()
Dim dDate As Date, dDatDat As Date, dDatTim As Date
Dim i&, lArr&(), lLB&, lUB&
Dim sDatInc$, sArr$(), sClm1$, sClm2$

    sDatInc = "1999:12:31:23:59:59:50000000000000000"
    sDatInc = "1999:12:31:23:59:59:49999999999999999"
    sDatInc = "2016:6:28:10:15:0:49999"
    sDatInc = "2016:6:28:10:15:0:50"
    sDatInc = "2016:6:28:10:15:0:5"
    sDatInc = "2016:6:28:10:15:0:499999999999"
    sDatInc = "2016:6:28:10:15:0:999999999999999999999999999"
sDatInc = "2016:6:28:10:15:0:390000000" ' Original

    sArr = Split(sDatInc, ":")

    lLB = LBound(sArr): lUB = UBound(sArr)
    ReDim lArr(lLB To lUB)
    For i = lLB To (lUB - 1)
        lArr(i) = CLng(sArr(i))
    Next
   'lArr(6) = CLng(Left$(sArr(6), 1))
    lArr(6) = CLng(AscW(sArr(6)) - 48) ' significantly faster
              ' or AscB 

    dDatDat = DateSerial(lArr(0), lArr(1), lArr(2))
    dDatTim = TimeSerial(lArr(3), lArr(4), lArr(5))

    dDate = dDatDat + dDatTim - _
            CLng(lArr(6) > 4) / 86400
' standard (school) rounding of the fractional part of seconds
' may gives increasing time, date, month & year ;)

    sClm1 = Format$(dDate, "yyyy:mm:dd")
    sClm2 = Format$(dDate, "hh:mm:ss")

    Debug.Print sDatInc & vbLf & _
                sClm1 & " " & sClm2 & _
                IIf(lArr(6) > 4, " ' *** Rounded Up!", "") & _
                vbLf
    Stop
End Sub

回复:古斯塔夫

>通常你将时间部分缩小
通常情况下,我的任务是站立。 如果它是时间戳 - 向下。如果它是时间diapason (勾选了多少?) - Up 。 此外,即使在第一种情况下,它也可能被舍入用于特殊目的,例如避免近时钟零事件提升。任务正在进行......

> 4/5舍入只会改变......
什么意思"只有"?你是否还等待上述简单的给定数据移动到边界之一?由于任务由OP确定,任何舍入都会转移一些值: " hh:mm:ss:ms" - > " HH:MM:SS"

> ...将所有日志记录移动0.5秒
你确定吗?如果给出原始" 2016:6:28:10:15:0:390000000"
它将被移动0.39-Down或0.61-Up ......

OP没有解释必须采用哪种舍入方式。但这并不是忘记四舍五入以支持简单切割的理由。

我提出了一些很复杂但很常见的解决方案,很容易从一个舍入转换到另一个舍入。它只需要添加唯一的' = Chr(39)符号:)

dDate = dDatDat + dDatTim ' - CLng(lArr(6) > 4) / 86400

这不难,是吗? 但它是这个任务陷阱之一及其解决方案的直观表现。

>我相信只需要一个阵列
- 是的......我明白了我并不感到惊讶,因为您认为字符串操作在数字解析等任务中是可以接受的。 第二个数组的目的是为了避免超低级字符串操作。对于我自己,我根本不会使用Split(),而只是解析字节数组...

而且,顺便说一句, - 的任务是尽量减少使用过的数组的数量,或者尝试用一两串代码填充解决方案吗?..

对不起,明星们现在不赞成字符串:)