用于查询 Excel 的多个打开命令 oledb 连接

Posted

技术标签:

【中文标题】用于查询 Excel 的多个打开命令 oledb 连接【英文标题】:Multiple open commands oledb connections for querying Excel 【发布时间】:2015-09-08 17:18:00 【问题描述】:
Private Function CreateConnString(ByVal Str As String) As String
    Return "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & Str & ";Extended Properties=""Excel 12.0;HDR=Yes;IMEX=1"""
End Function
...
For Each sMatl_Num As String In alMaterialNumbers
                ifileNo = 1
                dbConnection.ConnectionString = CreateConnString(sExcelDBPath)
                dbCommand.Connection = dbConnection
                dbCommand.CommandText = "SELECT [col1], [col2], [col3], [col4], [col5], [col6] FROM [sheet$] WHERE [material]='" & sMatl_Num & "'" & " AND [col3] IS NOT NULL" & " AND [col6] IS NOT NULL"
                dbConnection.Open()
                dbReader = dbCommand.ExecuteReader()
                If dbReader.HasRows Then
                    Do While dbReader.Read
                        sCol1= dbReader.GetString(0).ToString
                        sCol2= dbReader.GetString(1).ToString
                        sCol3= dbReader.GetString(2).ToString
                        sCol4= dbReader.GetString(3).ToString
                        sCol5= dbReader.GetString(4).ToString
                        sCol6= dbReader.GetString(5).ToString
                     'Write txt file with name and content derived from these strings
                     Loop
                End If
                dbReader.Close()
                dbConnection.Close()
Next

我正在使用 oledb 查询一个 Excel 文件。有很多列可以从每一行获取数据。这运行速度非常慢。有没有办法可以优化这个?数组列表的计数约为 23k。

【问题讨论】:

可以一次将整个文件读入数据表,然后应用过滤器一次处理其中的一部分。我不确定它会更快,但它会减少数据库操作 您不需要在GetString 之上的ToString。我怀疑这会让它更快:它只是冗余代码。 【参考方案1】:

尝试只打开一次连接,然后处理它作为记录集返回的行,然后关闭它。

因此,您可以更改 SQL 以按 sMatl_Num 对行进行排序,并使用 where 子句仅选择 alMaterialNumbers 中的 MaterialNumbers(这可能是 IN 子句或子查询 - 这取决于可能有​​多少值)

因此,有了一个记录集,您可以循环遍历它,为每个 MaterialNumbers 写出行,当数字更改时写出到下一个文件...

这有意义吗?

【讨论】:

将数据库的读取与文件的写入分开绝对是有意义的(内存允许,但只有 23k 条记录似乎不会成为问题)。它是否真的会更快是另一回事,但我认为您已经涵盖了仅使用一个查询来获取所有必需数据的想法。 是的,谢谢!使用这样的解决方案后,这个块在大约 9 分钟内运行。与几天相反,我会说这是一个相当大的优化。再次感谢! 很高兴知道。请勾选我的答案并向上箭头!【参考方案2】:

问题在于,对于每个sMatl_Num(我假设有 23k?),您都在打开一个 OLEDB 连接,读取一条记录,然后一个接一个地抓取字段,写入它们,然后关闭连接。打开和关闭连接,在过滤其他字段的同时查询单个物料编号,从返回的字段中提取数据是昂贵的。

如果您一次带入整个记录集(复制和粘贴),使用自动过滤器或其他东西过滤掉col3=null and col6=null,然后使用本机vlookup 功能拉入Col1 - @987654325,这可能会更快@ 值。它仍然可以在 VBA 中完成。

您使用的方法更适合单次快速查找大文件。就像您在 Excel 中有一个 UI,用户将在其中输入物料编号,然后您将 OLEDB 转移到您的物料主数据并获取您想要的属性并将它们返回到 UI。一次。

【讨论】:

以上是关于用于查询 Excel 的多个打开命令 oledb 连接的主要内容,如果未能解决你的问题,请参考以下文章

使用oledb读写excel出现“操作必须使用一个可更新的查询”的解决办法

SQL查询的数据插入到Excel 2007版

用于 excel 2013 的 OLEDB 连接字符串

在 Excel 上执行多个更新命令

SQL Server 如何安装 OLEDB 驱动

从VBA中的excel中选择多列