处理#Num!将Excel导入Access时出错

时间:2013-05-13 13:54:48

标签: excel ms-access ado ms-access-2003

我正在使用ADO(Provider = "Microsoft.Jet.OLEDB.4.0")将电子表格从Excel 2003导入Access 2003。但是,我在日期字段中有一些文本条目。正如您所料,它们以#Num!值出现。

我想做的是将违规字段包裹在IIf(IsDate(FIELDNAME),FIELDNAME,#1/1/1900#)之类的内容中。但是,这仍会导致#Num!。测试IsDate()IsDate(CVar())IsError()IsError(CDat())VBAFunctionThatReturns0GivenAnyValue(FIELDNAME)也是如此。

任何人都知道我可以使用的包装函数能做什么工作?我或多或少地在我的智慧结束?

请注意:我对导入的数据没有任何控制权,因此我无法修改电子表格,就像我想的那样。我还想避免导入函数本身的特定hackery(例如使用TransferSpreadsheet)。目标是使用相同的方法引入数据,只需忽略不起作用的位。

还应该指出,丢弃这里的非日期值是合适的。作为文本导入是我想要避免的理想选择,因为它会导致链中的各种其他错误。

编辑:添加了规定,2003。我还应该指出,环境中安装的.Net框架的版本不包括(或似乎不包括)ACE.12.0提供程序。

编辑2:根据要求,这是我正在执行的SQL(略微清理)版本。请注意,这不是确切的查询,但在同一电子表格中运行此问题会导致相同的问题:

SELECT 
    CStr(Nz([Notes], "")), 
    [ID],
    [Date]
INTO
    [;DATABASE=C:\DatabaseTarget.Mdb].[tblImport]
FROM
    [Excel 8.0;Database=C:\ExcelSheet.xls].[sheet1$]
WHERE
    [ID] IS NOT NULL

通过取出INTO子句并查看[Date]的值,可以看出问题。如果它们中的任何一个是#Num!那么即使在#Num! s中执行以下操作也会导致所有Test1-5,这相当地证明了问题。:

SELECT 
    CStr(Nz([Notes], '')), 
    [ID],
    CStr(Nz([Date],'')) As [Test1],
    IsError([Date]) As [Test2],
    IsDate([Date]) As [Test3],
    IsNull([Date]) As [Test4],
    IIf(True, 1, [Date]) As [Test5],
FROM
    [Excel 8.0;Database=C:\ExcelSheet.xls].[sheet1$]
WHERE
    [ID] IS NOT NULL

2 个答案:

答案 0 :(得分:0)

IsNull()的测试看起来应该有效。对于Excel数据......

ID  ActivityDescription ActivityDate
1   activity_1          2013-05-12
2   activity_2          2013-05-13
3   activity_3          2013-05-14
4   activity_4          2013-05-15
5   activity_5          2013-05-16
6   activity_6          2013-05-17
7   activity_7          2013-05-18
8   activity_8          2013-05-19
9   activity_9          2013-05-20
10  activity_10         2013-05-21
11  activity_11         2013-05-22
12  activity_12         2013-05-23
13  activity_13         oops!
14  activity_14         2013-05-25
15  activity_15         2013-05-26

...以下Access VBA代码......

Sub adoTest()
Dim con As ADODB.Connection, rst As ADODB.Recordset
Set con = New ADODB.Connection
con.Open _
        "Provider=Microsoft.JET.OLEDB.4.0;" & _
        "Data Source=C:\Users\Public\xlsTest.xls;" & _
        "Extended Properties=""Excel 8.0;HDR=YES"";"
Set rst = New ADODB.Recordset
rst.Open "SELECT * FROM [Sheet1$]", con
Do While Not rst.EOF
    Debug.Print _
            Format(rst("ID").Value, "00") & _
            "  " & _
            IIf(IsNull(rst("ActivityDate").Value), "<NULL>", rst("ActivityDate").Value)
    rst.MoveNext
Loop
rst.Close
Set rst = Nothing
con.Close
Set con = Nothing
End Sub

...产生这个:

01  2013-05-12
02  2013-05-13
03  2013-05-14
04  2013-05-15
05  2013-05-16
06  2013-05-17
07  2013-05-18
08  2013-05-19
09  2013-05-20
10  2013-05-21
11  2013-05-22
12  2013-05-23
13  <NULL>
14  2013-05-25
15  2013-05-26

这表明IsNull()将“错误”日期值识别为Null,而是替换文字<NULL>

根据上下文,Nz()函数也可能有用。

答案 1 :(得分:0)

#Num!在提供程序遇到可用于查询中的错误处理的大多数错误方法之前,错误似乎由提供程序引发。坚持使用ADO似乎很容易失败。

然而,在DAO中测试我的查询(没有INTO子句来生成记录集)确实产生了有效的sata,所以我认为DAO可以处理对OLEDB记录源的查询可能是值得的。事实证明它可以!

因此最终代码看起来像

On Error Resume Next
cmdFirstTry.Execute '' Includes fields which are pulled through as #Num! errors
Select Case Err.Number
    Case 0
        On Error Goto ErrorHandler
    Case &H80040E14
        '' Failed in this manner; Try with DAO
        On Error Goto ErrorHandler
        CurrentDb.Execute strSQL
    Case Else
        lngErrNum = Err.Number
        strErrDesc = Err.Description
        On Error Goto ErrorHandler
        Err.Raise lngErrNum, , strErrDesc
End Select

根据我的需要,这可以胜任这项工作,但我不会接受几天的答案,以防真的有一种优雅的方法。