Back to Blog
Technical

Excel Legacy Cell Comments and VML Drawings: How xl/comments*.xml and xl/drawings/vmlDrawing*.vml Preserve Author Names, Hidden Note Boxes, and Positioning Metadata the Threaded-Comment Era Left Behind

When an Excel user right-clicks a cell and chooses Insert Comment in older builds — or Insert Note in current ones — the workbook gains entries in two cooperating XML parts. The first is xl/comments1.xml, which stores the note text, the cell reference, and an <authors> table that records every commenter name verbatim. The second is xl/drawings/vmlDrawing1.vml, a fragment of vintage Vector Markup Language that describes the floating yellow note box: its size, its anchor, its colours, and crucially whether it is shown or hidden. This is the legacy comment system — distinct from the modern threaded comments stored in xl/threadedComments/ — and it is still produced, still hidden by default, and still routinely shipped with the original author’s name attached. This post walks through where the layer lives, what each part leaks, why hidden notes are not gone, why deletion orphans shapes and authors, and how to actually strip both parts before workbooks leave the perimeter.

Technical Team
May 23, 2026
21 min read

Two Comment Systems, and This Is the Old One

Modern Excel ships two parallel comment systems, and they store their data in completely different places. The newer one — covered in detail in our piece on threaded comments and persona IDs — writes conversational replies to xl/threadedComments/ and resolves each commenter to a Microsoft 365 identity in xl/persons/person.xml. The older one, which Microsoft now labels Notes in the ribbon but which the file format still calls comments, predates co-authoring entirely. It stores its text in xl/comments1.xml and the geometry of its yellow pop-up box in xl/drawings/vmlDrawing1.vml. The two systems are not mutually exclusive: a single workbook frequently carries both, because notes created years ago in a desktop build sit alongside threaded comments added later in the browser.

The legacy layer matters for metadata hygiene because almost everyone has forgotten it exists under its old name. Cleanup advice that says “remove the threaded comments” misses it entirely. Document Inspector treats it as a separate category. And because notes are hidden by default — they only appear when you hover the little red triangle in a cell corner — authors routinely leave candid remarks in them under the assumption that no recipient will ever look.

Notes Are Comments in the File Format

What the current ribbon calls a Note is what the XLSX format calls a comment, stored in xl/comments*.xml. What the ribbon calls a Comment is the newer threaded system in xl/threadedComments/. The naming flipped around 2019; the file format did not. A workbook can carry both, and a cleanup that only knows about one ships the other.

Inside xl/comments1.xml: Text and the Authors Table

The comments part has a simple, durable structure. It opens with an <authors> table — a flat list of every distinct commenter name — followed by a <commentList> in which each comment references an author by zero-based index and pins itself to a cell:

// xl/comments1.xml — authors table plus comment list

<comments xmlns="...spreadsheetml/2006/main">

<authors>

<author>ACME\j.maller</author>

<author>Priya Desai</author>

<author>External Reviewer (Big Four)</author>

</authors>

<commentList>

<comment ref="D14" authorId="0">

<text><r><t>placeholder — real number is in the CFO copy</t></r></text>

</comment>

<comment ref="F22" authorId="2">

<text><r><t>cannot support this assumption without the underlying contract</t></r></text>

</comment>

</commentList>

</comments>

Three things leak from that one fragment. The authors table records names exactly as Excel captured them — here a Windows domain login (ACME\j.maller), a full personal name, and a self-described external reviewer. The comment text carries candid editorial remarks: an admission that the visible number is a placeholder and the real figure lives in a separate CFO copy, and an external auditor refusing to support an assumption. And the authorId index ties each remark to a specific person, so a reader can attribute every note even though the rendered comment box usually shows only the text.

The Authors Table Is a Roster

The <authors> list captures the name Excel had for each commenter at the moment the note was created — a domain login, a display name, or whatever was typed into the username field. It survives independently of the comment text and is the single most reliable identity artefact in the legacy layer. Even a workbook whose notes look anonymous in the UI names every contributor in plain XML.

The VML Drawing: Geometry, Colour, and the Hidden Flag

The comment text alone is not a renderable note — Excel needs to know where the yellow box sits, how big it is, and whether it is currently visible. That information lives in a separate, much older format: Vector Markup Language, a pre-SVG vector dialect Microsoft retired everywhere else but kept alive specifically for legacy comments. Each note has a matching <v:shape> in xl/drawings/vmlDrawing1.vml:

// xl/drawings/vmlDrawing1.vml — the floating note box

<v:shape type="#_x0000_t202" style="...visibility:hidden">

<v:fill color2="#ffffe1"/>

<x:ClientData ObjectType="Note">

<x:MoveWithCells/>

<x:SizeWithCells/>

<x:Anchor>3, 15, 13, 4, 6, 31, 16, 1</x:Anchor>

<x:AutoFill>False</x:AutoFill>

<x:Row>13</x:Row>

<x:Column>3</x:Column>

</x:ClientData>

</v:shape>

The visibility:hidden in the style string is the toggle behind Show/Hide Comment. The <x:Row> and <x:Column> values are the zero-based anchor cell, so the VML shape independently records which cell a note belongs to even when the comments part is read separately. The <x:Anchor> tuple is the box geometry in column/row/offset units. None of this is the note text, but all of it is metadata: it tells a reader the layer exists, how many notes there are, which cells they target, and whether the author left them visible or tucked away.

Hidden Is Not Gone: The Show/Hide Illusion

The defining property of a legacy note is that it is hidden by default. A cell with a note shows only a small red triangle in its top-right corner; the box appears on hover or when the author explicitly pins it open with Show Comment. Authors internalise this as “the note is out of the way” and write accordingly. But hiding a note flips a single visibility attribute in the VML shape. The text in xl/comments1.xml is identical whether the box is shown or hidden. From a metadata-extraction standpoint, the show/hide state is irrelevant: a script reads the text the same way regardless.

This produces a predictable failure mode. A reviewer scrolls a worksheet, sees no open comment boxes, concludes the sheet has no notes, and ships it. The red triangles are easy to miss against busy formatting, and on a sheet with frozen panes or hidden rows they may not be visible at all. Meanwhile the comments part holds every candid remark anyone ever attached. The same pattern recurs across the format — it is the comment-layer equivalent of the shared-strings table preserving deleted cell contents: invisible in the grid, fully present in the XML.

Hiding a Note Changes One Attribute

Hide Comment sets visibility:hidden on the VML shape and nothing else. The note text stays byte-for-byte in xl/comments*.xml. Reviewing a workbook visually will never surface a hidden note; only reading the comments part will. Treat every red triangle — and every note you cannot see — as text on its way to the recipient.

What Authors Actually Write in Notes

Because notes feel ephemeral, they collect the candid commentary that never makes it into a cell. Across real-world workbooks the recurring categories are remarkably consistent:

  • Source admissions. “hard-coded — finance hasn’t confirmed,” “plug to make it tie,” “estimate, replace before board.” Each one flags a number the author does not trust.
  • Internal disagreements. “Mike thinks this is too aggressive,” “legal pushed back on this wording,” “don’t show this tab to the client.”
  • Identity and process leaks. Names of people not otherwise in the file, approval chains, and references to other documents and systems.
  • To-do residue. “ask Priya for the real margin,” “update after Q3 actuals,” “remove this note before sending” — an instruction that, ironically, is itself the note that got shipped.

The metadata value is that notes are written in a register no one uses for cell content. They are unguarded. A reader who extracts the comments part of a deal model frequently learns more about how much the author trusts their own numbers than they would from any amount of formula auditing.

Orphan Shapes and Orphan Authors

Deleting a note is a two-part operation that Excel does not always complete cleanly. Removing the comment should drop the <comment> element from xl/comments1.xml and the matching <v:shape> from the VML drawing. In practice several workflows leave one half behind. Round-tripping through a third-party library, copy-pasting cells with notes between sheets, or editing in one application and saving in another can leave a VML shape with no corresponding comment, or — more usefully to an investigator — an author entry in the <authors> table that no surviving comment references.

An orphan author is durable evidence that a contributor once left a note that has since been deleted. Excel almost never compacts the authors table, because author indices are positional — removing an entry would renumber every comment that follows. So the safe behaviour, and the one Excel usually takes, is to leave the deleted commenter’s name in the table forever. A workbook whose visible notes are all from one person can carry an authors table listing five, quietly documenting four reviewers whose comments were removed.

// authors table retains names no surviving comment references

<authors>

<author>Priya Desai</author> <!-- authorId 0, used -->

<author>ACME\d.okafor</author> <!-- authorId 1, ORPHAN -->

<author>contractor_temp</author> <!-- authorId 2, ORPHAN -->

</authors>

Deleting a Note Rarely Deletes the Name

Because author indices are positional, Excel leaves deleted commenters in the <authors> table rather than renumbering. A workbook that looks like it has one reviewer can name every person who ever touched the notes — including contractors and people who have since left. Compare the indices used by surviving comments against the full authors list to find the orphans.

How the Parts Wire Together

Three relationships hold the layer together, and any cleanup has to respect all three or it produces a workbook Excel complains about on open. The worksheet’s rels file (xl/worksheets/_rels/sheet1.xml.rels) carries a relationship of type comments pointing at ../comments1.xml and a relationship of type vmlDrawing pointing at ../drawings/vmlDrawing1.vml. The worksheet XML itself carries a <legacyDrawing r:id="..."/> element that names the VML relationship. And [Content_Types].xml declares the content types for both the comments part and the vml default extension.

This four-point wiring — comments part, VML part, two rels entries, the <legacyDrawing> pointer, and the content-type registrations — is why amateur cleanup tends to break files. Delete the comments part but leave the rels entry, and Excel reports the workbook as corrupt and offers to repair it. Leave the VML part but delete the comments, and the red triangles vanish while the orphan shapes linger. Reliable removal walks all of these in one coordinated pass, exactly as the hyperlink layer requires touching both the worksheet block and its rels file.

Reading the Layer Without Excel

Enumerating legacy notes needs only a ZIP reader and an XML parser. Walking every xl/comments*.xml part and joining each comment to its author by index produces an attributed list of every note in the workbook:

# dump every legacy note with its author and cell

import zipfile, re

from lxml import etree

SS = "http://schemas.openxmlformats.org/spreadsheetml/2006/main"

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

for name in z.namelist():

if not re.match(r"xl/comments\d+\.xml", name):

continue

tree = etree.fromstring(z.read(name))

authors = [a.text for a in tree.iter(f"{{SS}}author")]

for c in tree.iter(f"{{SS}}comment"):

who = authors[int(c.get("authorId"))]

txt = "".join(c.itertext()).strip()

print(c.get("ref"), who, repr(txt))

The script prints one line per note: the cell, the resolved author name, and the text. To surface orphan authors, diff the set of indices actually used by comments against range(len(authors)) — any index never used is a deleted commenter still named in the table. For ad-hoc inspection, renaming the file to .zip, expanding it, and grepping xl/comments*.xml for <author> and <t> surfaces the whole layer in seconds — which is exactly what an opportunistic recipient does the moment a workbook lands.

What an Investigator Reconstructs From the Layer

From a single sweep through the legacy comment layer of a moderately-used workbook, a reader typically extracts:

  • A roster of every commenter from the <authors> table, frequently including domain logins that reveal the username convention.
  • Candid editorial remarks — placeholders, plugs, disagreements, and “don’t share this” warnings — from the note text.
  • Names of people not otherwise present in the workbook, mentioned inside notes.
  • Orphan authors who left deleted notes, recovered from unused author indices.
  • Which cells the author considered uncertain enough to annotate, from the comment ref attributes.
  • Whether notes were left visible or hidden, from the VML visibility flags — a hint at how private the author believed them to be.
  • A rough chronology, when legacy notes coexist with threaded comments: the legacy layer is almost always the older one.

The first four categories are identity and candid content; the last three are process and timeline. Together they routinely reveal more about how a workbook was built — and how much its author trusted it — than the cell values do.

Why Document Inspector Handles It Asymmetrically

Microsoft’s Document Inspector does have a Comments and Annotations check, and on the desktop it will remove legacy notes when run. But the coverage has well-known gaps. The check is a separate item from the threaded-comments check, so users who clear one frequently believe they have cleared both. On Mac builds and in several online and mobile contexts the comment-removal scope differs from the Windows desktop, and notes that one platform strips another leaves in place — the same cross-platform inconsistency we documented for Document Inspector gaps between Mac and Windows. And the inspector operates on the workbook as Excel models it in memory; orphan VML shapes and orphan author entries that Excel no longer associates with a live comment are not always part of that model and can survive the pass.

The result matches the pattern across the whole format: the inspector handles the headline case — visible notes attached to live comments — and trusts the user not to care about the residue. A workbook “inspected and cleaned” routinely still ships orphan author names and orphan VML shapes, and a workbook cleaned of Comments in the modern sense routinely still ships every legacy Note.

“No Comments” and “No Notes” Are Different Claims

Clearing threaded comments does nothing to legacy notes, and vice versa. Document Inspector treats them as separate checks, splits coverage across platforms, and does not reliably reach orphan shapes or orphan author entries. If your share workflow stops at one inspector pass, assume the other comment layer — and its residue — is still in the file.

How to Actually Strip the Layer

Reliable cleanup operates at the package level and removes all four wiring points in one coordinated pass. For a workbook bound for external release the minimum sweep deletes every xl/comments*.xml part, deletes every xl/drawings/vmlDrawing*.vml part that exists solely to back notes, removes the comments and vmlDrawing relationships from each worksheet’s rels file, removes the <legacyDrawing> element from each worksheet, and drops the now-unused content-type declarations from [Content_Types].xml:

# remove the legacy comment layer end-to-end

# 1. drop every xl/comments*.xml part

# 2. drop every note-only xl/drawings/vmlDrawing*.vml part

# 3. delete Type=".../comments" and Type=".../vmlDrawing"

# relationships from each xl/worksheets/_rels/sheet*.xml.rels

# 4. remove the <legacyDrawing r:id="..."/> element from each

# xl/worksheets/sheet*.xml

# 5. drop the now-orphan Override/Default entries from

# [Content_Types].xml so the package validates

# Excel then opens the workbook with no notes and no repair prompt.

A subtle point: some vmlDrawing parts back more than notes — legacy form controls and other annotations can share the same VML file. A safe pass parses each VML part, removes only the shapes whose <x:ClientData ObjectType="Note"> marks them as comments, and keeps the part if other shapes remain. Blindly deleting every VML file can strip checkboxes and option buttons a worksheet legitimately needs.

For workbooks where some notes must stay — an internal instruction sheet that genuinely relies on them — the cleanup should at minimum rewrite the <authors> table to a single neutral label and compact it so no orphan names survive, then re-point every surviving comment’s authorId at that one entry. That removes the identity layer while preserving the editorial text the recipient is meant to read.

Pre-Share Legacy-Comment Checklist

  • Enumerate every xl/comments*.xml part and read every note’s text — including notes that are hidden in the grid.
  • Read the full <authors> table; confirm no domain logins, personal names, or external-reviewer labels remain.
  • Diff used author indices against the full table; remove every orphan author left by a deleted note.
  • Check each vmlDrawing*.vml part for note shapes and for unrelated form controls before deleting the file.
  • Remove the comments and vmlDrawing relationships, the <legacyDrawing> elements, and the matching content-type entries together.
  • Run the Comments and Annotations check and verify the threaded-comment layer separately — clearing one does not clear the other.
  • Strip the layer in code before the save dialog; do not rely on Hide Comment, Document Inspector alone, or visual review.
  • Verify by re-running the enumeration script and confirming zero comments parts and zero note shapes remain.

Notes as Part of a Coordinated Cleanup

The legacy comment layer interlocks with several siblings that should be touched in the same pass. The threaded-comment and persona layer is the modern counterpart and carries its own, tenant-resolvable identities; a workbook is not comment-clean until both are handled. The shared-strings table can retain the text of a note even after the comment is removed, if the note text was ever promoted into a cell. And the same author names that fill the comments table also appear in defined names, in VBA project metadata, and in the core document properties — stripping one source of a name while leaving the others is no cleanup at all.

The broader lesson is the one this whole series keeps returning to: a workbook is a package of cooperating parts, and metadata lives in the seams between them. The legacy comment layer is one of the oldest of those seams, easy to forget precisely because Microsoft renamed it, and reliably overlooked by anyone who thinks “comments” means only the modern threaded kind.

The Note Layer Is a Confessional

Legacy notes look like a quaint, almost obsolete feature — little yellow boxes that pop up on hover. In metadata terms they are one of the most candid layers a workbook carries. The <authors> table names everyone who annotated the file. The note text records the doubts, disagreements, and warnings the author would never write into a cell. The VML visibility flags show which of those remarks the author thought they had tucked away. Orphan authors preserve the names of reviewers whose notes were deleted. None of it appears in the rendered grid unless you hover the right cell; all of it is in the XML as plain UTF-8, trivially extractable with a ZIP reader and a ten-line script.

For workbooks staying inside an organisation, notes are exactly what they were designed to be: a lightweight way to leave context next to a number. For workbooks crossing the perimeter, they are a confessional the author forgot to lock. The only durable defence is to rewrite the layer as part of a coordinated cleanup that removes the comments part, the VML shapes, the rels entries, the legacy-drawing pointers, and the content-type registrations together — and to remember that in this format a “Note” is just a comment that learned to hide.

Audit Legacy Notes in Your Workbooks

Use MetaData Analyzer to enumerate every legacy note across every worksheet, resolve each one to its author, surface hidden note boxes that visual review never shows, detect orphan author names left by deleted comments, and confirm both the legacy and threaded comment layers are empty before your workbooks leave the organisation.