Excel like a finance pro.
Work with an Excel Table instead of a range
Address columns by their header name, and the macro survives inserted rows and columns.
1What it does
Almost every macro on this site finds its data by position — last used row, column C. That's fragile: insert a column and "Amount" is no longer column C. An Excel Table (a ListObject in VBA) gives the data a name and gives every column a name, so the macro can ask for `tbl.ListColumns("Amount")` and get the right column wherever it has moved to. Tables also grow automatically when rows are added, so there's no last-row arithmetic at all. It's the single change that makes a macro robust to the way people actually edit spreadsheets.
2The code
Sub TotalByHeaderName()
Dim ws As Worksheet, tbl As ListObject
Dim amountCol As ListColumn, cell As Range, total As Double
Set ws = ThisWorkbook.Worksheets("Data")
' Refer to the table by NAME (Table Design → Table Name), not by position.
On Error Resume Next
Set tbl = ws.ListObjects("tblInvoices")
On Error GoTo 0
If tbl Is Nothing Then
MsgBox "No table called tblInvoices on the Data sheet.", vbExclamation
Exit Sub
End If
' The column is found by its HEADER, so inserting columns can't break it.
Set amountCol = tbl.ListColumns("Amount")
' DataBodyRange excludes the header and any totals row. It's Nothing
' when the table has no rows yet, so guard it.
If Not amountCol.DataBodyRange Is Nothing Then
For Each cell In amountCol.DataBodyRange
If IsNumeric(cell.Value) Then total = total + cell.Value
Next cell
End If
' Add a row: the table grows, and formulas in other columns fill down.
With tbl.ListRows.Add
.Range(1, tbl.ListColumns("Customer").Index).Value = "Total"
.Range(1, amountCol.Index).Value = total
End With
End SubPaste into the Visual Basic Editor (Alt + F11 → Insert → Module), then run and save as macro-enabled (.xlsm).
New to macros? Set up in 5 minutes▾
- 1
Don't see the Developer tab in the ribbon?
You don't strictly need it — Alt + F11 opens the editor directly — but it makes running macros easier.- Windows: File → Options → Customize Ribbon → tick Developer in the right-hand list → OK.
- Mac: Excel → Preferences → Ribbon & Toolbar → tick Developer → Save.
- 2
Paste in the code
Press Alt + F11 to open the Visual Basic editor, then Insert → Module and paste the snippet's code into the blank window. Close it with Alt + Q. - 3
Run it
Press Alt + F8, pick the macro's name, and click Run — that's it. (Pasted a custom function instead? Just type it into a cell like any built-in:=GrossMargin(B2, B3).) - 4
Keep the macro — save as .xlsm
File → Save As → Excel Macro-Enabled Workbook (.xlsm). A plain .xlsx silently drops the code when you save. - 5
Macros blocked?
Click Enable Content on the yellow bar. If you downloaded the file, you may first need to right-click it → Properties → tick Unblock → OK, then reopen.
Heads up: macros can't be undone with Ctrl + Z — save a copy before running one that changes your workbook.
3When you use it
- Read a column by name so the macro survives a reordered export.
- Append a row without working out where the data ends.
- Loop only the data rows, excluding the header and totals row automatically.
4See it in action
A simulation — press Run to perform what the macro does to a sample workbook.
| ACustomer | BAmount |
|---|---|
| Acme | 4,200 |
| Globex | 9,800 |
| Initech | 1,450 |
Insert the column, then run it. Only one of the two approaches still finds Amount.
5Pitfalls
DataBodyRange is Nothing on an empty table, and the next line errors with 91.
Fix: Check `If Not col.DataBodyRange Is Nothing` before looping, as above.
The table is referred to as ListObjects(1), which breaks the moment a second table is added.
Fix: Name the table in Table Design and use the name.
A header gets renamed and ListColumns("Amount") errors with 9.
Fix: Header names are now part of the contract. Error-handle the lookup and say which column is missing.
Writing values into a calculated column overwrites the formula for every row.
Fix: Write into input columns only; let calculated columns fill themselves.
6No-code alternatives
- Find the column by header with Range.Find — Works on a plain range when converting to a table isn't possible. See the find-value snippet.
- Structured references in formulas — =SUM(tblInvoices[Amount]) gets the same robustness with no macro at all.
Rather not write macros? Wauvel's free tools generate branded, formula-driven Excel for you — no VBA required.
Learn the moves here — or let Wauvel run them on your numbers.
Meet your AI CFO →One CFO-grade Excel tip a week
A short, practical email for finance operators — functions, shortcuts, and the moves that save an afternoon. Free, unsubscribe anytime.