如何使用VBA在Excel中引用表格?

如何使用VBA在Excel中引用表格?,excel,vba,listobject,excel-tables,Excel,Vba,Listobject,Excel Tables,在Excel VBA中是否可以引用命名表 假设这可能是 Sheets("Sheet1").Table("A_Table").Select 我看到一些人提到表是列表对象,但我不确定这是否是同一回事。将范围转换为表,如中所述: 此外,定义引用对象的变量也很方便。比如说, Sub CreateTable() Dim lo as ListObject Set lo = ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$1:$D$16")

在Excel VBA中是否可以引用命名表

假设这可能是

Sheets("Sheet1").Table("A_Table").Select

我看到一些人提到表是列表对象,但我不确定这是否是同一回事。

将范围转换为表,如中所述:


此外,定义引用对象的变量也很方便。比如说,

Sub CreateTable()
    Dim lo as ListObject
    Set lo = ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$1:$D$16"), , xlYes)
    lo.Name = "Table1"
    lo.TableStyle = "TableStyleLight2"
    ...
End Sub

您可能会立即发现它很有优势。

除上述内容外,您还可以这样做(其中“YourListObjectName”是表的名称):

但我认为,只有当您想要引用活动工作表上的列表对象时,这种方法才有效

我找到您的问题是因为我想引用一个工作表上的列表对象(表),而另一个工作表上的透视表引用了该对象。由于列表对象是工作表集合的一部分,因此必须知道列表对象所在的工作表的名称才能引用它。因此,为了获取列表对象所在的工作表的名称,我获取了透视表的源列表对象(同样是一个表)的名称,并在工作表及其列表对象之间循环,直到找到包含我要查找的列表对象的工作表

Public Sub GetListObjectWorksheet()
' Get the name of the worksheet that contains the data
' that is the pivot table's source data.

    Dim WB As Workbook
    Set WB = ActiveWorkbook

    ' Create a PivotTable object and set it to be
    ' the pivot table in the active cell:
    Dim PT As PivotTable
    Set PT = ActiveCell.PivotTable

    Dim LO As ListObject
    Dim LOWS As Worksheet

    ' Loop through the worksheets and each worksheet's list objects
    ' to find the name of the worksheet that contains the list object
    ' that the pivot table uses as its source data:
    Dim WS As Worksheet
    For Each WS In WB.Worksheets
        ' Loop through the ListObjects in each workshet:
        For Each LO In WS.ListObjects
            ' If the ListObject's name is the name of the pivot table's soure data,
            ' set the LOWS to be the worksheet that contains the list object:
            If LO.Name = PT.SourceData Then
                Set LOWS = WB.Worksheets(LO.Parent.Name)
            End If
        Next LO
    Next WS

    Debug.Print LOWS.Name

End Sub

也许有人知道一个更直接的方法。

OP问,是否可以引用一个表,而不是如何添加一个表。因此,工作等效于

Sheets("Sheet1").Table("A_Table").Select
请允许我这样说:

Sheets("Sheet1").ListObjects("A_Table").Range.Select
或选择零件(仅与表中的数据类似):

对于零件,在选择它们之前,您可能需要测试是否存在标题行和总计行

说真的,这是在VBA中引用表的唯一问题?Excel中的表格非常有意义,但在VBA中使用它们太难了

Excel中的“表”实际上被称为ListObject

引用表格的“正确”方法是从工作表中获取其ListObject,即
SheetObject.ListObjects(ListObjectName)

如果要在不使用工作表的情况下引用表,可以使用hack
Application.Range(ListObjectName).ListObject

注意:这种攻击依赖于这样一个事实:Excel总是为表的DataCodeRange创建一个与表同名的命名范围。但是,此范围名称可以更改…尽管这不是您希望执行的操作,因为如果您编辑表名,名称将重置!您还可以获得一个没有关联ListObject的命名范围

如果Excel的1004错误消息对您的名字不太有帮助,您可能需要创建一个包装器

Public Function GetListObject(ByVal ListObjectName As String, Optional ParentWorksheet As Worksheet = Nothing) As Excel.ListObject
On Error Resume Next

    If (Not ParentWorksheet Is Nothing) Then
        Set GetListObject = ParentWorksheet.ListObjects(ListObjectName)
    Else
        Set GetListObject = Application.Range(ListObjectName).ListObject
    End If

On Error GoTo 0 'Or your error handler

    If (Not GetListObject Is Nothing) Then
        'Success
    ElseIf (Not ParentWorksheet Is Nothing) Then
        Call Err.Raise(1004, ThisWorkBook.Name, "ListObject '" & ListObjectName & "' not found on sheet '" & ParentWorksheet.Name & "'!")
    Else
        Call Err.Raise(1004, ThisWorkBook.Name, "ListObject '" & ListObjectName & "' not found!")
    End If

End Function
还有一些很好的ListObject信息。

添加第三个选项。 @AndrewD第二个选项的“速记”版本

  • SheetObject.ListObjects(“TableName”)
  • Application.Range(“TableName”).ListObject
  • [TableName].ListObject

  • 是的,括号引用中没有引号。

    顺便说一句,不要期望在
    应用程序中找到表DataBodyRange范围名称。名称
    !但它们肯定可以使用
    Application.Range(…)
    访问。这种方法似乎只有在包含所需表的工作簿当前处于活动状态时才有效。如果在另一个文件处于活动状态的情况下运行代码,此方法将失败。。与
    ActiveSheet
    对象的方法相同。不太喜欢您建议的VBA,但您删除的外部链接是关于如何引用表和表的一部分的一个很好的总结,谢谢。支持hack and NOTE。事实上,我在刚刚发布的一个新问题中添加了一个参考:也许你可以帮忙,@AndrewD?你不高兴地警告说,该范围以某种方式从表名重命名,这不仅适用于表,而且适用于所有命名的范围。。。它似乎能够处理用户无意中重命名工作表。。。或者重新设计,将不同的名称单元格重新映射到不同的图纸。。。当一个函数与多个工作表上的内容交互时(或者即使它们最初都在ActiveSheet上,但可能不在以后),无需VB编辑。这似乎是一种灵活性(也许在我不熟悉VBA的情况下,我不知道如何处理这样的更改?),似乎是至关重要的。我们如何在VBA查询中使用表,就像我们在工作表中所做的那样,例如“select*from[sheet1$]where col1='x'”@Vikky我不熟悉您引用的VBA查询,但对此很感兴趣。您是否有此类查询的文档链接(MSDN或其他)?当通过OLE或ODBC从其他应用程序或工具引用Excel时是否使用此选项?如果是的话,是哪一份申请?首先我想感谢你的回复。我已经找到了问题的解决方案,excel表格中的表格可以使用oledb。这是文章的链接,它帮助我“Excel中的表非常有意义,但在VBA中它们很难使用!”告诉我吧!为什么不能像查询数据库表一样查询它们?@Vikky,关于如何使用Excel for OLE DB的链接确实很有趣,但请注意,它与此处讨论的表概念无关,因此说“Excel工作表中的表可以在oledb中使用”是不正确的。(来自您的链接:“在我们开始之前:……2.这与Excel的内置表(2007年及更高版本)/列表(2003年及以前版本)功能无关。”)鉴于@AndrewD对application.range方法的潜在缺陷所作的描述,这似乎是仅使用表名获取表的ListObject的唯一可靠方法。除了在代码中创建数据透视表(这可能不是您的意图),我认为您的方法尽可能直接。我试图添加一个泛型函数,让ListObject为您的答案指定一个数据透视表名称,但显然这并不符合犹太教义。所以我决定创建一个新的代码,并提供该代码作为答案。但我在这里投票支持你的答案,因为这是一个可以预见的需要,需要能够从数据透视表名称中获取ListObject。
    Sheets("Sheet1").ListObjects("A_Table").Range.Select
    
    Dim LO As ListObject
    Set LO = Sheets("Sheet1").ListObjects("A_Table")
    LO.HeaderRowRange.Select        ' Select just header row
    LO.DataBodyRange.Select         ' Select just data cells
    LO.TotalsRowRange.Select        ' Select just totals row
    
    Public Function GetListObject(ByVal ListObjectName As String, Optional ParentWorksheet As Worksheet = Nothing) As Excel.ListObject
    On Error Resume Next
    
        If (Not ParentWorksheet Is Nothing) Then
            Set GetListObject = ParentWorksheet.ListObjects(ListObjectName)
        Else
            Set GetListObject = Application.Range(ListObjectName).ListObject
        End If
    
    On Error GoTo 0 'Or your error handler
    
        If (Not GetListObject Is Nothing) Then
            'Success
        ElseIf (Not ParentWorksheet Is Nothing) Then
            Call Err.Raise(1004, ThisWorkBook.Name, "ListObject '" & ListObjectName & "' not found on sheet '" & ParentWorksheet.Name & "'!")
        Else
            Call Err.Raise(1004, ThisWorkBook.Name, "ListObject '" & ListObjectName & "' not found!")
        End If
    
    End Function