在Excel 2010中使用VBA查询表格(QueryTables),创建多个连接。

6

我正在遵循在另一个网站上找到的代码。这是我的代码基础:

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

每次按下分配给它的按钮时,问题就出现了,它会创建一个新的连接并且似乎永远不会断开。在测试后,我打开电子表格,发现在“连接”下列出了许多版本的连接。 连接 连接1 连接2
我无法找到关闭或删除连接的方法。如果我在“刷新”后添加“.delete”,我会收到1004错误。因为数据正在后台刷新,所以无法执行此操作。
有什么想法可以关闭或删除连接吗?
8个回答

11
你可能会问自己为什么要在代码中每次创建QueryTable。虽然有些原因需要这样做,但通常并非必要。
QueryTable更常用于设计时对象。也就是说,您只需一次创建QueryTable(通过代码或UI),然后刷新QueryTable以获取更新的数据即可。
如果需要更改基础SQL语句,有几种选择。您可以设置提示值的参数或从单元格获取它。修改现有QueryTable中的代码是更改SQL的另一个选项。
Sheet1.QueryTables(1).CommandText = "Select * FROM ...."
Sheet1.QueryTables(1).Refresh

您可以通过更改CommandText选择不同的列甚至不同的表格。如果是不同的数据库,您将需要一个新的连接,但这是非常罕见的。

我知道这并没有直接回答您的问题,但我认为确定您是否真的需要每次添加QueryTable是第一步。

有关参数的更多信息,请参见http://dailydoseofexcel.com/archives/2004/12/13/parameters-in-excel-external-data-queries/。它适用于2003年,因此与后来的版本存在一些不一致之处。基础知识是相同的,只是如果您使用的是2007或更高版本,则可能需要了解ListObject对象。


7
我遇到了同样的问题。之前的答案虽然是朝着正确方向迈出的一步,但很麻烦。不过,这让我进一步细化了搜索内容,最终找到了胜利者...
即:对于您现有的QueryTable对象,只需执行以下操作:http://msdn.microsoft.com/en-us/library/bb213491(v=office.12).aspx
.MaintainConnection = False

工作非常顺利。在数据刷新后,不再出现Access数据库锁定文件。


1

不需要使用add方法添加另一个查询表,您可以直接更新连接的CommandText属性。但是,您必须知道,在更新ODBC连接的CommandText属性时存在一个错误。如果您暂时切换到OLEDB连接,并更新CommandText属性,然后再切换回ODBC,它不会创建新的连接。别问我为什么...这对我有效。

创建一个新模块并插入以下代码:

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

这个UpdateWorkbookConnection子程序只能用于更新OLEDB或ODBC连接。该连接不一定需要链接到数据透视表。它还可以解决另一个问题,并允许您在基于相同连接的多个数据透视表存在时更新连接。

要启动更新,只需使用连接对象和命令文本参数调用函数,如下所示:

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

您还可以选择更新连接字符串。


1
我发现默认情况下通过这种方式创建的新连接被称为“Connection”。我正在使用这段代码片段来删除连接但保留列表对象。
Application.DisplayAlerts = False
ActiveWorkbook.Connections("Connection").Delete
Application.DisplayAlerts = True

它可以很容易地进行修改,以删除最新添加的连接(或者如果您通过它们的索引跟踪连接)。

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

1

您应该将连接声明为单独的对象,然后在数据库查询完成后再关闭它。

我没有VBA IDE在身边,所以如果有任何不准确之处,请见谅,但这应该可以指引您朝正确的方向发展。

例如:

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

当我尝试这样做时,Worksheets("Received")...这一行会出现无效的过程调用运行时错误5。我还尝试将其从New Connection更改为New ADODB Connection并相应地使用它,但是没有成功。 - DavidStein
好的,我所做的只是重新格式化了st0000的答案,但这确实是你最初关于处理关闭连接的问题的答案。我不在Excel中工作,所以无法帮助解决其他任何问题。 - RolandTumble

0

如果您想在刷新后立即删除,请不要在后台进行刷新(使用第一个参数 -> 刷新为false),以便您有正确的操作顺序


0

多年后仍然有参考价值……与同样的问题斗争,这是目前最有帮助的线程。我的情况是上述情况的变体,当我找到解决方案时,我将添加它。

我正在使用Access数据库作为我的数据源,并在新工作表上建立查询表。然后我再添加两个新工作表,并尝试在每个工作表上使用相同的连接来建立查询表,但是针对不同的Access表格。第一个查询表完全正常工作,并且我使用.QueryTables(1)。Delete并将查询表对象设置为无来断开连接。

然而,在没有关闭连接的情况下,下一个表格在建立新的查询表时失败了。我怀疑(并将在下面添加解决方案)在删除查询表之前需要断开连接。 Rasmus的代码似乎是可能的解决方案。


0
尝试将QueryTable.MaintainConnection属性设置为False...
如果刷新后要维护到指定数据源的连接并保持工作簿打开状态,请将MaintainConnection设置为True。默认值为True!似乎没有针对此进行UI复选框(读/写布尔)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接