Excel like a finance pro.
Format a sheet so it's fit to send
The ten minutes of tidying that happens after every refresh, in one keystroke.
1What it does
A refreshed export is correct and unreadable: no thousands separators, negatives with a minus sign buried mid-column, columns too narrow to show the headers, and nothing frozen. Fixing that by hand takes ten minutes and happens every single month. The macro does the lot — number format with negatives in brackets, a bold header row, autofit, freeze panes, and a border under the headings. The one rule worth following is to format the RANGE rather than whole columns: `Columns("B:D").NumberFormat` touches a million cells and makes the file bigger and slower for no benefit.
2The code
Sub FormatReport()
Dim ws As Worksheet, lastRow As Long, lastCol As Long
Set ws = ActiveSheet
lastRow = ws.Cells(ws.Rows.Count, 1).End(xlUp).Row
lastCol = ws.Cells(1, ws.Columns.Count).End(xlToLeft).Column
If lastRow < 2 Then Exit Sub ' nothing but a header
Application.ScreenUpdating = False
With ws.Range(ws.Cells(1, 1), ws.Cells(1, lastCol))
.Font.Bold = True
.Interior.Color = RGB(244, 242, 234)
.Borders(xlEdgeBottom).Weight = xlMedium
End With
' Numbers only, and only the used range — never whole columns.
With ws.Range(ws.Cells(2, 2), ws.Cells(lastRow, lastCol))
.NumberFormat = "#,##0;(#,##0)" ' accountant's brackets
.HorizontalAlignment = xlRight
End With
ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol)).Columns.AutoFit
' Freeze below the header. Needs the sheet active, so do it last.
ws.Activate
ws.Range("A2").Select
ActiveWindow.FreezePanes = False ' clear any existing freeze first
ActiveWindow.FreezePanes = True
ws.Range("A1").Select
Application.ScreenUpdating = True
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
- Tidy a refreshed export before it goes to anyone.
- Make every monthly schedule look the same without doing it by hand.
- Run it at the end of a close macro so the output is presentable.
4See it in action
A simulation — press Run to perform what the macro does to a sample workbook.
| Account | This month | Last month |
|---|---|---|
| 4000 Product revenue | 486000 | 441200 |
| 5000 Cost of goods sold | -281100 | -259400 |
| 6200 Payroll | -94300 | -88100 |
| 6400 Travel | -3120 | -5880 |
Correct and unreadable: no separators, negatives with a stray minus, columns too narrow for their headings.
5Pitfalls
Formatting whole columns — `Columns("B:D").NumberFormat = …` — touches over a million cells per column and inflates the file.
Fix: Build the range from the last used row and column, as above.
FreezePanes does nothing, because the sheet wasn't active. It's a window property, not a sheet one.
Fix: Activate the sheet and select the anchor cell first — the only place in this macro where Select is unavoidable.
Running it twice stacks a second freeze in the wrong place.
Fix: Set `FreezePanes = False` before setting it True, as above.
The header row is formatted as numbers too, so a text heading goes right-aligned and odd.
Fix: Start the number range at row 2 and column 2 — labels stay left.
6No-code alternatives
- A Table (Ctrl + T) — Gets you banding, autofilter and a frozen header for free, and survives a refresh. Worth preferring when the data allows it.
- Cell Styles — Define the look once and apply by name; a macro then only has to assign the style.
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.