VBA Tables and ListObjects

Tables are one of the most powerful features of Excel.  Controlling them using VBA provides a way to automate that power, which generates a double benefit 🙂

Excel likes to store data within tables.  The basic structural rules, such as (a) headings must be unique (b) only one header row allowed, make tables compatible with more complex tools.  For example, Power Query, Power Pivot, and SharePoint lists all use tables as either a source or an output.  Therefore, it is clearly Microsoft’s intention that we use tables.

However, the biggest benefit to the everyday Excel user is much simpler; if we add new data to the bottom of a table, any formulas referencing the table will automatically expand to include the new data.

Whether you love tables as much as I do or not, this post will help you automate them with VBA.

Tables, as we know them today, first appeared in Excel 2007.  This was a replacement for the Lists functionality found in Excel 2003.  From a VBA perspective, the document object model (DOM) did not change with the upgraded functionality.  So, while we use the term ‘tables’ in Excel, they are still referred to as ListObjects within VBA.

Table of Contents

Download the example file: Join the free Insiders Program and gain access to the example file used for this post.

File name: 0009 VBA Tables and ListObjects.zip

Structure of a table

Before we get deep into any VBA code, it’s useful to understand how tables are structured.

Range & Data Body Range

The range is the whole area of the table.

VBA tables - range

The data body range only includes the rows of data, it excludes the header and totals.

VBA tables - data body range

Header and total rows

The header row range is the top row of the table containing the column headers.

VBA tables - header row range

The totals row range, if displayed, includes calculations at the bottom of the table.

VBA tables - totals row range

List columns and list rows

The individual columns are known as list columns.

VBA tables - list columns

Each row is known as a list row.

VBA tables - list rows

The VBA code in this post details how to manage all these table objects.

Referencing the parts of a table

While you may be tempted to skip this section, I recommend you read it in full and work through the examples.  Understanding Excel’s document object model is the key to reading and writing VBA code.  Master this, and your ability to write your own VBA code will be much higher.

Many of the examples in this first section use the select method, this is to illustrate how to reference parts of the table.  In reality, you would rarely use the select method.

Select the entire table

The following macro will select the whole table, including the totals and header rows.

Sub SelectTable()

ActiveSheet.ListObjects("myTable").Range.Select

End Sub

Select the data within a table

The DataBodyRange excludes the header and totals sections of the table.

Sub SelectTableData()

ActiveSheet.ListObjects("myTable").DataBodyRange.Select

End Sub

Get a value from an individual cell within a table

The following macro retrieves the table value from row 2, column 4, and displays it in a message box.

Sub GetValueFromTable()

MsgBox ActiveSheet.ListObjects("myTable").DataBodyRange(2, 4).value

End Sub

Select an entire column

The macro below shows how to select a column by its position, or by its name.

Sub SelectAnEntireColumn()

'Select column based on position
ActiveSheet.ListObjects("myTable").ListColumns(2).Range.Select

'Select column based on name
ActiveSheet.ListObjects("myTable").ListColumns("Category").Range.Select

End Sub

Select a column (data only)

This is similar to the macro above, but it uses the DataBodyRange to only select the data; it excludes the headers and totals.

Sub SelectColumnData()

'Select column data based on position
ActiveSheet.ListObjects("myTable").ListColumns(4).DataBodyRange.Select

'Select column data based on name
ActiveSheet.ListObjects("myTable").ListColumns("Category").DataBodyRange.Select

End Sub

Select a specific column header

This macro shows how to select the column header cell of the 5th column.

Sub SelectCellInHeader()

ActiveSheet.ListObjects("myTable").HeaderRowRange(5).Select

End Sub

Select a specific column within the totals section

This example demonstrates how to select the cell in the totals row of the 3rd column.

Sub SelectCellInTotal()

ActiveSheet.ListObjects("myTable").TotalsRowRange(3).Select

End Sub

Select an entire row of data

The macro below selects the 3rd row of data from the table.
NOTE – The header row is not included as a ListRow.  Therefore, ListRows(3) is the 3rd row within the DataBodyRange, and not the 3rd row from the top of the table.

Sub SelectRowOfData()

ActiveSheet.ListObjects("myTable").ListRows(3).Range.Select

End Sub

Select the header row

The following macro selects the header section of the table.

Sub SelectHeaderSection()

ActiveSheet.ListObjects("myTable").HeaderRowRange.Select

End Sub

Select the totals row

To select the totals row of the table, use the following code.

Sub SelectTotalsSection()

ActiveSheet.ListObjects("myTable").TotalsRowRange.Select

End Sub

OK, now we know how to reference the parts of a table, it’s time to get into some more interesting examples.

Creating and converting tables

This section of macros focuses on creating and resizing tables.

Convert selection to a table

The macro below creates a table based on the currently selected region and names it as myTable.  The range is referenced as Selection.CurrentRegion, but this can be substituted for any range object.

If you’re working along with the example file, this macro will trigger an error, as a table called myTable already exists in the workbook.  A new table will still be created with a default name, but the VBA code will error at the renaming step.

Sub ConvertRangeToTable()

tableName As String
Dim tableRange As Range

Set tableName = "myTable"
Set tableRange = Selection.CurrentRegion
ActiveSheet.ListObjects.Add(SourceType:=xlSrcRange, _
    Source:=tableRange, _
    xlListObjectHasHeaders:=xlYes _
    ).Name = tableName

End Sub

Convert a table back to a range

This macro will convert a table back to a standard range.

Sub ConvertTableToRange()

ActiveSheet.ListObjects("myTable").Unlist

End Sub

NOTE – Unfortunately, when converting a table to a standard range, the table formatting is not removed.  Therefore, the cells may still look like a table, even when they are not – that’s frustrating!!!

Resize the range of the table

To following macro resizes a table to cell A1 – J100.

Sub ResizeTableRange()

ActiveSheet.ListObjects("myTable").Resize Range("$A$1:$J$100")

End Sub

Table styles

There are many table formatting options, the most common of which are shown below.

Change the table style

Change the style of a table to an existing pre-defined style.

Sub ChangeTableStyle()

ActiveSheet.ListObjects("myTable").TableStyle = "TableStyleLight15"

End Sub

To apply different table styles, the easiest method is to use the macro recorder.  The recorded VBA code will include the name of any styles you select.

Get the table style name

Use the following macro to get the name of the style already applied to a table.

Sub GetTableStyleName()

MsgBox ActiveSheet.ListObjects("myTable").TableStyle

End Sub

Apply a style to the first or last column

The first and last columns of a table can be formatted differently using the following macros.

Sub ColumnStyles()

'Apply special style to first column
ActiveSheet.ListObjects("myTable").ShowTableStyleFirstColumn = True

'Apply special style to last column
ActiveSheet.ListObjects("myTable").ShowTableStyleLastColumn = True

End Sub

Adding or removing stripes

By default, tables have banded rows, but there are other options for this, such as removing row banding or adding column banding.

Sub ChangeStripes()

'Apply column stripes
ActiveSheet.ListObjects("myTable").ShowTableStyleColumnStripes = True

'Remove row stripes
ActiveSheet.ListObjects("myTable").ShowTableStyleRowStripes = False

End Sub

Set the default table style

The following macro sets the default table style.

Sub SetDefaultTableStyle()

'Set default table style
ActiveWorkbook.DefaultTableStyle = "TableStyleMedium2"

End Sub

Looping through tables

The macros in this section loop through all the tables on the worksheet or workbook.

Loop through all tables on a worksheet

If we want to run a macro on every table of a worksheet, we must loop through the ListObjects collection.

Sub LoopThroughAllTablesWorksheet()

'Create variables to hold the worksheet and the table
Dim ws As Worksheet
Dim tbl As ListObject

Set ws = ActiveSheet
'Loop through each table in worksheet
For Each tbl In ws.ListObjects

    'Do something to the Table....

Next tbl

End Sub

In the code above, we have set the table to a variable, so we must refer to the table in the right way.  In the section labeled ‘Do something to the table…, insert the action to be undertaken on each table, using tbl to reference the table.

For example, the following will change the table style of every table.

tbl.TableStyle = "TableStyleLight15"

Loop through all tables in a workbook

Rather than looping through a single worksheet, as shown above, the macro below loops through every table on every worksheet.

Sub LoopThroughAllTablesWorkbook()

'Create variables to hold the worksheet and the table
Dim ws As Worksheet
Dim tbl As ListObject

'Loop through each worksheet
For Each ws In ActiveWorkbook.Worksheets

    'Loop through each table in worksheet
    For Each tbl In ws.ListObjects

        'Do something to the Table....

    Next tbl

Next ws

End Sub

As noted in the section above, we must refer to the table using its variable.  For example, the following will display the totals row for every table.

tbl.ShowTotals = True

Adding & removing rows and columns

The following macros add and remove rows, headers, and totals from a table.

Add columns into a table

The following macro adds a column to a table.

Sub AddColumnToTable()

'Add column at the end
ActiveSheet.ListObjects("myTable").ListColumns.Add

'Add column at position 2
ActiveSheet.ListObjects("myTable").ListColumns.Add Position:=2
End Sub

Add rows to the bottom of a table

The next macro will add a row to the bottom of a table

Sub AddRowsToTable()

'Add row at bottom
ActiveSheet.ListObjects("myTable").ListRows.Add

'Add row at the first row
ActiveSheet.ListObjects("myTable").ListRows.Add Position:=1
End Sub

Delete columns from a table

To delete a column, it is necessary to use either the column index number or the column header.

Sub DeleteColumnsFromTable()

'Delete column 2
ActiveSheet.ListObjects("myTable").ListColumns(2).Delete

'Delete a column by name
ActiveSheet.ListObjects("myTable").ListColumns("Feb").Delete
End Sub

Delete rows from a table

In the table structure, rows do not have names, and therefore can only be deleted by referring to the row number.

Sub DeleteRowsFromTable()

'Delete row 2
ActiveSheet.ListObjects("myTable").ListRows(2).Delete

'Delete multiple rows
ActiveSheet.ListObjects("myTable").Range.Rows("4:6").Delete
End Sub

Add total row to a table

The total row at the bottom of a table can be used for calculations.

Sub AddTotalRowToTable()

'Display total row with value in last column
ActiveSheet.ListObjects("myTable").ShowTotals = True

'Change the total for the "Total Column" to an average
ActiveSheet.ListObjects("myTable").ListColumns("TotalColumn").TotalsCalculation = _
    xlTotalsCalculationAverage

'Totals can be added by position, rather than name
ActiveSheet.ListObjects("myTable").ListColumns(2).TotalsCalculation = _
    xlTotalsCalculationAverage
End Sub

Types of totals calculation

xlTotalsCalculationNone
xlTotalsCalculationAverage
xlTotalsCalculationCount
xlTotalsCalculationCountNums
xlTotalsCalculationMax
xlTotalsCalculationMin
xlTotalsCalculationSum
xlTotalsCalculationStdDev
xlTotalsCalculationVar

Table header visability

Table headers can be turned on or off.   The following will hide the headers.

Sub ChangeTableHeader()

ActiveSheet.ListObjects("myTable").ShowHeaders = False

End Sub

Remove auto filter

The auto filter can be hidden.  Please note, the table header must be visible for this code to work.

Sub RemoveAutoFilter()

ActiveSheet.ListObjects("myTable").ShowAutoFilterDropDown = False

End Sub

I have a separate post about controlling auto filter settings – check it out here.  Most of that post applies to tables too.

Other range techniques

Other existing VBA techniques for managing ranges can also be applied to tables.

Using the union operator

To select multiple ranges, we can use VBA’s union operator. Here is an example, it will select rows 4, 1, and 3.

Sub SelectMultipleRangesUnionOperator()

Union(ActiveSheet.ListObjects("myTable").ListRows(4).Range, _
    ActiveSheet.ListObjects("myTable").ListRows(1).Range, _
    ActiveSheet.ListObjects("myTable").ListRows(3).Range).Select

End Sub

Assign values from a variant array to a table row

To assign values to an entire row from a variant array, use code similar to the following:

Sub AssignValueToTableFromArray()

'Assing values to array (for illustration)
Dim myArray As Variant
myArray = Range("A2:D2")

'Assign values in array to the table
ActiveSheet.ListObjects("myTable").ListRows(2).Range.Value = myArray

End Sub

Reference parts of a table using the range object

Within VBA, a table can be referenced as if it were a standard range object.

Sub SelectTablePartsAsRange()

ActiveSheet.Range("myTable[Category]").Select

End Sub

Counting rows and columns

Often, it is useful to count the number of rows or columns.  This is a good method to reference rows or columns which have been added.

Counting rows

To count the number of rows within the table, use the following macro.

Sub CountNumberOfRows()

Msgbox ActiveSheet.ListObjects("myTable").ListRows.Count

End Sub

Counting columns

The following macro will count the number of columns within the table.

Sub CountNumberOfColumns()

Msgbox ActiveSheet.ListObjects("myTable").ListColumns.Count

End Sub

Useful table techniques

The following are some other useful VBA codes for controlling tables.

Show the table data entry form

If a table starts at cell A1, there is a simple data entry form that can be displayed.

Sub ShowDataEntryForm()

'Only works if Table starts at Cell A1
ActiveSheet.ShowDataForm

End Sub

The following screenshot shows the data form for the example table.

Tables data input screen

Check if a table exists

The following macro checks if a table already exists within a workbook.  Change the tblName variable to adapt this to your requirements.

Sub CheckIfTableExists()

'Create variables to hold the worksheet and the table
Dim ws As Worksheet
Dim tbl As ListObject
Dim tblName As String
Dim tblExists As Boolean

tblName = "myTable"

'Loop through eac worksheet
For Each ws In ActiveWorkbook.Worksheets

    'Loop through each table in worksheet
    For Each tbl In ws.ListObjects

        If tbl.Name = tblName Then

            tblExists = True

        End If

    Next tbl

Next ws

If tblExists = True Then

    MsgBox "Table " & tblName & " exists."

Else

    MsgBox "Table " & tblName & " does not exists."

End If

End Sub

Find out if a table has been selected, if so which

The following macros find the name of the selected table.

Method 1

As you will see in the comments Jon Peltier had an easy approach to this, which has now become my preferred approach.

Sub SimulateActiveTable()

Dim ActiveTable As ListObject

On Error Resume Next
Set ActiveTable = ActiveCell.ListObject
On Error GoTo 0

'Confirm if a cell is in a Table
If ActiveTable Is Nothing Then
    MsgBox "Select table and try again"
Else
    MsgBox "The active cell is in a Table called: " & ActiveTable.Name
End If

End Sub

Method 2

This option, which was my original method, loops through each table on the worksheet and checks if they intersect with the active cell.

Sub SimulateActiveTable_Method2()

Dim ActiveTable As ListObject
Dim tbl As ListObject

'Loop through each table, check if table intersects with active cell
For Each tbl In ActiveSheet.ListObjects

    If Not Intersect(ActiveCell, tbl.Range) Is Nothing Then

        Set ActiveTable = tbl
        MsgBox "The active cell is in a Table called: " & ActiveTable.Name
    
    End If

Next tbl

'If no intersection then no tabl selected
If ActiveTable Is Nothing Then

    MsgBox "Select an Excel table and try again"

End If

End Sub

Conclusion

Wow! That was a lot of code examples.

There are over 30 VBA macros above, and even this does not cover everything, but hopefully covers 99% of your requirements. For your remaining requirements, you could try Microsoft’s VBA object reference library (https://docs.microsoft.com/en-us/office/vba/api/Excel.ListObject)


Discover how you can automate your work with our Excel courses and tools.

Excel Academy

Excel Academy
The complete program for saving time by automating Excel.

Excel Automation Secrets

Excel Automation Secrets
Discover the 7-step framework for automating Excel.

Office Scripts Course

Office Scripts: Automate Excel Everywhere
Start using Office Scripts and Power Automate to automate Excel in new ways.

57 thoughts on “VBA Tables and ListObjects”

  1. It really really a good one. It gave me solution to all my doubts. Thanks a lot. Explanation is so nice and simple, one can easily understand. Once again thanks

    Reply
      • Hi,
        This site is very helpful.
        Sorry to say, Jeff’s question wasn’t SHOULD he populate the new row when he creates, but rather, HOW would you populate the new row with data at the time of its creation.
        Thanks,

        Reply
  2. Hi,

    Lets say you have a table starting at row 10, 4 columns wide.
    on cell A7 i would like to place the MAX value from the table column1
    and on cell A8 the MIN value from the same column.
    And this for each column.

    How can this be done?
    following code generates an error 9
    myMax = Application.WorksheetFunction.Max(ActiveSheet.ListObjects(“Tabel1[kolom1]”).Range)

    Reply
    • To reference a column in a Table, you would need to use the following syntax:

      myMax = Application.WorksheetFunction.Max(ActiveSheet.ListObjects(“Tabel1”).ListColumns(“kolom1”).Range)

      Reply
  3. Awesome post!!! Thank you so much.
    I have a question for you:

    Do you know a way of applying a customized table style using vBA?
    I have only been able to use the predefined ones.
    This works:
    objSheet.ListObjects(sFile).TableStyle = “TableStyleMedium2
    But this does not:
    objSheet.ListObjects(sFile).TableStyle = “My_Style_Table”

    Thanks!!

    Reply
    • I’ve tested this, and I can select a custom style.

      The custom styles only exist in the workbook they are created in (they are not available in other workbooks), so it may be that the style you’ve created doesn’t exist in the workbooks you’re trying to apply them in.

      Reply
  4. Hi,
    Great learning points here. My question is I’m using the a Table as source data for a Pivot Table but the range I’m getting does not include the Header Row which is required by the Pivot Table.

    This is my code line that gets the source data:
    SrcData = shQB.Name & “!” & Range(“tbQB”).Address(ReferenceStyle:=xlR1C1

    As I said this does not include the Header Row in the return

    If I apply your line in article above such as
    SrcData = ActiveSheet.ListObjects(“tbQB”).Range then I get an error code 13
    H
    Any idea on how I can get this to work greatly appreciated

    Reply
    • Using structured references for Tables, the range should be defined as follows:

      Range("tbQB[[#Headers],[#Data]]")

      That should include the header row, but not the totals row.

      Reply
  5. For some of the ‘check’ type subroutines, I’d suggest changing the sub to a function.
    Example
    sub CheckTableExists()
    becomes
    Function CheckTableExists(tblname as string) as boolean
    Instead of the MsgBox responses inside the sub, you’d set the return value to TRUE or FALSE as appropriate

    Reply
  6. Hello,
    I look for a way to DISABLE the “Autofill ” for table columns.
    I’ve tryed the following actions but did not work:
    1. “Application.AutoCorrect.AutoExpandListRange = False”
    2. “Application.AutoCorrect.AutoFillFormulasInLists = False”

    How can I get this working out?

    Reply
  7. This post explained Excel tables as implemented in VBA. I watched long boring Excel tutorials. I’ve learned a lot from them but didn’t get the information about manipulating tables in VBA.
    The codes presented here are straight forward.
    Thanks a lot!

    Reply
  8. Instead of selecting a specific row, how would you select a row based on an active cell? Using (ActiveCell.Row) in lieu of the row number?

    Sub SelectRowOfData()

    ActiveSheet.ListObjects(“myTable”).ListRows(??).Range.Select

    End Sub

    Reply
    • You could just use a simple calculation based on row numbers:

      Dim SelectRow As Integer
      SelectRow = ActiveCell.Row - ActiveSheet.ListObjects("myTable").ListRows(1).Range.Row + 1
      
      ActiveSheet.ListObjects("myTable").ListRows(SelectRow).Range.Select
      Reply
  9. Very useful information all in one place! Thank you!

    I have a table where once a task is completed and column S contains a “Y”, I would like to move that row to the bottom of the table. How can I do this?

    Thanks

    Reply
  10. What an excellent post. Thank you.
    I came looking for one thing and found a wealth of information on other things I can use. Having said that, what I was looking for isn’t here and I hope you can help.

    I have a workbook with many many tables and recently some corruptions in the file began to occur. The excel error report “Repaired Records: External data range from /xl/queryTables/queryTable17.bin part (External data range)”.
    The xml report didn’t have any additional info.
    Some of the tables are refreshed by powerquery from csv files in the same folder.

    I had already renamed all of my tables to Tbl_AMoreDescriptiveTableName and have no idea which one is Table17.
    Because I’ve renamed the tables, the original table numbers are nowhere to be found (not that I can see in name manager etc.)

    I was given the VB code (excerpt below) but it only lists the table name and sheet it’s located but not the original table number that the MS error message refers to.
    Is there a way to determine the same table number as referenced by Excel’s error handling ?

    variable tbl As ListObject

    .Cells(lRow, “A”) = tbl.Name
    .Cells(lRow, “B”) = tbl.Parent.Name (for the sheet it’s located in)

    Reply
    • It’s difficult to advise, as your file is corrupted. So it’s not a standard scenario.

      If your file is corrupted, then it may be that Table17 doesn’t exist, but within the XML file structure Excel believes it does. You could try (a) rebuilding the file (b) finding some software that repairs Excel files.

      Reply
  11. Very useful information!

    It’s probably a subset of what you have included, but I have an Excel Table (ValidTags) that is just a header and a list of values, and I want to update the table with a 1D array of values (TagArray). Might be bigger or smaller.

    How do I do that?

    Reply
  12. I’m attempting to use these table references to copy table contents to a blank sheet in another file, and I get a subscript out of range.

    Sheets(“SourceSheetWithTable”).ListObjects(“ExcelTableName”).Range.Copy Workbooks(“Destination.xlsx”).Worksheets(“Sheet1”).Range(“A1”)

    Does it not like going from a table to a regular range? Does the range have to match the size of the table?

    Reply
    • The “Subscript out of range” error is because one of the items you’ve referenced doesn’t exist. When I’ve tested your code it works fine, so it’s definitely something to do with the names in your environment.
      (a) You should double-check the names of everything, as there is probably a typo in there.
      (b) Are you running the code with the workbook containing the “SourceSheetWithTable” sheet as the active workbook

      Reply
      • Thanks- here’s what I cobbled together from some other sources. Instead of using the Copy method, it’s assigning .value to .value. It doesn’t seem as elegant but it works! I added my questions as comments. Could you tell me if I’m understanding correctly?

        ‘load a Range variable with the listobject.Range
        With wsCopy.ListObjects(1)
        Set src = .Range ‘Union(.HeaderRowRange, .DataBodyRange)
        End With

        ‘Does this resize the destination range to match the size of the src.Range and then assign it the src.Range.Value? It looks like .Rows.Count and .Columns.Count inside the Resize method refer to src variable due to being inside the With?
        With src
        wsDest.Range(“A1”).Resize(.Rows.Count, .Columns.Count).Value = .Value
        End With

        Reply
  13. Is there any way to sort a table using a custom list? I’m new to VBA and all this information is great stuff!

    Reply
    • Try it with the Macro recorder. You can sort a custom list using the standard sort dialog box. Then look at the code and see which bit appears to be the correct part to achieve what you want.

      Reply
  14. Thanks for your efforts to teach us
    could you plz advise if want to add row in a table with active cells
    is highly appreciated

    Reply
  15. Very helpful reference on listobjects!

    Can you suggest a way to populate a 2-column listbox with two columns from an Excel table using structured references?

    Reply
  16. Great post – my issue occurs when I do a .ListObjects(table_name).Range.ClearContents
    the execution of the line above deletes my table_name and the table associated with it.
    .ListObjects(table_name).Range.Value = data_obj
    this line also deletes my table_name and the table associated with it.
    data_obj is a variant that is a 2d array. I am trying to use the same table, but the dimensions change when new data is requested
    My table gets created in VBA using the following
    .ListObjects.Add(xlSrcRange, data_rng, , xlYes, , “TableStyleMedium2”).Name = table_name
    Why is the table disappearing. I have these table names linked to charts, and the deletion of the table is causing a bit of pain. Any help will be greatly appreciated

    Reply
    • By using Range, you are referencing the entire table object. Have you tried using:
      .ListObjects(table_name).DataBodyRange.ClearContents
      That should just clear the data, but keep the Table on the worksheet.

      Reply
  17. Thanks so much for the quick response. Yes, I have tried clearing the DataBodyRange and the HeaderRowRange both of these calls maintain the table
    The second line where I do the assignment
    .ListObjects(table_name).Range.Value = data_obj
    also deletes the table_name and the table associated with the name

    Because the table dimensions change, I do a resize
    .ListObjects(table_name).Resize data_rng
    I get data_rng as follows – cellAddr is A1 – the start of the table header row
    Set data_rng = .Range(cellAddr).Resize(row_cnt, col_cnt)

    Am I required to set the HeaderRowRange and the DataBodyRange separately when I want to assign the data_obj to the Range.Value?

    I was hoping I could just assign
    .ListObjects(table_name).Range.Value = data_obj

    otherwise I need to unwind the data_obj to pull out the headers and the data body.

    Thanks again

    Reply
  18. Is there any way to set the entire range of the table without setting the HeaderRowRange and the DataBodyRange separately?

    .ListObjects(table_name).Resize data_rng
    .ListObjects(table_name).Range.Value = data_obj

    The second line will delete the table_name and the table associated with it.

    Reply
  19. Thank you so very much for this summary. I found everything except how to reference a cell by column name and by row number. I wish to loop through the values in a column called “Color”.
    colr = tbl2.DataBodyRange(x, “Color”).Value
    better yet, I’d like to find the row in this table that has a match to a specific color.

    Reply
  20. Answered my own question with clues from above.
    Loop Through all items in a table column:
    for x = 1 to tbl.ListRows.Count
    colr = tbl.ListColumns(“Color”).Range(x + 1).Value
    ‘use colr for something
    next x

    Reply
    • Hi Steven,

      I would just make on change to your method so that you use the DataBodyRange rather than the Range (this means you can use x rather than x+1)

      for x = 1 to tbl.ListRows.Count
      colr = tbl.ListColumns("Color").DataBodyRange(x).Value
      'use colr for something
      next x
      Reply
    • hey steven,
      here’s an alternate method that i use to loop through all table rows in a specific column:
      but you have to watch because your x +1 will exceed the number of rows in the table
      dim icell as range
      For Each icell In [Table_name[column_name]]
      ‘do whatever
      next

      Reply
  21. this was a very helpful article. i have since used the following to address parts of a table. it’s just my preference to use these since i create most of my tables on the fly in vba.

    not an exhaustive list, just thought i’d post them in case anybody else wants to give them a try.
    Select the data within a table
    ?[Table_Summary_1].address

    Get a value from an individual cell within a table ?[Table_Summary_1].cells(2,4).value

    Select an entire column, header and totals row included
    ?[Table_Summary_1[[#All],PO]].Select

    Select a column (data only)
    ?[Table_Summary_1[customer]].Select
    $A$6:$A$14
    ?[Table_Summary_1].columns(1).Select
    $A$6:$A$14

    Select a specific column header

    ?[Table_Summary_1].cells(0,4).value
    PO
    ?[Table_Summary_1[PO]].rows(0).Select

    Select a specific column within the totals section activesheet.ListObjects(“Table5”).ListColumns(“weight”).Total.Value

    Select an entire row of data
    ?[Table_Summary_1].rows(2).Address
    $A$7:$N$7

    Select the header row
    [Table_Summary_1].rows(0).select

    setting column alignment
    [Table_Summary_1[Customer]].HorizontalAlignment = xlCenter

    Reply
  22. Thanks for your discussion of Tables, I learned several things. The thing I was looking for, however, is below.

    An SQL SELECT statement can be run on an Excel Table, BUT you can’t use the table name directly. One way to run the SQL statement is to use a Range name. So, my question is, how can I assign a table’s address to a range name, in VBA?

    Reply
    • Hi Mike,

      The Table contains a Range and DataBodyRange property.
      Range = Whole table
      DataBodyRange = Data only, without the header

      So to get the address of a Table you could use:

      Dim tbl As ListObject
      Set tbl = Worksheets("Template").ListObjects("Template")
      
      MsgBox tbl.Range.Address
      MsgBox tbl.DataBodyRange.Address
      
      Reply
  23. Hi
    I really appreciate this information. I sure am learning.
    I am wanting to find a value and replace the row with amended data.
    I have an unique no. assisgned to each row as part of the table.

    I see you have shown how to select a table row. I am unsure how to use this info in find and replace a table row with the amended row data.
    Deeanna

    Reply
  24. Great article. Thanks.

    To clear formatting after converting to range we can use ClearFormats..

    Sub ConvertTableToRange()
    Dim rng As Range
    Set rng = ActiveSheet.ListObjects(“myTable2”).Range
    ActiveSheet.ListObjects(“myTable2”).Unlist
    rng.ClearFormats
    End Sub

    I have not gone through all comments above so someone may have suggested this.

    Reply
  25. Wow 🤩 it’s a great article! Thank you.
    How can I copy a “table” from sheet1 then paste it in sheet2 but when I do it again and every time I want to paste it in sheet2 it should be pasted above the previous pasted table and so on.

    Also, I need to print the time stamp on the left top of every table like this: “Printed on 19/07/2023 11:11”

    Reply

Leave a Comment