Excel 按名称引用查询表对象

Excel 按名称引用查询表对象,excel,vba,Excel,Vba,我正在用VBA开发一个MS Excel 2013工具,它涉及到查询表的使用 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 startTi

我正在用VBA开发一个MS Excel 2013工具,它涉及到查询表的使用

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
一个不便之处是访问Excel工作表中的现有查询表。目前,我能找到的唯一访问查询表的方法是通过整数索引。为了快速验证概念,我提出了以下代码:

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
这是可行的,但我不想这样做。最终产品工具最多有五个不同的查询表。我想按名称引用查询表

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
我如何翻译:

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
Set QT = querySheet.ListObjects.item(1).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
Set QT = querySheet.ListObjects.items.QueryTable("My Query Table")
根据,没有任何
QueryTables
的集合是
ListObjects
的属性。正确的代码是:

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
Set QT = querySheet.ListObjects.items(1).QueryTable
您可能需要参考适当的
ListObject项
like(只是示例代码):

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
另一种选择是通过以下方式通过工作表属性引用QT:

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
Set QT = Worksheet("QTable").QueryTables("My Query Table")

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

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
Sheet1.QueryTables("MyQtName")
在新版本中打开2003工作表时,它仍然有一个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
在2007年及更高版本中,只有三种方法可以创建将成为Worksheet.QueryTables成员的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
  • 通过代码
  • 数据-来自文本
  • 数据-来自Web
  • 这些新版本中的所有其他UI外部数据连接将不会生成QueryTables成员,而是生成ListObject。该ListObject将只有一个可通过ListObject.QueryTable属性访问的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
    
    这是坏消息。ListObject中其父级没有Name属性的QueryTable。好的,它就在那里,但是如果你试图访问它,你会得到一个运行时错误1004。我猜MS决定了,因为每个ListObject只有一个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
    
    如果尝试将工作表.QueryTables.QueryTable转换为ListObject,则外部数据连接将消失,并且新ListObject没有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
    
    由于您的QueryTables.Count返回零,因此您的所有QueryTables都在ListObjects中,并且没有名称。ListObjects具有名称。你可以用

    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
    
    Sheet1.ListObjects("MyListName").QueryTable
    
    下面是一个函数,它接受一个名称和一个工作表,并返回一个具有该名称或是具有该名称的ListObject的子级的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
    
    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
    

    Set QT=querySheet.ListObjects.items.QueryTable未编译。我没有看到ListObjects的items属性。对于您的第二个建议,设置QT=Worksheet(“QTable”).QueryTables(“我的查询表”),这对我不起作用,因为QTable是预先存在的。我将其更改为:
    Set QT=querySheet.ListObjects.items(1)。QueryTable
    ,它与您的代码类似。您认为“工作表是预先存在的”是什么意思。。。这很明显-将QT的名称更改为您真正拥有的名称。您始终可以通过以下方式检查工作表中QT的数量:
    Debug.Print Worksheets(“QTable”).QueryTables.Count
    以及每个QT的名称:
    ly have。您始终可以通过以下方式检查工作表中的QT编号:
    Debug.Print Worksheets(“QTable”).QueryTables(1).Name`为第一个。如果不清楚,请道歉。查询表不是通过VBA生成的。它是由不同的用户通过数据连接向导构建的。您发布的代码(我之前尝试过)的计数将显示为0,即使我可以通过ListObjects.item(1)访问QueryTable。因此,我猜ListObject数据来自外部源。因此,要访问QT,您需要找到合适的ListObject并使用
    ListObject.QueryTable
    reference。非常好的摘要和功能!这是非常有帮助和描述性的。谢谢@Dick Kusleika遗憾的是,ListObjects在2013年似乎不再具有name属性或QueryTable属性。ListObjects是一个集合对象,在工作表上保存所有ListObject对象。ListObject是一个包含单个实例的对象。集合对象从来没有名称或QueryTable属性,但ListObject仍然有。至少根据MSDN的说法。@DickKusleika我没有看到属于工作表的ListObject对象。他们可能已经处理掉了。