TL;DR — There is no
Sheets.Exists. Write one function, put it in every project, and stop improvising: try toSetthe sheet with error handling switched off for one line, then check whether the variable isNothing. Get three details right and it never lies: ask a specific workbook, not whatever happens to be active; searchSheets, notWorksheets, because a chart sheet can already hold the name; and pass the name as aString, because aVariantholding a number is read as a position. Remember that hidden sheets exist too — "exists" is not "visible".
Function SheetExists(ByVal sheetName As String, Optional wb As Workbook) As Boolean
Dim sh As Object
If wb Is Nothing Then Set wb = ThisWorkbook
On Error Resume Next
Set sh = wb.Sheets(sheetName)
On Error GoTo 0
SheetExists = Not sh Is Nothing
End Function
This is the third of a three-part cluster on a sheet's identity. The tab name is a label the user owns. Rename changes that label, hide takes the tab off screen without taking the sheet out of reach, and exists, covered here, is the check you run before trusting a label. Any code that finds a sheet by a name a user could have changed should ask this question first.
What you'll learn
- The mental model: existence is a question about one name in one workbook
- The function, and why each of its lines is there
- Three ways the common versions give the wrong answer
- Loop, On Error, or Evaluate: which approach to use when
- The patterns that depend on it: get-or-create, delete-if-exists, unique names
- Checking a sheet in a workbook that is closed
The mental model: one name, one workbook, one namespace
"Does the sheet exist?" is always shorthand for a narrower question: does this workbook contain a sheet
of any kind whose name matches this text, ignoring case? Each part of that sentence is a place where a
check can go wrong. This workbook — not the active one by accident. A sheet of any kind — worksheets and
chart sheets share one set of names. Ignoring case — SALES and Sales are the same name to Excel.
And a sheet that exists may not be on screen. Hidden and very hidden sheets are still in the collection, so the check finds them — which is exactly right when you are about to add a sheet with that name, because Excel would refuse the duplicate even though the user cannot see it.
The function, line by line
The version above does four things, and each one matters:
Dim sh As Object—Object, notWorksheet, so a chart sheet can be assigned without a type mismatch.If wb Is Nothing Then Set wb = ThisWorkbook— a default you chose on purpose, instead of the implicitActiveWorkbookan unqualifiedSheetswould use.On Error Resume Next...On Error GoTo 0— errors are ignored for exactly one line. The lookup raises error 9 when the name is missing, which is the answer we want; any other error elsewhere stays visible. The On Error guide explains why the switch must always be turned back off.SheetExists = Not sh Is Nothing— if the lookup failed,shwas never set and is stillNothing.
Use it wherever a name comes from outside your code — a cell, a user, a file name:
If SheetExists("Summary") Then
ThisWorkbook.Sheets("Summary").Range("A1").Value = Date
Else
MsgBox "The Summary sheet is missing."
End If
Debug.Print SheetExists("Rates", Workbooks("Prices.xlsx")) ' ask another open workbook
Three ways the common versions give the wrong answer
1. Asking the wrong workbook. Many snippets call Sheets(name) with no workbook in front. That searches
whatever workbook is active when the line runs — which is not the one you meant as soon as your macro has
opened a second file. The check says "missing", the next line adds a sheet to the wrong workbook, and nothing
errors. Always pass or default the workbook explicitly, as the function does.
2. Searching Worksheets instead of Sheets. Worksheets only contains worksheets; Sheets also contains
chart sheets. Names are unique across both. So if a chart sheet is called Summary, a check against
Worksheets says the name is free, and ws.Name = "Summary" then fails with error 1004. For "can I use this
name?" the only correct collection is Sheets.
3. Passing a number by accident. Sheets(3) means the third sheet; Sheets("3") means the sheet called
3. If the name arrives in a Variant — from a cell, for example — and the cell holds the number 3, the
lookup goes by position and finds whatever sheet is third. The check says "exists" for a sheet that has
nothing to do with the name. Declaring the parameter ByVal sheetName As String forces the conversion to
text before the lookup, which is why the signature matters.
Loop, On Error, or Evaluate
You will see three approaches. Here is how they compare:
| Approach | How | Verdict |
|---|---|---|
On Error + Set |
try the lookup, check for Nothing |
default — one lookup, exact Excel semantics |
Loop + StrComp |
compare each name, case-insensitively | clear; use it when you match a pattern, not a name |
Evaluate("ISREF(...)") |
build a formula reference and test it | avoid — breaks on apostrophes and chart sheets |
The loop is the right tool when "exists" really means "any sheet whose name starts with 2026":
Function FirstSheetLike(wb As Workbook, ByVal pattern As String) As Object
Dim sh As Object
For Each sh In wb.Sheets
If LCase$(sh.Name) Like LCase$(pattern) Then
Set FirstSheetLike = sh
Exit Function
End If
Next sh
End Function
' Set sh = FirstSheetLike(ThisWorkbook, "2026-*") ' Nothing if none matches
The Evaluate trick — Evaluate("ISREF('" & name & "'!A1)") — looks clever and fails in quiet ways: a name
containing an apostrophe breaks the formula unless you double it, a chart sheet has no A1 and returns
False, and the formula is evaluated against the active workbook. It saves two lines and costs you three
bugs.
The patterns built on it
Almost every use of the check is one of three patterns, and each has its own guide:
' Get or create: reuse the sheet if it is there, otherwise add it
If SheetExists("Log") Then
Set ws = ThisWorkbook.Worksheets("Log")
Else
Set ws = ThisWorkbook.Worksheets.Add(After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count))
ws.Name = "Log"
End If
' Delete if exists: no error 9 when it is already gone
If SheetExists("Temp") Then
Application.DisplayAlerts = False
ThisWorkbook.Sheets("Temp").Delete
Application.DisplayAlerts = True
End If
The Add Sheet guide covers the first in full, the
Delete Sheet guide the second, including the last-visible-sheet rule. The third is
generating a free name — Report (2), Report (3) — which the Rename Sheet guide
builds on top of SheetExists.
The judgment call: check names, do not rely on them
The check exists because names are fragile. It makes code that has to use a name — sheets the user creates, names typed into a cell, files from outside — safe. It is not a reason to keep finding your own sheets by name. For sheets your tool owns, use the CodeName and there is nothing to check. My rule: if a name came from a person, check it; if the sheet came from you, do not look it up by name at all. And for a workbook that is closed, there is no shortcut worth trusting: open it read-only, check with the same function, and close it.
How ExcelMaster helps
Existence bugs rarely look like existence bugs. They look like a sheet added to the wrong workbook, a rename that fails because a chart sheet already had the name, or a macro that writes a month's figures into sheet number 3 because a cell held a number instead of text.
ExcelMaster lets you describe the job — "for each region in column A, reuse its sheet if it exists or create it" — and writes the check against the right workbook and the right collection, with the name passed as text, so the get-or-create logic does what it says.
Frequently asked questions
How do I check if a sheet exists in VBA?
There is no built-in method, so use a small function: switch error handling off, try
Set sh = wb.Sheets(name), switch it back on, and return Not sh Is Nothing. It finds worksheets and chart
sheets, visible or hidden, and ignores case the way Excel does.
How do I check if a sheet exists in another workbook?
Pass that workbook to the function, for example SheetExists("Rates", Workbooks("Prices.xlsx")). The
workbook has to be open. If it is closed, open it read-only, run the check, and close it again.
Is the sheet name check case-sensitive?
No. Excel treats Sales, SALES and sales as the same name, so the lookup through Sheets(name) is not
case-sensitive. If you loop and compare names yourself, use StrComp(a, b, vbTextCompare) or compare
LCase$ values to get the same result.
Why does my check say a sheet does not exist when I cannot add it?
Usually because the check searched Worksheets and the name is used by a chart sheet, which only appears in
Sheets. Names must be unique across both, so check against Sheets. A hidden sheet can also hold the name;
the check finds it, but you cannot see it in the tab strip.
Does a hidden sheet count as existing?
Yes. Hidden and very hidden sheets are still in the Sheets collection, so the check returns True for
them. If you need to know whether the user can see it, test sh.Visible = xlSheetVisible after the check.
Tested in
Tested in: Excel 365 (Windows 11), VBA 7.1 — last verified 2026-09-30.
Related guides: VBA Rename Sheet · VBA Hide Sheet · VBA Add Sheet · VBA Delete Sheet · VBA Worksheets · VBA On Error · VBA Like · VBA Open Workbook
