Print-Ready All Sheets: One Click to Set Landscape, Narrow Margins, and Fit-to-Width on Every Tab
Standardizes print settings — landscape, fit-to-width, narrow margins, centered — across every qualifying sheet in one pass. No more setting up Page Setup 30 times before the partner review.
Table of Contents
TL;DR: You’re printing a 30-tab workpaper for the partner’s binder. Every sheet needs landscape, fit-to-width, narrow margins, and a centered layout. This macro handles it all in one pass — prompts for visible-only or all-sheets, skips Cover and Notes tabs by name, shows live progress in the status bar, and tells you exactly how many sheets were set up. Open Print Preview on any tab and it’s ready.
The Problem
You’ve built a 28-tab workpaper for the quarterly review. Depreciation schedules. State apportionment. M-1 reconciliation. Trial balance tie-out. Every number is right. You hit Ctrl+P on the first sheet and see a portrait spreadsheet with “Normal” margins bleeding into a second page. You fix it — landscape, fit to width, narrow margins, center on page. Switch to Sched-E. Portrait. Normal margins. Fix it. Sched-L. Same thing. Twelve sheets in, the partner walks by and asks if the binder is ready. It’s not. You’re still doing Page Setup.
Now imagine doing this every quarter. Every engagement. Every time you inherit a workbook from someone who never set up print settings. Fifteen minutes per binder, three binders per quarter, four quarters a year — that’s three hours of your life spent clicking Page Layout → Orientation → Landscape → Margins → Narrow → repeat.
#Prerequisites & Setup
What you’ll need:
- Excel 2016+ (desktop)
- A multi-sheet workbook — tax workpapers, trial balance, schedules, depreciation
- No special setup required — the macro handles sheets with or without existing settings
What the macro sets:
- Orientation: Landscape
- Scaling: Fit to 1 page wide (auto height)
- Margins: Narrow (0.25” left/right, 0.5” top/bottom)
- Alignment: Centered horizontally on the page
- Print area: Full UsedRange
- Headers/Footers: Assigned only if blank (does not overwrite existing headers)
Limitations:
- Works on
ThisWorkbook— the workbook containing the macro. Store in Personal Macro Workbook to run on any open file - Every qualifying sheet gets landscape — if you have a portrait-only sheet (e.g., Cover), add its name to the
EXCLUDEconstant - Overwrites existing print settings — orientation, margins, scaling, print area are replaced, not merged
- Print settings in VBA are inherently slow — each
PageSetupproperty access is a cross-process call. The status bar shows live progress so you know it’s working - Does not set specific paper size (assumes Letter) or print titles (repeat rows/columns)
#The Macro
Option Explicit
Sub PrintReadyAllSheets()
' ── Print-Ready All Sheets ─────────────────────────
' Standardizes print settings across every qualifying
' sheet in one pass. Prompts for visibility scope
' (visible-only or all), skips excluded sheets by
' name, and reports live progress in the status bar.
'
' Sets: landscape, fit 1 page wide, narrow margins,
' center-on-page, print area = UsedRange, and default
' headers/footers ONLY if the sheet doesn't have them.
' ────────────────────────────────────────────────────
' ── Configuration ──────────────────────────────────
Const EXCLUDE As String = "Cover,Notes,TOC,Instructions,Dashboard"
' ── State management ───────────────────────────────
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
' ── Variables ──────────────────────────────────────
Dim ws As Worksheet
Dim updated As Long, skipped As Long, total As Long
Dim excludeArr() As String
Dim i As Long, j As Long
Dim isExcluded As Boolean
Dim visibleOnly As VbMsgBoxResult
Dim progress As Long
' ── Error handling ─────────────────────────────────
On Error GoTo CleanUp
' ── Step 1: Ask about visibility scope ─────────────
visibleOnly = MsgBox("Set up visible sheets only?" & vbCrLf & _
vbCrLf & " Yes = Visible sheets only" & vbCrLf & _
" No = All sheets (including hidden)", _
vbYesNoCancel + vbQuestion, "Print Setup Scope")
If visibleOnly = vbCancel Then GoTo CleanUp
' ── Step 2: Parse exclude list ─────────────────────
excludeArr = Split(EXCLUDE, ",")
For i = LBound(excludeArr) To UBound(excludeArr)
excludeArr(i) = Trim(excludeArr(i))
Next i
' ── Step 3: Count qualifying sheets ────────────────
total = 0
For Each ws In ThisWorkbook.Worksheets
If visibleOnly = vbNo Or ws.Visible = xlSheetVisible Then
isExcluded = False
For j = LBound(excludeArr) To UBound(excludeArr)
If StrComp(ws.Name, excludeArr(j), vbTextCompare) = 0 Then
isExcluded = True
Exit For
End If
Next j
If Not isExcluded Then total = total + 1
End If
Next ws
If total = 0 Then
MsgBox "No qualifying sheets found.", vbExclamation
GoTo CleanUp
End If
' ── Step 4: Confirm with user ──────────────────────
If MsgBox("Apply print settings to " & total & " sheet(s)?" & _
vbCrLf & vbCrLf & "This will overwrite existing page setup " & _
"on every qualifying sheet.", vbYesNo + vbExclamation, _
"Confirm") = vbNo Then GoTo CleanUp
' ── Step 5: Apply print settings ───────────────────
updated = 0
skipped = 0
progress = 0
For Each ws In ThisWorkbook.Worksheets
' Apply visibility filter
If visibleOnly = vbYes And ws.Visible <> xlSheetVisible Then
skipped = skipped + 1
GoTo NextSheet
End If
' Check exclusion list (case-insensitive)
isExcluded = False
For j = LBound(excludeArr) To UBound(excludeArr)
If StrComp(ws.Name, excludeArr(j), vbTextCompare) = 0 Then
isExcluded = True
Exit For
End If
Next j
If isExcluded Then
skipped = skipped + 1
GoTo NextSheet
End If
progress = progress + 1
Application.StatusBar = "Setting up sheet " & progress & _
" of " & total & ": " & ws.Name & "..."
' ── Page setup (group all calls for one sheet) ──
With ws.PageSetup
.Zoom = False
.FitToPagesWide = 1
.Orientation = xlLandscape
.LeftMargin = Application.InchesToPoints(0.25)
.RightMargin = Application.InchesToPoints(0.25)
.TopMargin = Application.InchesToPoints(0.5)
.BottomMargin = Application.InchesToPoints(0.5)
.CenterHorizontally = True
.CenterVertically = False
.PrintArea = ws.UsedRange.Address
End With
' ── Headers/footers — only if blank ─────────────
If ws.PageSetup.LeftHeader = "" And _
ws.PageSetup.CenterHeader = "" And _
ws.PageSetup.RightHeader = "" Then
ws.PageSetup.LeftHeader = "&F"
ws.PageSetup.RightHeader = "&D"
End If
If ws.PageSetup.LeftFooter = "" And _
ws.PageSetup.CenterFooter = "" And _
ws.PageSetup.RightFooter = "" Then
ws.PageSetup.LeftFooter = ThisWorkbook.FullName
ws.PageSetup.CenterFooter = "FOR INTERNAL USE ONLY"
ws.PageSetup.RightFooter = "Page &P of &N"
End If
updated = updated + 1
NextSheet:
Next ws
' ── Step 6: Summary ────────────────────────────────
MsgBox updated & " sheet(s) set up for print." & vbCrLf & _
skipped & " sheet(s) skipped.", vbInformation, _
"Print Setup Complete"
CleanUp:
Application.StatusBar = False
Application.ScreenUpdating = True
Application.Calculation = xlCalculationAutomatic
If Err.Number <> 0 Then
MsgBox "Error " & Err.Number & ": " & Err.Description, _
vbCritical, "Macro Error"
End If
End Sub
#How It Works
#Two passes: count first, apply second
The macro counts qualifying sheets before it touches anything. This serves two
purposes. First, the confirmation message tells you exactly how many sheets will
be affected — "Apply print settings to 24 sheet(s)?" — so you can cancel if
the number is wrong. Second, it lets the status bar show meaningful progress
("Setting up sheet 12 of 24: Sched-E Deductions...") instead of a meaningless
increment.
total = 0
For Each ws In ThisWorkbook.Worksheets
If visibleOnly = vbNo Or ws.Visible = xlSheetVisible Then
' ... exclusion check ...
If Not isExcluded Then total = total + 1
End If
Next ws
The count pass is free — it iterates worksheet objects without touching any cells or page setup properties, so it completes in milliseconds.
#PageSetup is slow — group all calls for one sheet
Every ws.PageSetup property access is a cross-process call from VBA to Excel’s
printing engine. Accessing five properties across five separate With blocks
takes five cross-process calls. Wrapping them in a single With ws.PageSetup
block minimizes the overhead.
With ws.PageSetup
.Zoom = False
.FitToPagesWide = 1
.Orientation = xlLandscape
.LeftMargin = Application.InchesToPoints(0.25)
.RightMargin = Application.InchesToPoints(0.25)
.TopMargin = Application.InchesToPoints(0.5)
.BottomMargin = Application.InchesToPoints(0.5)
.CenterHorizontally = True
.PrintArea = ws.UsedRange.Address
End With
Despite the grouping, setting up 30 sheets still takes 5–15 seconds depending on your machine and workbook size. That’s why the status bar feedback is non-negotiable — without it, the user sees nothing while Excel appears to freeze.
#Why Zoom = False matters
.Zoom = False
.FitToPagesWide = 1
Setting Zoom = False toggles Excel from percentage-based scaling to fit-to-page
scaling. Without this line, FitToPagesWide = 1 has no effect — Excel ignores it
and keeps whatever zoom percentage was already set. The order matters: Zoom must
be set to False before FitToPagesWide.
Not setting FitToPagesTall means “automatic” — the sheet uses as many pages in
height as it needs. For a workpaper with 50 rows that fits on one page in landscape,
that’s one page total. For a depreciation schedule with 200 rows, the height expands
to two or three pages automatically.
#Headers and footers are additive, not destructive
The macro checks whether headers or footers already exist before writing anything:
If ws.PageSetup.LeftHeader = "" And _
ws.PageSetup.CenterHeader = "" And _
ws.PageSetup.RightHeader = "" Then
ws.PageSetup.LeftHeader = "&F"
ws.PageSetup.RightHeader = "&D"
End If
If the sheet already has custom headers — perhaps applied by the Batch
Header/Footer macro with firm name, client name, and tax year — this macro
leaves them untouched. It only fills in blanks. The &F code inserts the
workbook filename, &D inserts the current date, and the footer gets a file
path, “FOR INTERNAL USE ONLY” watermark, and page numbers.
The same guard applies to footers. If any of the three footer sections is non-empty, the entire footer is left alone — the assumption being that if someone configured a footer, they configured all of it.
#The exclude list: Cover gets portrait everything
The EXCLUDE constant skips sheets that shouldn’t get landscape and narrow margins.
A cover page is the textbook example — it’s one page with the firm logo, engagement
title, and preparer info, and it looks terrible in landscape. The constant string is
split by comma, trimmed, and matched case-insensitively.
Const EXCLUDE As String = "Cover,Notes,TOC,Instructions,Dashboard"
Add your own sheet names to this list before running. If your firm uses “Summary”
as a cover sheet, add it. The matching uses StrComp with vbTextCompare so
“COVER”, “cover”, and “Cover” are all treated identically.
#Why a MsgBox before anything happens
This macro overwrites print settings on every sheet it touches. There is no undo.
The two-step confirmation — first the scope dialog (Yes/No/Cancel), then the
explicit confirm with sheet count — gives you two chances to back out. If you
selected “No” for all-sheets and the count says “24 sheet(s)” but you expected 12,
you cancel, investigate, and run again.
#Adapt It
Get the next macro in your inbox
One copy-paste-ready macro recipe every two weeks. No spam, no VBA theory — just automation that saves you time.
Excel Macro Guy
Excel enthusiast · married to an accountant
I love Excel. My wife is an accountant. Every busy season, I watch her wrestle with workpapers and think "a macro could do that in half a second." So I build them. She tests them on real client data. What survives gets published here.