13

我正在使用 VBA 开发一个 MS Excel 2013 工具,其中涉及到 QueryTables 的使用。

一个不便之处是在 Excel 工作表中访问现有的QueryTable。目前,我能找到访问查询表的唯一方法是通过整数索引。我想出了以下代码来快速验证概念:

Sub RefreshDataQuery()

Dim querySheet As Worksheet
Dim interface As Worksheet

Set querySheet = Worksheets("QTable")
Set interface = Worksheets("Interface")

Dim sh As Worksheet
Dim QT As QueryTable

Dim startTime As Double
Dim endTime As Double

Set QT = querySheet.ListObjects.item(1).QueryTable

startTime = Timer
QT.Refresh
endTime = Timer - startTime

interface.Cells(1, 1).Value = "Elapsed time to run query"
interface.Cells(1, 2).Value = endTime
interface.Cells(1, 3).Value = "Seconds"

End Sub

这行得通,但我不想这样做。最终产品工具将有多达五个不同的查询表。我想通过名称来引用 QueryTable。

我怎么翻译:

Set QT = querySheet.ListObjects.item(1).QueryTable

类似于以下内容:

Set QT = querySheet.ListObjects.items.QueryTable("My Query Table")
4

3 回答 3

10

在 Excel 2003 和更早版本中,外部数据连接会创建一个父对象是工作表的 QueryTable 对象。您可以通过 QueryTables 集合对象访问 QueryTable 对象。像大多数集合对象一样,您可以将索引号或名称传递给(默认)Item 方法来获取它。

Sheet1.QueryTables("MyQtName")

当您在新版本中打开 2003 工作表时,它仍然有一个 QueryTable 对象,并且可以以相同的方式访问。即使您转换文件格式,QueryTable 仍然存在。

在 2007 及更高版本中,只有三种方法可以创建将成为 Worksheet.QueryTables 成员的 QueryTable:

  1. 通过代码
  2. 数据 - 来自文本
  3. 数据 - 来自网络

这些新版本中的所有其他 UI 外部数据连接都不会生成 QueryTables 成员,而是生成 ListObject。该 ListObject 将只有一个 QueryTable 对象,可以通过 ListObject.QueryTable 属性访问。

这是坏消息。ListObject 中其父级没有 Name 属性的 QueryTable。好吧,它就在那里,但是如果您尝试访问它,您将收到运行时错误 1004。我猜MS决定了,因为每个ListObject只有一个QueryTable,所以它应该有一个名字是没有意义的。

如果您尝试将 Worksheet.QueryTables.QueryTable 转换为 ListObject,外部数据连接就会消失,并且新的 ListObject 没有 QueryTable。

由于您的 QueryTables.Count 返回零,因此您的所有 QueryTables 都在 ListObjects 内并且没有名称。ListObjects 有名字。您可以使用

Sheet1.ListObjects("MyListName").QueryTable

这是一个函数,它接受一个名称和一个工作表,并返回一个具有该名称或者是具有该名称的 ListObject 的子对象的 QueryTable。

Public Function QueryTableByName(ByVal sName As String, ByRef sh As Worksheet) As QueryTable

    Dim qt As QueryTable
    Dim lo As ListObject

    On Error Resume Next
        Set qt = sh.QueryTables(sName)
    On Error GoTo 0

    If qt Is Nothing Then
        On Error Resume Next
            Set lo = sh.ListObjects(sName)
        On Error GoTo 0

        If Not lo Is Nothing Then
            On Error Resume Next
                Set qt = lo.QueryTable
            On Error GoTo 0
        End If
    End If

    Set QueryTableByName = qt

End Function
于 2013-08-05T22:47:54.920 回答
6

根据ListObject 的这个 MSDN 链接,没有任何集合QueryTablesListObjects. 正确的代码是:

Set QT = querySheet.ListObjects.items(1).QueryTable

您可能需要参考适当ListObject item的内容(仅示例代码):

Dim LS as ListObject
Set LS = querySheet.ListObjects("My LO 1")
Set QT = LS.QueryTable

另一种选择是通过WorkSheet property这种方式引用 QT:

Set QT = Worksheet("QTable").QueryTables("My Query Table")
于 2013-08-05T20:41:53.240 回答
1

这有效:

Range("ClassifiedAsSupply").ListObject.QueryTable.Refresh BackgroundQuery:=True

感谢 Dingbatdata:https ://www.dingbatdata.com/2017/11/24/referencing-listobjects-with-vba/#comment-719

于 2021-08-24T20:09:52.643 回答