Long before real-time co-authoring, Excel let several people edit one file at once through a feature called Share Workbook. To merge their edits it had to remember them — so it wrote a complete change journal into xl/revisions/. That journal records every cell that changed, the value it held before and the value it holds after, the name of the person who changed it, the machine they were on, and the exact second it happened. The feature is buried in modern menus and largely replaced by co-authoring, yet shared workbooks still circulate by the million, and every one of them carries this audit trail in plain XML — including values that were later overwritten, cells later cleared, and changes the author thought they had rejected. This post walks through where the revision store lives, what a single edit leaks, how the log reconstructs an entire editing timeline with names attached, why Document Inspector misses it, and how to actually strip it before a workbook leaves the perimeter.
The Share Workbook feature solved a problem that predated the cloud: how do you let three people open the same .xls on a network drive at once and reconcile their edits when they save? Excel’s answer was to keep a per-user change log. When you save, Excel compares your copy against the shared baseline, writes down each difference, and merges it — resolving conflicts by asking whose value wins. To do any of that it must store, for every change, what the cell used to contain and what it contains now. That before-and-after pair is the whole point of the mechanism, and it is exactly the thing you would never want to ship to an outsider.
The modern ribbon hides Share Workbook behind legacy commands, and Microsoft now steers everyone toward co-authoring in OneDrive and SharePoint — which carries its own metadata risks. But the legacy feature was never removed. Workbooks created or shared with it still circulate, get forwarded, get re-saved, and quietly carry their revision store with them. While a workbook is shared, that store lives in a dedicated folder inside the XLSX package: xl/revisions/.
A shared workbook keeps a journal of every edit — old value, new value, author, and timestamp — because merging changes requires it. That journal is written to xl/revisions/ in plain XML, and it travels with the file whether or not anyone ever opens the change history.
The revision store separates the index from the entries. xl/revisions/revisionHeaders.xml is the table of contents: one <header> element per save-and-merge session, each stamping that session with a globally unique id, the editing user’s name, and the exact moment they saved. Each header points, by relationship, to a numbered log part — revisionLog1.xml, revisionLog2.xml, and so on — that holds the actual changes made in that session.
// xl/revisions/revisionHeaders.xml — one entry per editing session
<headers xmlns="...spreadsheetml/2006/main" guid="{3F2A...}">
<header
guid="{7C11-...}"
dateTime="2026-03-14T09:42:11"
maxSheetId="4"
userName="Jane Okafor (Finance)"
r:id="rId1">
<sheetIdMap count="4"> ... </sheetIdMap>
</header>
</headers>
The userName attribute is whatever string was set as the user name in that copy of Excel — often a full name and department, sometimes an email, sometimes a machine login. The dateTime is a precise local timestamp. Already, before reading a single cell change, the header list alone reconstructs who touched the file and when, session by session — the same kind of timeline that timeline reconstruction assembles from scattered timestamps, except here it is handed over pre-sorted and pre-attributed.
The substance lives in the log parts. Each cell edit is a <rcc> element — a revision cell change — carrying a revision id and the sheet id it applies to. Inside it sit two children that are the heart of the disclosure: <oc>, the old cell, and <nc>, the new cell. Each is an ordinary cell element with a reference and a value. The log literally stores the value that was there before the edit next to the value that replaced it:
// xl/revisions/revisionLog1.xml — one edit, both values preserved
<revisions xmlns="...">
<rcc rId="1" sId="2">
<oc r="D14"><v>1200000</v></oc>
<nc r="D14"><v>1850000</v></nc>
</rcc>
// a text edit — the old wording is kept verbatim
<rcc rId="2" sId="1">
<oc r="B3" t="inlineStr"><is><t>Tentative — do not circulate</t></is></oc>
<nc r="B3" t="inlineStr"><is><t>Final figures</t></is></nc>
</rcc>
</revisions>
Read that second change again. The cell on the delivered sheet says Final figures. The revision log preserves what it said before: Tentative — do not circulate. The recipient sees the polished version; the file carries the candid one. A single forecast cell discloses the figure was revised upward from 1.2M to 1.85M, by whom, and when. This is the same hazard as the shared-strings table preserving deleted text, except the revision log goes further: it pairs the deleted value with its replacement and stamps the pair with an author and a time.
Every <rcc> stores the old cell and the new cell side by side. Overwriting a number does not erase the original — it files it in revisionLog*.xml next to the value that replaced it, attributed and timestamped through its header.
Cell edits are only one kind of revision. The log records the full grammar of structural change so a merge can replay it. Alongside <rcc> you find:
<rrc> — row/column inserts and deletes. When someone deletes a row, the revision preserves the action and frequently the contents of what was removed, so a column of figures someone deleted to “tidy up” can be read straight out of the log.<rm> — cell moves. Records the source and destination range of a cut-and-paste, mapping how data was rearranged.<ris> and <rsnm> — sheet inserts and renames. A sheet renamed from Q3 layoffs model to Q3 plan keeps both names in the rename revision.<rfmt> — formatting changes. Even style edits are logged, which can reveal that a cell was once flagged with a warning fill or a bold “review” format.Each of these carries the same chain of attribution: the revision belongs to a log part, the log part belongs to a header, and the header names a person and a moment. The combined effect is that the structural shape of the workbook’s history — which sheets existed, what they were called, what rows were added and removed — is reconstructible, not just the cell values. A deleted sheet that leaves traces in defined names can leave a far more complete record here.
A shared workbook also keeps a list of everyone with the file open. The user roster — stored in xl/revisions/userNames.xml and surfaced through the legacy “Who has this workbook open now” dialog — records each participant’s display name and a per-user id that ties their identity to the changes they made. Combine the roster with the headers and every revision in the log resolves to a named human being, not an anonymous edit.
The mechanism goes one level deeper still. When two people changed the same cell, Excel had to record the conflict so it could ask which value to keep. That means the log can preserve not only the value that won but the competing value that was discarded — a candid snapshot of disagreement. If one analyst entered a revenue figure and a manager overrode it, both numbers can sit in the revision store, each tagged to its author. The delivered sheet shows one number; the file remembers the argument.
The header list and userNames.xml together attribute each revision to a specific named editor. The result is a built-in org chart of who worked on the file, what each of them changed, and where two of them disagreed.
The dangerous property of the revision store, exactly as with pivot and chart caches, is that it is decoupled from the visible state of the grid. Several actions that feel like erasing a value leave it sitting in the log:
<oc> element. Nothing on the grid hints that the prior figure is still recoverable.In every case the author performs an action that looks like removing data and concludes the workbook is clean. The visible grid agrees with that belief, which is exactly why the logged value — in a folder nobody opens — is so easy to ship by accident. It is the same trap as the pivot cache surviving the deletion of its source sheet, but applied to the entire editing history rather than one dataset.
Reconstructing the full edit timeline needs only a ZIP reader and an XML parser. Pairing the author and timestamp from each header with the before-and-after values in its log part replays the entire history directly from the package:
# dump every logged edit: who, when, old value -> new value
import zipfile, re
from lxml import etree
def local(t): return t.rsplit("}", 1)[-1]
with zipfile.ZipFile("workbook.xlsx") as z:
logs = [n for n in z.namelist() if re.match(r"xl/revisions/revisionLog\d+\.xml", n)]
for name in logs:
root = etree.fromstring(z.read(name))
for rcc in root.iter():
if local(rcc.tag) != "rcc": continue
old = rcc.find(".//" + "{*}oc")
new = rcc.find(".//" + "{*}nc")
ov = "".join(old.itertext()) if old is not None else "(empty)"
nv = "".join(new.itertext()) if new is not None else "(empty)"
print(f"{ov!r} -> {nv!r}")
Joined to revisionHeaders.xml for the userName and dateTime of each session, this produces a clean ledger of every edit with full attribution. For ad-hoc inspection, renaming the file to .zip, expanding it, and grepping xl/revisions/ for <oc> surfaces every superseded value in seconds — the same trivial unzip-and-read move that also exposes the chart caches and the hyperlink relationship records.
From a single sweep through the revision store of a shared workbook, a reader typically extracts:
userNames.xml, with each change attributed to a specific person.Taken together, these reconstruct not a static snapshot but a movie of the workbook’s creation: who changed what, to what, when, and over whose objection. Few other parts of the file disclose intent and authorship so completely — the revision log was engineered to remember exactly the things a careful sender would want forgotten.
Excel does have a relevant safeguard, but it is conditional and easy to defeat. When you turn off sharing — or run Document Inspector against a shared workbook — Excel will offer to discard the change history, and the “keep change history for N days” setting (30 by default) means old revisions are meant to age out. In principle, a workbook whose sharing is properly turned off should shed its revision store.
In practice, the guard fails in the ways that matter. The history is only cleaned when sharing is deliberately switched off through the right command; a file forwarded while still shared carries its full log untouched. Document Inspector flags the personal information and history only while the file is in the shared state it knows how to inspect, and many conversions, third-party exports, and automated pipelines copy the xl/revisions/ parts verbatim without ever triggering the cleanup. The retention window is a default that an administrator or a determined user can extend to keep history far longer. The net effect is that “I ran Document Inspector” is no guarantee the revision store is gone — the same false confidence the inspector creates around custom XML parts and printer settings.
Excel only discards the revision store when sharing is explicitly turned off in the right way. A shared workbook that is simply forwarded, exported, or re-saved by another tool keeps its complete change history — and the recipient inherits every superseded value, name, and timestamp.
The goal is to deliver a workbook with no xl/revisions/ folder and no lingering shared-workbook flag. The realistic options, in increasing order of reliability:
xl/revisions/ part (the headers, the numbered logs, and userNames.xml), remove the <fileSharing> element and the shared-workbook flag from xl/workbook.xml, and prune the matching relationships and [Content_Types].xml entries — a complete pass, not just a UI toggle.Whichever path you take, verify by re-opening the delivered file as a ZIP and confirming the xl/revisions/ folder is absent. A workbook that merely looks unshared in the title bar can still carry the store if it was cleaned by an unreliable route. The only state worth shipping is one where the folder does not exist at all.
xl/revisions/ folder and a <fileSharing> entry in xl/workbook.xml.revisionLog*.xml for superseded values; confirm no <oc> holds a figure or note that should not leave the building.userNames.xml for editor names that disclose who worked on the file.xl/revisions/ folder is gone entirely.The revision store rarely travels alone. The same superseded values it preserves are often also frozen in the shared-strings table wherever they were typed, summarised in a pivot cache if a pivot used them, and the editor names it lists often reappear in legacy comment author tables and threaded-comment personas. Stripping the revision store while leaving those siblings populated removes one copy of the history and ships several echoes of it. A workbook is only revision-clean when the logs, the user roster, the sharing flag, and every parallel store of the same values and names 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 the same information is frequently stored in several of them at once. A shared workbook looks like an ordinary file — one current value per cell, one name in the title bar. In the format it is a fully attributed, timestamped journal of every edit anyone ever made, sitting in plain XML in a folder the recipient need only unzip to read.
Share Workbook was meant to be the convenient way for a team to edit one file together before the cloud made it easy — type your changes, save, and let Excel merge everyone’s work. The revision log quietly inverts that convenience for anyone forwarding the file. Behind every current cell is the value it replaced; behind every edit is the person who made it and the second they did; behind every “final” figure is the draft it was promoted from and, sometimes, the colleague who disagreed. None of it shows in the rendered grid, and none of it is reliably removed by forwarding the file, deleting a sheet, or trusting that Document Inspector ran.
For workbooks that stay inside a team, the change history is exactly what it was built to be: the record that lets several people edit one file without losing each other’s work. For workbooks crossing the perimeter, it is a fully attributed, dated confession the author thought they had reduced to a clean set of final numbers. The only durable defences are to turn sharing off deliberately and verify, or to flatten the live values into a fresh, never-shared workbook — and to remember that in this format, the number in the cell was never the whole story. The history behind it is.
Use MetaData Analyzer to detect shared-workbook revision stores across your files, read every superseded value behind the current grid, reconstruct the full editing timeline with names and timestamps attached, surface deleted rows and renamed sheets captured in the log, and confirm no workbook is shipping an edit history you never meant to disclose before it leaves the organisation.
Another layer where deleted text survives — the revision log goes further by pairing each old value with its replacement, author, and time.
The cloud successor to Share Workbook — the same attribution and history risks, moved into co-authoring and version history.
How scattered timestamps rebuild a document’s history — the revision log hands that timeline over pre-sorted and pre-attributed.