Back to Blog
Technical

Excel Hidden and Very Hidden Sheets: How the state Attribute in xl/workbook.xml Conceals Entire Worksheets Behind veryHidden That the Excel UI Cannot Reveal

A workbook can present three clean tabs and carry a dozen more you will never see by clicking around. Excel decides whether a sheet appears in the tab strip with a single word — the state attribute on each <sheet> element in xl/workbook.xml. Set it to hidden and the tab disappears but the right-click Unhide list still offers it back. Set it to veryHidden and the tab disappears and the Unhide list stays empty — a sheet that, by ordinary means, the recipient cannot even discover exists. Either way the sheet itself, with every value, formula, source range, and old draft on it, sits in the package fully intact. This post walks through where the flag lives, the difference between the two hidden states, what routinely ends up on concealed sheets, why hiding removes nothing from the file, why Document Inspector is an unreliable guard, and how to find and strip the sheets before a workbook leaves the building.

Technical Team
June 22, 2026
21 min read

One Word Decides Whether a Sheet Exists to the Reader

Every worksheet in a workbook is registered once in xl/workbook.xml, inside a <sheets> list. Each entry is a <sheet> element with a display name, an internal sheetId, a relationship r:id pointing at the part that actually holds the cells, and — only when the sheet is not visible — a state attribute. That single attribute is the entire mechanism. It does not move, encrypt, or shrink the sheet; it only tells the application whether to draw a tab for it.

There are three legal values. The default, written as visible or simply left off, draws the tab normally. hidden removes the tab but keeps the sheet in the user-facing Unhide dialog, so anyone can bring it back in two clicks. veryHidden removes the tab and withholds it from that dialog — a state that can only be set or cleared through VBA or by editing the XML directly. The data on the sheet is identical in all three cases. The only thing that changes is how hard the format works to keep the reader from noticing it is there.

Hidden Hides the Tab, Not the Data

Marking a sheet hidden or veryHidden changes one attribute in xl/workbook.xml. The worksheet part — every value, formula, and source range on it — remains in the package, byte for byte, and ships with the file.

Inside xl/workbook.xml

The sheet registry is small and readable. A workbook with three visible tabs and two concealed ones looks like this — the concealment is the one extra attribute, nothing more:

// xl/workbook.xml — the sheets list, two sheets the reader will never see

<sheets>

<sheet name="Summary" sheetId="1" r:id="rId1"/>

<sheet name="Dashboard" sheetId="2" r:id="rId2"/>

<sheet name="Client View" sheetId="3" r:id="rId3"/>

// these two have a state attribute — the reader never sees a tab

<sheet name="Cost_Model" sheetId="4" state="hidden" r:id="rId4"/>

<sheet name="Margin_Floor_DONOTSEND" sheetId="5" state="veryHidden" r:id="rId5"/>

</sheets>

Read what the registry hands over before anyone opens a single cell. There are five sheets, not three. One is named Cost_Model and one Margin_Floor_DONOTSEND — names the author chose for their own eyes, now legible to anyone who unzips the file. The r:id on each points through xl/_rels/workbook.xml.rels to the exact worksheet part holding the data, so finding the concealed content is a single hop away. The sheet name alone — like a defined name or a connection label — is often enough to tell a reader what they were not meant to find.

hidden vs veryHidden: Two Clicks Away, or Effectively Invisible

The gap between the two concealed states is the whole reason veryHidden matters. A hidden sheet is a courtesy hide: right-click any tab, choose Unhide, and it is listed there for the taking. Most recipients who suspect something is missing will find a hidden sheet in seconds. It protects against clutter, not against a curious reader.

A veryHidden sheet is different in kind. It does not appear in the Unhide dialog at all. There is no menu, no checkbox, no ribbon command in standard Excel that will reveal it. To an ordinary user it simply does not exist — which is precisely why developers use it to stash configuration, license logic, and scratch calculations behind a polished front end. The catch is that “cannot be revealed through the UI” is not “cannot be read.” The sheet is in the ZIP exactly like any other, and a text editor or a three-line script walks straight past the concealment the interface so carefully maintains.

“Very Hidden” Is a UI Promise, Not a Security Boundary

veryHidden only instructs the Excel interface not to offer the sheet for unhiding. It does not remove, encrypt, or restrict the worksheet part. Anyone who opens the file as a ZIP — or flips the attribute back in a few seconds — reads it in full.

What Routinely Ends Up on a Sheet Nobody Is Meant to See

Concealed sheets are not exotic; they are where the working machinery of a workbook is kept once the front tabs are made presentable. The recurring offenders are exactly the things an author would least like to forward:

  • Lookup and master-data tables. The list of customers, the rate card, the employee roster, or the product catalogue that the visible dropdowns and VLOOKUP formulas pull from — the same internal picklists that also surface through data validation lists.
  • Cost and margin engines. A sheet that computes the floor price, the internal cost, or the discount ceiling behind a clean quote — the numbers the recipient is negotiating against, sitting one attribute away from view.
  • Old drafts and scratch work. A prior version of the model, a sheet of half-finished calculations, or a copy kept “just in case” and hidden rather than deleted — preserved in full alongside the polished result.
  • Assumptions and scenario inputs. The growth rates, attrition figures, and what-if toggles that drive the headline numbers, hidden so the dashboard looks authoritative rather than provisional.
  • Other parties’ data. When a template is reused across clients, the previous client’s figures are often left on a hidden sheet rather than cleared — one recipient receiving another’s confidential numbers.

The visible tabs are the report; the concealed ones are how it was made. Forwarding the file ships both. And because the formulas on the visible sheets frequently reference the hidden ones by name — =Cost_Model!B12 — the front of the workbook openly cites the back, telling a reader a hidden sheet exists and exactly what it is called even before they go looking for it.

The Visible Sheets Point Straight at the Hidden Ones

Concealment fails most completely when the rest of the workbook keeps referring to what is concealed. A hidden sheet that nothing references is at least quiet; a hidden sheet wired into the live model announces itself from every direction. The trails are everywhere:

  • Cross-sheet formulas. Any =Margin_Floor_DONOTSEND!A1 on a visible sheet names the hidden sheet in plain text and shows what it is used for.
  • Defined names. A named range scoped to a hidden sheet appears in the defined-names table with the sheet name in its refersTo, fully legible regardless of the sheet’s state.
  • Validation and chart sources. Dropdowns and chart series often draw their values from a hidden sheet, recording the reference in the worksheet and chart parts — alongside the cached values those layers keep, as with chart caches.
  • The calculation chain. The calcChain part enumerates every formula cell across the whole workbook, hidden sheets included, mapping the dependency web without regard to which tabs are drawn.

Hiding Removes Nothing From the Package

The intuition that makes hidden sheets dangerous is the belief that hiding is a kind of deletion — that an out-of-sight sheet is, for practical purposes, gone. It is not. The worksheet lives in its own part, typically xl/worksheets/sheet5.xml, and that file is present in the ZIP whether the sheet is visible, hidden, or very hidden. Setting the state attribute touches xl/workbook.xml and nothing else.

That means every defence people imagine they have applied is illusory. Hiding a sheet does not strip its formulas. It does not flatten its values. It does not break the references the rest of the workbook makes to it. It does not remove it from the shared-strings table that pools every text value in the file, so even the words on a very-hidden sheet sit in the same plain-text vocabulary as everything else. The sheet is exactly as readable as the front page; it simply has no tab.

A Three-Tab Workbook Can Carry a Dozen Sheets

The tab strip is a rendering of the visible sheets, not an inventory of the file. Count the <sheet> elements in xl/workbook.xml and the xl/worksheets/ folder, not the tabs, to know how many worksheets you are actually sending.

Finding Hidden and Very-Hidden Sheets Without Excel

Surfacing the layer needs only a ZIP reader and an XML parser. Listing every sheet with its visibility state takes a few lines and never opens Excel — and crucially, it lists the veryHidden sheets the application itself refuses to show:

# list every sheet and its visibility state, very-hidden included

import zipfile

from lxml import etree

def local(t): return t.rsplit("&rbrace;", 1)[-1]

with zipfile.ZipFile("workbook.xlsx") as z:

root = etree.fromstring(z.read("xl/workbook.xml"))

for s in root.iter():

if local(s.tag) != "sheet": continue

state = s.get("state", "visible")

print(f"{state:<10} {s.get('name')}")

For a quick manual check, renaming the file to .zip, expanding it, and opening xl/workbook.xml shows the full sheet list with every state in seconds — the same trivial unzip-and-read move that also exposes the data-connection store and the hyperlink relationship records. Anyone who can rename a file can enumerate every sheet you thought you had concealed.

What an Investigator Reconstructs From the Concealed Sheets

From a single sweep through a workbook’s sheet registry and the parts behind it, a reader typically extracts:

  • The true sheet count and the names of every concealed sheet — names that frequently editorialise, from DONOTSEND to old_ to a client’s name left on a reused template.
  • The full contents of lookup tables, rate cards, and master data the visible sheets only sample from.
  • The cost, margin, and assumption engines behind clean headline numbers, complete with their formulas.
  • Prior drafts and scratch versions hidden rather than deleted, documenting how the final figures were reached.
  • Cross-references from visible sheets that name the hidden ones and reveal what each is for.
  • Another party’s confidential data stranded on a hidden sheet when a template was recycled.

Taken together, the concealed sheets often hold more than the visible ones — they are the inputs, the workings, and the history that the presentable front tabs are designed to summarise and smooth over. For anyone reviewing a workbook adversarially, the hidden sheets are the first place worth looking.

Why Document Inspector Is an Incomplete Guard Here

Hidden sheets are one of the areas Document Inspector does address — its “Hidden Worksheets” check can find and remove sheets in the hidden state. That is genuinely useful, but it comes with two large caveats that turn it into false confidence if relied on alone.

First, the inspector historically does not remove veryHidden sheets — the very state most likely to hold the things an author most wants concealed. A sheet hidden the ordinary way may be flagged and stripped while the very-hidden sheet beside it is passed over entirely. Second, the check is opt-in and inconsistent across versions and platforms; a workbook can be saved, sent, and never inspected at all. The result is the familiar blind spot: a file can clear the checks a user did run and still ship a very-hidden sheet full of cost models — the same gap that leaves custom XML parts and defined names in place.

The Inspector’s Hidden-Sheet Check Skips the Worst Case

Document Inspector can remove ordinary hidden sheets but typically leaves veryHidden ones in place. Passing the inspector is not evidence that every concealed sheet is gone — it is evidence that the easy ones are.

How to Actually Find and Remove Concealed Sheets

The goal is a delivered workbook whose xl/workbook.xml lists only the sheets you intend the recipient to have, with no hidden or veryHidden survivors and no orphaned worksheet parts. The realistic options, in increasing order of reliability:

  • Enumerate, then unhide everything, then decide. Use VBA or a script to set every sheet’s state to visible so you can actually see what is in the file — including the very-hidden sheets the Unhide dialog refuses to list — then delete the ones that should not ship. You cannot make a decision about a sheet you cannot see.
  • Delete the sheets, do not re-hide them. For external release, remove the concealed sheets outright rather than confirming they are hidden. A deleted sheet’s part is dropped from the package; a hidden one is not. Then fix any #REF! errors the deletion surfaces on the visible sheets — those errors are the visible model telling you what it was quietly pulling from the hidden one.
  • Round-trip the visible sheets into a clean copy. Copy only the sheets the recipient should have into a brand-new workbook and paste as values where the formulas referenced concealed data. Because the new file never contained the hidden sheets, it cannot leak them — the same flatten-into-a-fresh-file move that reliably sheds other embedded layers.

Whichever path you take, verify by re-opening the delivered file as a ZIP and confirming that xl/workbook.xml lists exactly the sheets you meant to send and that the xl/worksheets/ folder holds no more parts than that. A workbook that merely shows the right tabs is not a workbook that contains only the right sheets.

Pre-Share Hidden-Sheet Checklist

  • Count the <sheet> elements in xl/workbook.xml and compare to the tabs you can see — a mismatch means concealed sheets.
  • Read the state attribute on every sheet and treat any veryHidden value as a deliberate concealment to investigate.
  • Unhide every sheet — via VBA or by editing the XML — so you can see what is actually in the file before deciding what ships.
  • Read the concealed sheets for lookup tables, cost models, old drafts, assumptions, and another party’s leftover data.
  • Delete the sheets that should not leave the building rather than re-hiding them, and resolve the resulting reference errors on the visible sheets.
  • Do not trust Document Inspector alone — it skips very-hidden sheets and may not be run at all.
  • Verify by re-opening the final file as a ZIP and confirming xl/workbook.xml and xl/worksheets/ contain only the intended sheets.

Hidden Sheets as Part of a Coordinated Cleanup

A concealed sheet rarely travels alone. The lookup table on it usually backs data-validation dropdowns on the visible sheets; its values are pooled into the same shared-strings table as everything else; its formula cells are catalogued in the calculation chain; and a defined name may point straight at it. Removing the sheet while leaving those siblings populated can shed the obvious copy and keep several echoes. A workbook is only sheet-clean when the concealed sheets, the names and validations that reference them, and the caches built from their data are handled in one pass.

The broader lesson is the one this series keeps returning to: a workbook is a package of cooperating parts, and what the interface chooses to draw is not the same as what the file contains. The tab strip is a curated view; the sheet registry is the truth. Three clean tabs can sit in front of a cost model, a rate card, and last quarter’s draft — each a full worksheet in the package, each one attribute away from visible, each readable by anyone who unzips the file.

The Tab Strip Is a Curtain, Not a Wall

Hiding a sheet was meant to be housekeeping — a way to keep helper tabs out of sight so a report reads cleanly. The state attribute does exactly that and nothing more: it asks the interface not to draw a tab. It does not ask the format to forget the sheet, and the format does not. Behind every very-hidden tab is a complete worksheet, with its values, its formulas, and the references that wire it into the visible model — all in plain XML, all one unzip away.

For workbooks that stay inside the team, hidden and very-hidden sheets are exactly the convenience they were built to be: the working parts kept tidily out of the way. For workbooks crossing the perimeter, they are the inputs, the workings, and the history the author assumed had been left behind. The only durable defences are to enumerate every sheet regardless of state, delete the ones that should not ship rather than re-hiding them, and verify against the sheet registry — and to remember that in this format, the tabs you can see were never the same thing as the sheets you are sending.

Audit the Hidden Sheets in Your Workbooks

Use MetaData Analyzer to enumerate every worksheet in your files regardless of visibility state, surface hidden and very-hidden sheets the Excel interface refuses to list, read the names and contents of concealed lookup tables, cost models, and leftover drafts, flag sheets the visible model still references, and confirm no workbook is shipping a sheet you meant to keep before it leaves the organisation.