【问题标题】:How do I reference tables in Excel using VBA?如何使用 VBA 在 Excel 中引用表格?
【发布时间】:2013-08-04 12:50:57
【问题描述】:

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

假设这可能是...

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

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

【问题讨论】:

    标签: excel vba listobject excel-tables


    【解决方案1】:

    如this answer 中所述将范围转换为表格:

    Sub CreateTable()
        ActiveSheet.ListObjects.Add(xlSrcRange, Range("$B$1:$D$16"), , xlYes).Name = _
            "Table1"
            'No go in 2003
        ActiveSheet.ListObjects("Table1").TableStyle = "TableStyleLight2"
    End Sub
    

    【讨论】:

      【解决方案2】:

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

      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
      

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

      【讨论】:

        【解决方案3】:

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

        Dim LO As ListObject
        Set LO = ActiveSheet.ListObjects("YourListObjectName")
        

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

        我找到了您的问题,因为我想在一个工作表上引用另一个工作表上的数据透视表所引用的列表对象(表)。由于列表对象是 Worksheets 集合的一部分,因此您必须知道列表对象所在的工作表的名称才能引用它。因此,为了获取列表对象所在的工作表的名称,我获取了数据透视表的源列表对象(再次是表)的名称,并遍历工作表及其列表对象,直到找到包含列表的工作表我正在寻找的对象。

        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
        

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

        【讨论】:

        • 鉴于@AndrewD 写的关于 application.range 方法潜在缺点的内容,这似乎是仅使用表名获取表的 ListObject 的唯一可靠方法。
        • 除了在您的代码中创建 PivotTable(这可能不是您的意图)之外,我认为您的方式尽可能直接.我试图添加一个通用函数来获得一个 ListObject 给你的答案一个 PivotTable 名称,但显然这不是犹太洁食。所以我决定创建一个新的question 并提供该代码作为答案。但我确实在这里赞成你的回答,因为这是可以预见的需要能够从 PivotTable 名称中获取 ListObject。
        【解决方案4】:

        OP 询问,是否可以引用表格,而不是如何添加表格。所以

        的工作等价物
        Sheets("Sheet1").Table("A_Table").Select
        

        应该是这样的陈述:

        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
        

        对于这些部分,您可能需要在选择它们之前测试标题和总计行是否存在。

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

        【讨论】:

        • 我们如何在 VBA 查询中使用表格,就像我们对表格所做的那样,例如“select * from [sheet1$] where col1='x'”
        • @Vikky 我不熟悉您引用的 VBA 查询,但对它很感兴趣。您是否有此类查询的文档链接(MSDN 或其他)?通过 OLE 或 ODBC 从另一个应用程序或工具引用 Excel 时是否使用此功能?如果是,是哪个应用程序?
        • 首先感谢您的回复。我已经为我的问题找到了解决方案,可以使用 oledb 使用 excel 表中的表格。这是对我有帮助的文章链接chandoo.org/wp/2012/04/02/using-excel-as-your-database
        • “Excel 中的表格非常有意义,但在 VBA 中却很难使用!” 告诉我吧!为什么它们不能像数据库表一样被查询?
        • @Vikky,关于如何使用 Excel for OLE DB 的链接确实很有趣,但请注意,它与此处讨论的表的概念无关,因此说“表”是不正确的在 excel 表中可以使用 oledb”。 (来自您的链接:“在我们开始之前:... 2. 这与 Excel 的内置表格(2007 及更高版本)/列表(2003 及更早版本)功能无关。”)
        【解决方案5】:

        Excel 中的“表”确实称为 ListObject。

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

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

        注意: 此 hack 依赖于 Excel 始终为表的 DataBodyRange 创建与表同名的命名范围这一事实。然而,这个范围名称​​可以改变......虽然这不是你想要做的事情,因为如果你编辑表名,名称将重置!你也可以得到一个没有关联 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 信息here。

        【讨论】:

        • BTW 不要指望在Application.Names 中找到表DataBodyRange 范围名称!但绝对可以使用Application.Range(...) 访问它们。
        • 这种方式似乎只有在包含所需表的工作簿当前处于活动状态时才有效。如果您以某种方式在另一个文件处于活动状态的情况下运行代码,则此方法将失败。与ActiveSheet 对象的方法相同。
        • 不是您建议的 VBA 的忠实拥护者,但您删除的外部链接很好地总结了如何引用表格和表格的一部分,谢谢。
        • 支持 hack 和 NOTE。事实上,我在刚刚发布的一个新问题中添加了一个参考:stackoverflow.com/q/46058096/5457466@AndrewD 也许你可以帮忙?
        • 您对范围以某种方式从表名中重命名的不满意警告,这不仅适用于表,而且适用于所有命名范围......它似乎能够处理用户无意中重命名工作表...或重新设计,将各种名称单元重新映射到不同的工作表...当一个函数与多个工作表上的事物交互时[或者即使它们最初都在 ActiveSheet 上,但可能不会在以后],不需要VB 编辑。似乎灵活性(也许在我对 VBA 的非专业知识中,我不明白如何处理此类更改?),似乎至关重要
        【解决方案6】:

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

        1. SheetObject.ListObjects("TableName")
        2. Application.Range("TableName").ListObject
        3. [TableName].ListObject

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-12-20
          • 1970-01-01
          • 2010-09-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多