Wauvel

Excel like a finance pro.

← All VBA snippets

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 Sub

Paste 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. 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. 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. 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. 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. 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.

AccountThis monthLast month
4000 Product revenue486000441200
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.