VBA 混合数据输入的 ADO 日期格式

VBA ADO Date Formatting on Mixed Data Input

我们正在尝试使用 ADO 从关闭的工作簿中读取数据,删除所有空格并将任何错误键入的日期转换为有效格式。清理数据后,会将其上传到自定义应用程序中。

我们正在使用 ADO 来提高速度,因为我们发现使用 VBA 到 open/manipulate/close 花费的时间太长,这意味着我们错过了上传目标时间(我们有多个工作簿,我们需要将其应用到).

我们遇到的问题是将日期转换为有效格式。日期以 dd/mm/yy 或 dd.mm.yy 的形式输入到工作簿中 - 我们对此无法控制,模板是几年前创建的,我们无法更新它并应用数据验证。

我们尝试过的想法:我们有一些想法,但没有成功,有谁知道这些建议中的任何一个是否可行/建议替代想法?

检查“.”并应用 Replace(): If InStr(rs.Fields("Date").Value, ".") > 0 Then rs.Fields("Date").Value = Replace(rs.Fields("Date").Value, ".", "/")

当列以类型 202: adVarWChar 读入记录集时,这有效,不幸的是,由于大多数日期有效,记录集中的数据设置为类型 7: adDate,循环时,一次我们得到一个无效的日期格式(带点),我们得到一个调试错误:

“您无法记录更改,因为您输入的值违反了为此 table 或列表定义的设置(例如,值小于最小值或大于最大值) . 更正错误并重试

将整列数据类型转换为 202 adVarWChar: 由于上面的代码适用于格式化为文本的条目,我们想看看是否可以将整列数据直接作为文本拉入,我们已经尝试过 Casting 和 Convert 但无法让它工作 - 我没有不再有我们为此尝试的示例代码。我记得尝试将 IMEX=1 添加到连接字符串,但这似乎没有任何区别。

对整个列应用 Find/Replace 查询: 我们没有检索数据并循环遍历数据,而是直接在列上应用查找和替换查询,类似于我们能够 trim 整个列的方式。同样,我们无法找到任何有效的 code/queries。

创建一个空记录集并将列类型设置为字符串: 我们有一个想法,创建一个 blank/empty 记录集并手动将日期列设置为字符串类型,然后循环检索数据并将它们移动到新的记录集中。我们并没有在这方面走得太远,因为我们不太确定如何创建一个空白的 RS,然后我们还想,我们如何将这些数据写回工作表——因为我认为你不能写回一个关闭的工作簿。

这是我目前的代码:

Sub DataTesting()

On Error GoTo ErrorHandler

'set the workbook path of the file we want to read from
Dim workbookFileName As String
workbookFileName = "C:\Users\xxx\xxx\myWorkbook.xls"

'create a connection string
Dim connectionString As String
connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" _
    & workbookFileName _
    & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;"";" 'IMEX=1"";"

'open the connection
Dim conn As ADODB.connection
Set conn = New ADODB.connection
conn.connectionString = connectionString
conn.Open

Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset

'Convert all data in the date column to a valid date (e.g. replace dates with decimals 1.1.21 to 01/01/2021)

'set query to select all data from the date column
Dim query As String
query = "SELECT * FROM [DATA SHEET$B2:B100]"  'col B is the Date column

With rs
    .ActiveConnection = conn
    '.Fields.Append "Date", adVarChar, 20, adFldMayBeNull   'NOT WORKING
    .CursorType = adOpenDynamic
    .LockType = adLockOptimistic
    .Source = query
    .Open

    If Not .BOF And Not .EOF Then
        While (Not .EOF)
            If InStr(rs.Fields("Date").Value, ".") > 0 Then rs.Fields("Date").Value = Replace(rs.Fields("Date").Value, ".", "/")
            .MoveNext
        Wend
    End If
    .Close
End With

conn.Close

GoTo CleanUp

ErrorHandler:
MsgBox Err.Description 'THIS WILL BE WRITTEN TO TXT FILE

CleanUp:
'ensure the record set is equal to nothing and closed
If Not (rs Is Nothing) Then
    If (rs.State And adStateOpen) = adStateOpen Then rs.Close
    Set rs = Nothing
End If

'ensure the connection is equal to nothing and closed
If Not (conn Is Nothing) Then
    If (conn.State And adStateOpen) = adStateOpen Then conn.Close
    Set conn = Nothing
End If

End Sub

更新: 我现在可以使用以下查询读取数据:

"SELECT IIF([Date] IS NULL, NULL, CSTR([Date])) AS [Date] FROM [DATA SHEET$B2:B10]"

这只有在我设置 IMEX=1 时才有效,它只是只读的。我能够遍历每个项目并打印出值/检测点的位置,但我无法修改它们!

如@Doug Coats 所述,我可以将数据移动到数组中,对数组执行操作。但是我究竟该如何将该数组放回记录集中呢?

我想我需要关闭第一个 'read only' 连接,然后重新打开它作为 'write' 连接。然后以某种方式 运行 更新查询 - 但如何用数组中的值替换现有记录集值?

谢谢

您可以尝试更新查询

    Const SQL = " UPDATE [DATA SHEET$] " & _
                " SET [Date] = REPLACE([Date],""."",""/"")" & _
                " WHERE INSTR([Date],""."") > 0 "

    Dim n
    conn.Execute SQL, n
    MsgBox n & " records updated"

Sub testdata()
   Dim wb, ws, i
   Set wb = Workbooks.Add
   Set ws = wb.Sheets(1)
   ws.Name = "DATA SHEET"
   ws.Cells(1, 2) = "Date"
   For i = 2 To 10
      If Rnd() > 0.5 Then
         ws.Cells(i, 2) = "27.07.21"
      Else
         ws.Cells(i, 2) = "27/07/21"
      End If
   Next
   wb.SaveAs "c:\temp\so\dates.xls"
   wb.Close
End Sub