IMEX=0 的 Excel ADODB 查询不从第一行返回数据

Posted

技术标签:

【中文标题】IMEX=0 的 Excel ADODB 查询不从第一行返回数据【英文标题】:Excel ADODB query with IMEX=0 not returning data from the first row 【发布时间】:2018-05-01 15:02:44 【问题描述】:

我在 Excel VBA 中使用 ADODB 来查询/更新另一个(已关闭)Excel 电子表格中的命名范围。使用 ADODB 对电子表格进行 SELECT 查询很简单;但是,弄清楚 UPDATE 查询是一件很麻烦的事情。经过很多,很多......大量的研究和调整,我终于让更新工作。

但是,我发现 SELECT 查询不包括来自命名范围的第一行数据,即记录集包含 19 行,而命名范围有 20 行,记录集的第一行包含来自第二个的数据命名范围的行。命名范围没有标题行......它一直是可靠的数据。

我知道你在说什么,“哦,你需要将 HDR 属性设置为“否”。:-) 不,我试过了。见下文。

我得到的唯一额外线索是,当 IMEX 设置为 1 或 2 时,SELECT 查询将返回所有行。当 IMEX 设置为 0 时,第一行将丢失。但是,当 IMEX 设置为 1 或 2 时,记录集是只读的,因此无法更新。据我所知,使更新工作的唯一方法是将 IMEX 设置为 0。

为了简洁起见,下面的代码摘自一个更大的函数。

strSourcePath 是目标工作簿的完整路径 strSourceRange 是要更新的范围的名称 avNewValues() 是要写入

的新值的二维数组

我正在使用 32 位 Office 2016 和 64 位 Windows 10。

Dim conn As ADODB.Connection
Dim rs As ADODB.Recordset
Dim strconnect As String
Dim strSQL As String
Dim iRow As Integer, iCol As Integer

strconnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
            "Data Source=" & strSourcePath & ";" & _
            "Extended Properties=""Excel 12.0;HDR=No;IMEX=0"";"

strSQL = "SELECT * FROM " & strSourceRange & ";"

Set conn = CreateObject("adodb.connection")
conn.Open strconnect

Set rs = CreateObject("ADODB.Recordset")
rs.Open strSQL, conn, adOpenStatic, adLockOptimistic

'Update the values in the recordset
rs.MoveFirst
For iRow = 1 To UBound(avNewValues, 1)
    For iCol = 1 To UBound(avNewValues, 2)
        rs.Fields(iCol - 1).Value = avNewValues(iRow, iCol)
    Next
    rs.MoveNext
Next
rs.Update

【问题讨论】:

忘了说,我也试过 IMEX=0 和 FirstRowHasNames=FALSE;这仍然跳过第一行。我厌倦了 IMEX=1 和 ReadOnly=FALSE;这仍然返回一个只读的记录集(至少错误消息说它是只读的。) 您是否要更新 Excel 工作表?暂时忘记第一行的问题。更新永远不会起作用,此功能存在限制。你走错了路,我建议在临时工作表上 CopyFromRecordset,进行必要的修改,等等......等等...... 抱歉,我误解了,UPDATE 可能适用于另一个 Excel 工作簿,但不在同一个工作簿中。请忽略我上面的评论。 谢谢,@M.R.实际上,它确实有效。无需打开目标工作簿,它的速度非常快。使用 CopyFromRecordset 需要打开(大)目标工作簿......这意味着与 ADODB SQL 查询相比,内存消耗和 CPU 周期要多得多。此外,在我看来,使用 SQL 处理逻辑的能力(而不是构建 VBA 来确定应该更新哪一行/列)是一个很大的价值......巨大!唯一的问题是我还没有弄清楚如何让 SELECT 查询完全正确。 哎呀...@M.R....我们同时发布。 :-) 是的,目标在不同的工作簿中。 【参考方案1】:

请为 XLSX 文件尝试以下连接字符串(注意下面字符串中的关键字 Xml):

 strconnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=" & strSourcePath & ";" & _
        "Extended Properties=""Excel 12.0 Xml;HDR=No;IMEX=0"";"

或者这个用于 XLSM 文件(注意下面字符串中的关键字 Macro):

 strconnect = "Provider=Microsoft.ACE.OLEDB.12.0;" & _
        "Data Source=" & strSourcePath & ";" & _
        "Extended Properties=""Excel 12.0 Macro;HDR=No;IMEX=0"";"

另外,请尝试设置 IMEX=1。我有一个类似的问题,这个参数组合解决了它。

【讨论】:

谢谢,@M.R.好的建议。我刚刚尝试了这些,但都产生了与以前相同的结果,即记录集可以更新,但第一行数据丢失。当我更改为 IMEX=1 时,第一行数据又回来了,但记录集是只读的。 IMEX=2 有什么不同吗? 很遗憾,不,@M.R. IMEX=2 的行为与 IMEX=1 相同,即我得到了第一行数据但记录集处于只读状态。 获取这个...如果您根本不指定 IMEX 属性,那么它可以工作,即返回所有行并且记录集是读/写的。去搞清楚。在我意识到这一点之前,我已经决定只适应不良行为并向数据范围添加标题行。但现在我将跳过 IMEX 属性。这无疑会带来一些数据类型不匹配的风险,但对于当前项目来说风险很低。【参考方案2】:

这是我发现的。如果您根本不指定 IMEX 属性,那么它可以工作,即返回所有行并且记录集是读/写的。这很令人困惑,因为我能找到的所有文档都说连接对象假定默认 IMEX 值为零。如果这是真的,那么显式指定默认值会改变连接对象的行为。

在我发现这一点之前,我决定只适应不良行为并向数据范围添加标题行。但现在我将完全跳过 IMEX 属性,除了默认值。这无疑会带来一些数据类型不匹配的风险,但对于当前项目来说风险很低。

【讨论】:

以上是关于IMEX=0 的 Excel ADODB 查询不从第一行返回数据的主要内容,如果未能解决你的问题,请参考以下文章

关于Excel导入的HDR=YES; IMEX=1详解

ACE.OLEDB 链接字符串:关于Excel导入的HDR=YES; IMEX=1

2021 年的 Excel ADODB 查询日期

关于OleDB连接Excel的Extended Properties(扩展属性)HDR=YES; IMEX=2个人理解心得

ADODB对象忽略excel中的文本

无法从 excel 列中读取字符串值