处理#Num!将 Excel 导入 Access 时出错
Posted
技术标签:
【中文标题】处理#Num!将 Excel 导入 Access 时出错【英文标题】:Handling a #Num! Error on importing Excel into Access 【发布时间】:2013-05-13 13:54:47 【问题描述】:我正在使用 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)
也是如此。
任何人都知道我可以使用的包装函数来完成这项工作吗?我或多或少已经束手无策了?
请注意:我对导入的数据没有任何控制权,因此我无法修复电子表格,就像我想的那样。我还想避免导入函数本身的特定黑客行为(例如,改用 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!
,那么即使对所有Test1-5 在#Num!
s 中执行以下结果,也可以说明问题。:
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
【问题讨论】:
【参考方案1】:测试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()
函数也可能有用。
【讨论】:
在 ACE 下可能工作得很好,但不幸的是,我坚持使用 JET,因为这是 Office 2003。抱歉,应该指定。也就是说,不确定我是否使用 IsNull() 进行测试或直接进入 Nz。这种情况有点奇怪,因为在这些字段中出现的一些文本数据确实得到了正确解释,但有些则没有。 @tobriand 我刚刚使用 Jet 测试了代码,得到了完全相同的结果。 (我已经更新了我的答案。) 我会在几分钟内尝试一下,看看它是否能修复它。我是否认为不将数据包装在 IsNull 中也会产生#Num!错误? @tobriand 不,如果我只是尝试Debug.Print
rst("ActivityDate").Value
那个条目是空的,而不是 #Num!
。但是,如果我在 Excel 工作表中创建一个 Access 链接表,然后在数据表视图中打开该链接表,我确实会看到 #Num!
。
我现在尝试了IsNull
方法,结果相同。我认为#Num!与其他错误类型相比,这是一种非常挑剔的错误类型。虽然找到了解决方法!通过 DAO 触发相同的查询并关闭错误,并且它无法引入的任何数据都将替换为 Null,这正是我想要的。【参考方案2】:
#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
根据我的需要,这可以完成工作,但我不会在几天内接受作为答案,以防真的有一种优雅的方法。
【讨论】:
你正在执行的SQL语句是什么? 我添加了上述问题的精简版。 SQL 语句在 DAO 上执行良好,即使没有为 Provider 等指定更多细节。但是,我在 ADODB 上得到了可比较的结果,因此首先是这个问题!以上是关于处理#Num!将 Excel 导入 Access 时出错的主要内容,如果未能解决你的问题,请参考以下文章