Settings

An .xlsx is a zip, and the sheets are only some of it

Rename a copy of a workbook to .zip and open it. A small test workbook built for this page holds these parts, among others:

xl/workbook.xml the sheet list, and the defined names xl/worksheets/sheet1.xml one part per sheet, visible or not xl/sharedStrings.xml every distinct piece of text in the book xl/calcChain.xml which cells hold formulas xl/comments1.xml cell notes, with the author on each one xl/pivotCache/pivotCacheDefinition1.xml xl/pivotCache/pivotCacheRecords1.xml docProps/core.xml author, last saved by, revision count docProps/app.xml editing time, company

Deleting something from the grid is a change to one of those parts. Several of the others are not touched by it.

Hidden, and the one nobody has heard of

Every sheet in the book appears in xl/workbook.xml as a <sheet> element with a name and a relationship id. A hidden sheet has one more attribute:

<sheet name="Summary" sheetId="1" r:id="rId1"/> <sheet name="Working" sheetId="2" state="hidden" r:id="rId2"/> <sheet name="Payroll" sheetId="3" state="veryHidden" r:id="rId3"/>

The attribute takes three values: visible, hidden and veryHidden. The first two behave as you would expect. A veryHidden sheet does not appear in the Unhide list, so nobody browsing the workbook in Excel finds it from the interface at all; it takes the VBA editor or unzipping the file. It was never meant as a security feature, and is routinely treated as though a sheet marked that way is gone.

It is not gone. The sheet's own part is still in the zip with every cell in it. X-RAY reports both of the test workbook's hidden sheets by name, and marks the second as very hidden.

The shape of data that was removed

Hidden rows and columns are one attribute each: <row r="4" hidden="1"> and a <col> entry with hidden="1" on it. The cells inside them are ordinary cells with ordinary values.

Two more things describe data that is no longer visible. The autofilter is stored as <autoFilter ref="A1:D40"/>, a range written when the filter was applied, and the print area is a defined name called _xlnm.Print_Area. Either can name a rectangle far larger than anything still on the sheet, which tells a reader how many rows there used to be.

Ordinary defined names do the same more directly. The test workbook carries two:

<definedName name="Redundancy_List">Payroll!$A$1:$D$40</definedName> <definedName name="Old_Bonus_Pool">Working!$F$1:$F$99</definedName>

The range may be long gone. The name is a sentence about what used to be in it, and it is sitting in xl/workbook.xml.

Text survives the cell it was in

Excel does not store text in the cell. It keeps one pool of strings for the whole workbook in xl/sharedStrings.xml, as a list of <si> items, and a cell that holds text is written as a type-s cell whose value is a position in that list:

<c r="A2" t="s"><v>3</v></c> means: the text at position 3 in sharedStrings

Clearing a cell removes the reference. Whether the entry itself goes depends on whether the application rebuilds the pool, and a pool item that no cell points at any more is still a valid file. The test workbook has one on purpose: item 8 reads Redundancy shortlist: Okafor, Beltran, Doyle, no cell in any sheet refers to it, and it opens in a spreadsheet application without complaint and shows nothing.

The same pool is shared with the sheets you deleted. This is exactly why CLEANSHEET rebuilds the table rather than leaving it: on the test file it walks the surviving sheets, keeps only the items they still reference, renumbers every cell's index to match, and the pool goes from nine items to six.

A number outlives the formula that made it

A formula cell holds two children: the formula and the last value it produced.

<c r="C2"><f>Payroll!D40*1.15</f><v>1264350</v></c>

The <v> is the cached result, kept so the file can be displayed without recalculating first. Remove the <f> and the number stays. That is deliberate when CLEANSHEET does it: the visible figures are untouched and the workings, including the reference to a sheet you would rather nobody knew about, come out.

Read the other way round, a cached value is evidence. A number computed from a sheet that is no longer in the workbook is still the number, and the formula beside it names the sheet, the cell and the multiplier.

xl/calcChain.xml is a companion to all this: a list of which cells hold formulas, by cell reference and sheet index. CLEANSHEET deletes it, because once the formulas are gone it would name cells that no longer calculate and Excel reads that as a damaged file. Excel builds it again on the next save.

The pivot cache, which is the one that catches people

A pivot table does not read the source rows when it draws itself. It reads a cache: a private copy of the source data, written into the workbook as its own parts. That is what makes a pivot fast, and what lets it keep working when the source is not open.

The copy is in two files. xl/pivotCache/pivotCacheDefinition1.xml names the source in a <worksheetSource> element, then lists every column as a <cacheField> with a <sharedItems> list of every distinct value in that column. xl/pivotCache/pivotCacheRecords1.xml then holds one <r> element per source row, with an <x> index into the shared items for text and an <n> for a number.

The pivot table part itself refers to the cache by cacheId. It never names the sheet. The link runs table to cache, and the cache remembers the sheet, which means deleting the sheet breaks nothing and removes nothing.

This was tested rather than assumed. The test workbook has a pivot table over a very hidden Payroll sheet of names, teams and salaries. The Payroll worksheet part was then deleted from the zip, along with its entry in the sheet list, its relationship and its defined name. Opened afterwards, the workbook has two sheets and no Payroll. Its pivot cache still says:

<worksheetSource ref="A1:D40" sheet="Payroll"/> refreshedBy="m.hollis" recordCount="4" saveData="1" Name Team Salary Priya Raman Legal 141500 Tom Okafor Legal 98250 Ana Beltran Finance 177000 Ken Doyle Finance 112400

Those four rows were read back out of the file by a standard spreadsheet library, not carved out by hand. The sheet is gone and the salaries are not. refreshedBy adds the name of whoever last refreshed the pivot.

What to do before you send a workbook

Look at it first. X-RAY unpacks the zip in the browser tab and reports the author, the account that saved it last, the revision count, the editing time, the company, and every hidden and very hidden sheet by name.

Then clean it. CLEANSHEET is the spreadsheet pass. On the test workbook it removed both hidden sheets and their parts, both defined names that pointed at them, the pivot table and both pivot cache files, xl/calcChain.xml, the comments part and the drawing that renders the note boxes; it froze the one formula to its cached value; and it rebuilt the shared string pool down to the six items still in use. It keeps the print area, because that one still refers to a sheet that is still there.

Check what the numbers are about. DATASCAN reads a CSV or JSON export and names the columns that look like personal data (emails, phone numbers, national insurance and social security numbers, card numbers, addresses), which is the question of whether the data should be leaving at all, rather than where it is hiding.

And check for credentials. SENTINEL reads every XML part inside the zip, not only the visible cells, so a key or a token sitting in a hidden sheet, an orphaned shared string or a pivot cache is in scope. It reports on Office files; it does not rewrite them.

Questions people ask about The data still in a spreadsheet you thought you deleted

What is a veryHidden sheet?

A worksheet whose state attribute in xl/workbook.xml is set to veryHidden rather than hidden. The difference is that it does not appear in Excel's Unhide list, so it cannot be brought back from the normal interface at all. The sheet and all of its data are still in the file.

Can someone see a spreadsheet's data after I delete the source sheet?

If there is a pivot table over it, yes. The pivot table keeps its own copy of the source rows in xl/pivotCache/pivotCacheRecords1.xml, and deleting the worksheet does not delete that part. This was tested on a workbook built for this page: with the source sheet removed from the zip, every source row was still read back out of the cache.

Why is deleted text still in sharedStrings.xml?

Because it is one pool of strings for the whole workbook, indexed by position, and cells refer to positions in it. Clearing a cell removes the reference. Whether the entry is dropped depends on whether the application rewrites the pool on save, and an entry nothing points at is a perfectly valid file that shows nothing on screen.

Does deleting a formula remove the number it worked out?

No, and that is usually what you want. A formula cell stores the formula and the last value it produced side by side, so removing the formula leaves the figure exactly as it was. It also means a number computed from a sheet that is no longer in the workbook stays behind after the sheet goes.

Is saving as CSV a safe way to strip all of this?

For one sheet, largely yes: a CSV is the values of one grid and nothing else, so hidden sheets, pivot caches, comments, the string pool and the document properties do not come with it. It also loses the formatting and every other sheet, and it does nothing about personal data in the rows themselves, which is a different question.

How do I check a workbook without opening Excel?

Copy it, rename the copy to .zip and unzip it. Open xl/workbook.xml and look at the state attribute on every sheet element and at the defined names. Then look at what parts are in the folder: anything under xl/pivotCache/ is a copy of somebody's source rows, xl/comments1.xml is the notes, and xl/sharedStrings.xml is every piece of text the book has ever held. It needs nothing installed and takes about a minute.

Related tools

More on this

All 13 guides under “What is in a file that you did not put there”. Part of the reading for HR and recruiting teams.

A letter, now and then

An occasional letter when there is something worth reading: the new guides and what changed in the tools. Never more than once a month and nothing else, and you can leave at any time on the unsubscribe page.