简体   繁体   English

具有VBA的Excel 2010中带有VBA的Excel 2010中的查询表(QueryTables)

[英]Query Tables (QueryTables) in Excel 2010 with VBA with VBA creating many connections

I'm following code I found on another site. 我正在跟踪在另一个站点上找到的代码。 Here's the basics of my code: 这是我的代码的基础:

Dim SQL As String
Dim connString As String

connString = "ODBC;DSN=DB01;UID=;PWD=;Database=MyDatabase"
SQL = "Select * from SomeTable"

With Worksheets("Received").QueryTables.Add(Connection:=connString, Destination:=Worksheets("Received").Range("A5"), SQL:=SQL)
.Refresh

End With

End Sub

The problem with doing this is every single time they hit the button assigned to this it creates a new connection and doesn't ever seem to drop it. 这样做的问题是,每当他们单击分配给它的按钮时,都会创建一个新的连接,而且似乎从未断开过该连接。 I open the spreadsheet after testing and there are many versions of the connection listed under Connections. 我在测试后打开电子表格,并且在“连接”下列出了许多版本的连接。 Connection Connection1 Connection2 连接连接1连接2

I can't seem to find a way to close or delete the connections either. 我似乎也找不到关闭或删除连接的方法。 If I add ".delete" after ".Refresh" I get a 1004 error. 如果在“ .Refresh”之后添加“ .delete”,则会出现1004错误。 This operation cannot be done because the data is refreshing in the background. 由于数据在后台刷新,因此无法执行此操作。

Any ideas how to close or delete the connection? 任何想法如何关闭或删除连接?

You might ask yourself why you're creating a QueryTable every time in your code. 您可能会问自己,为什么每次在代码中都创建QueryTable。 There are reasons to do it, but it usually isn't necessary. 有理由这样做,但是通常没有必要。

QueryTables are more typically design-time objects. QueryTables通常是设计时对象。 That is, you create your QueryTable once (through code or the UI) and the you Refresh the QueryTable to get updated data. 也就是说,您一次创建了QueryTable(通过代码或UI),然后刷新了QueryTable以获取更新的数据。

If you need to change the underlying SQL statement, you have some options. 如果需要更改基础SQL语句,则可以选择一些方法。 You could set up Parameters that prompt for a value or get it from a cell. 您可以设置提示输入值或从单元格获取值的参数。 Another option for changing the SQL is changing it in code for the existing QueryTable. 更改SQL的另一种方法是更改​​现有QueryTable的代码。

Sheet1.QueryTables(1).CommandText = "Select * FROM ...."
Sheet1.QueryTables(1).Refresh

You can select different columns or even different tables by changing CommandText. 您可以通过更改CommandText选择不同的列甚至不同的表。 If it's a different database, you'll need a new connection, but that's pretty rare. 如果是另一个数据库,则需要一个新的连接,但这很少见。

I know that doesn't answer your question directly, but I think determining whether you really need to add the QueryTable each time is the first step. 我知道这并不能直接回答您的问题,但是我认为确定您是否真的需要每次都添加QueryTable是第一步。

For more on Parameters, see http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/ It's for 2003, so there are few inconsistencies with later versions. 有关参数的更多信息,请参见http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/适用于2003年,因此与以后的版本几乎没有不一致之处。 The basics are the same, you just may need to learn about the ListObject object if you're using 2007 or later. 基本原理是相同的,如果您使用的是2007年或更高版本,则可能只需要了解ListObject对象。

I had the same issue. 我遇到过同样的问题。 The previous answer while a definite step in the right direction is a PITA. 向正确方向迈出明确一步的先前答案是PITA。

It did however allow me to refine my search and the winner is... 但是,它的确使我可以优化搜索范围,而获胜者是...

http://msdn.microsoft.com/en-us/library/bb213491(v=office.12).aspx http://msdn.microsoft.com/zh-cn/library/bb213491(v=office.12).aspx

ie for your existing QueryTable Object just do this: 即对于您现有的QueryTable对象,只需执行以下操作:

.MaintainConnection = False

Works ever so swell. 作品如此膨胀。 No more Access DB lock file after the data is refreshed. 刷新数据后,不再有Access DB锁定文件。

I've found that by default new connections created this way are called "Connection". 我发现默认情况下以这种方式创建的新连接称为“连接”。 What I am using is this snippet of code to remove the connection but retain the listobject. 我正在使用的是这段代码以删除连接,但保留listobject。

Application.DisplayAlerts = False
ActiveWorkbook.Connections("Connection").Delete
Application.DisplayAlerts = True

It can easily be modified to remove the latest added connection (or if you keep track of the connections by their index). 可以轻松地对其进行修改,以删除最新添加的连接(或者如果您通过连接的索引跟踪连接)。

Application.DisplayAlerts = False
ActiveWorkbook.Connections(ActiveWorkbook.Connections.Count).Delete
Application.DisplayAlerts = True

Instead of adding another query table with the add method, you can simply update the CommandText Property of the connection. 不必使用add方法添加另一个查询表,只需简单地更新连接的CommandText属性。 However you have to be aware that there is a bug when updating the CommandText property of an ODBC connection. 但是,您必须知道更新ODBC连接的CommandText属性时存在错误。 If you temporarily switch to an OLEDB connection, update your CommandText property and then switch back to ODBC it does not create the new connection. 如果您暂时切换到OLEDB连接,请更新CommandText属性,然后再切换回ODBC,这不会创建新的连接。 Don't ask me why... this just works for me. 不要问我为什么...这对我有用。

Create a new module and insert the following code: 创建一个新模块并插入以下代码:

Option Explicit

Sub UpdateWorkbookConnection(WorkbookConnectionObject As WorkbookConnection, Optional ByVal CommandText As String = "", Optional ByVal ConnectionString As String = "")

With WorkbookConnectionObject
    If .Type = xlConnectionTypeODBC Then
        If CommandText = "" Then CommandText = .ODBCConnection.CommandText
        If ConnectionString = "" Then ConnectionString = .ODBCConnection.Connection
        .ODBCConnection.Connection = Replace(.ODBCConnection.Connection, "ODBC;", "OLEDB;", 1, 1, vbTextCompare)
    ElseIf .Type = xlConnectionTypeOLEDB Then
        If CommandText = "" Then CommandText = .OLEDBConnection.CommandText
        If ConnectionString = "" Then ConnectionString = .OLEDBConnection.Connection
    Else
        MsgBox "Invalid connection object sent to UpdateWorkbookConnection function!", vbCritical, "Update Error"
        Exit Sub
    End If
    If StrComp(.OLEDBConnection.CommandText, CommandText, vbTextCompare) <> 0 Then
        .OLEDBConnection.CommandText = CommandText
    End If
    If StrComp(.OLEDBConnection.Connection, ConnectionString, vbTextCompare) <> 0 Then
        .OLEDBConnection.Connection = ConnectionString
    End If
    .Refresh
End With

End Sub

This UpdateWorkbookConnection subroutine only works on updating OLEDB or ODBC connections. UpdateWorkbookConnection子例程仅适用于更新OLEDB或ODBC连接。 The connection does not necessarily have to be linked to a pivot table. 该连接不一定必须链接到数据透视表。 It also fixes another problem and allows you to update the connection even if there are multiple pivot tables based on the same connection. 它还解决了另一个问题,即使有多个基于同一连接的数据透视表,也可以更新连接。

To initiate the update just call the function with the connection object and command text parameters like this: 要启动更新,只需使用连接对象和命令文本参数调用函数,如下所示:

UpdateWorkbookConnection ActiveWorkbook.Connections("Connection"), "exec sp_MyAwesomeProcedure"

You can optionally update the connection string as well. 您也可以选择更新连接字符串。

You should declare the connection as a separate object then you can close it once the database query is complete. 您应该将连接声明为单独的对象,然后在数据库查询完成后就可以将其关闭。

I don't have the VBA IDE in front of me, so excuse me if there are any inaccuracies, but it should point you in the right direction. 我前面没有VBA IDE,因此如果有任何不正确之处,请原谅,但它应该为您指明正确的方向。

Eg 例如

Dim SQL As String
Dim con As connection

Set con = New connection
con.ConnectionString = "ODBC;DSN=DB01;UID=;PWD=;Database=MyDatabase"

Worksheets("Received").QueryTables.Add(Connection:=con, Destination:=Worksheets("Received").Range("A5"), SQL:=SQL).Refresh

con.close
set con = nothing

如果要在刷新后立即删除,则不应该在后台进行刷新(使用第一个参数->刷新为False),以便您有适当的操作顺序

Try setting the QueryTable.MaintainConnection property to False... 尝试将QueryTable.MaintainConnection属性设置为False ...

"Set MaintainConnection to True if the connection to the specified data source is to be maintained after the refresh and until the workbook is closed. The default value is True! And there doesn't seem to be a UI check box for this (Read/write Boolean)" “如果要在刷新后并在关闭工作簿之前保持与指定数据源的连接,请将MaintenanceConnection设置为True。默认值为True!而且似乎没有用于此的UI复选框(读/写布尔)”

Still relevant years later...battling the same issue and this is the most helpful thread out there. 几年后仍然有意义……与同一个问题作斗争,这是那里最有帮助的话题。 My situation is a variant of the above and I will add my solution when I find it. 我的情况是上述情况的一种,我将在找到解决方案后添加解决方案。

I am using an Access database for my data source and establish a querytable on a new sheet. 我正在使用Access数据库作为数据源,并在新表上建立一个querytable。 I then add two more new sheets and try to establish a querytable using the same connection on each of them, but to a different Access table. 然后,我再添加两个新的工作表,并尝试在每个工作表上使用相同的连接建立一个查询表,但将其连接到不同的Access表。 The first querytable works just fine and I use .QueryTables(1).Delete and setting the querytable object to Nothing to make it disconnected. 第一个查询表工作正常,我使用.QueryTables(1).Delete并将查询表对象设置为Nothing使其断开连接。

However, the next sheet fails on establishing a new querytable using the same connection, which was not closed. 但是,下一张表无法使用未关闭的相同连接建立新的查询表。 I suspect (and will add the solution below) that I need to drop the connection before deleting the querytable. 我怀疑(并将在下面添加解决方案)在删除查询表之前需要断开连接。 Rasmus' code above looks like the likely solution. 上面的Rasmus的代码似乎是可能的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM