A shared workbook (several people editing, with change tracking) keeps extra data beside the workbook: a log of every change in a separate stream, a list of who has the file open, and locks. Custom views save window, print and filter settings under a name; they are stored inside the workbook and its sheets. Section numbers are those of [MS-XLS] v20250819; integers are little-endian. “GUID” is a 16-byte identifier as in [MS-DTYP]; ShortDTR is the 8-byte date and time structure of the spec.
Users and locks
| Record | Fields |
|---|---|
| CUsr (0x0191, 2.4.72) | iCount (2): the number of unique users who have the shared workbook open. |
| CbUsr (0x0192, 2.4.40) | rgCbUsr (512 bytes): an array of 256 two-byte values, the size of each UsrInfo record kept in the workbook. |
| UsrInfo (0x0193, 2.4.340) | A user who has the workbook open. lUsrId (4, signed: the unique identifier), guid (16: the last set of revisions this user synchronised), shortdtr (8: when the user opened the file), then the user’s name (a count and characters) and 1 unused byte. |
| UsrExcl (0x0194, 2.4.339) | Opens a collection. fExclusive (4: 0 no exclusive lock, 1 the user has an exclusive lock), sdtr (8, ShortDTR: when it was set), cchUser (2) and the user’s name stUser. |
| UsrChk (0x0198, 2.4.338) | version (2): the BIFF version used by the last user who opened the file: 0x0200 BIFF2, 0x0300 BIFF3, 0x0400 BIFF4, 0x0500 BIFF5, 0x0600 BIFF8. |
| BCUsrs (0x0197, 2.4.16) | Opens a collection of UsrInfo records in the user names stream. iCount (2): the number of users of the operating system on the machine. |
| FileLock (0x0195, 2.4.116) | lPurpose (4): why the shared workbook is locked: 0 not locked, 0x00010001 for writing or reading, 0x00010002 for merging two copies, 0x00010004 to make it exclusive, 0x00010008 to delete it (the spec’s wording is cut short in the extract). |
The revision log
Each change is one record in the revision stream, beginning with a 14-byte RRD
structure; records are ordered by revid as described in the Revision Stream
ABNF (2.1.7), which this page does not give.
RRD (2.5.220)
| Size | Field | Meaning |
|---|---|---|
| 4 | cbMemory | The size of the revision structure in memory (not in the file), at least 26; ignored in RRDHead. |
| 4 | revid | Signed, 0 or more: the revision identifier, the order of the revisions. |
| 2 | revt | A RevisionType, below. |
| 2 | flags | Bit 0 fAccepted (reviewed and accepted), 1 fUndoAction (the revision came from an undo), 2 unused, 3 fDelAtEdgeOfSort (the row or column being deleted is at the edge of a sorted range; only RRDInsDel with a row or column insert or delete), 4–15 reserved. |
| 2 | tabid | The sheet identifier (0xFFFF when not tied to one sheet). |
RevisionType (2.5.212)
0x0000 insert row, 0x0001 insert column, 0x0002 delete row, 0x0003 delete column, 0x0004 cell move, 0x0005 insert sheet, 0x0007 sort, 0x0008 cell change, 0x0009 rename sheet, 0x000A defined name change, 0x000B format, 0x000C AutoFormat, 0x000D comment, 0x0020 header (metadata), 0x0025 conflict, 0x002B custom view added, 0x002C custom view deleted, 0x002E query table field removed.
| Record | Fields (after the RRD) |
|---|---|
| RRDHead (0x0138, 2.4.226) | The metadata of a set of revisions by one user: guid (16: its identity), wFileCodePage (2), cchUser (2), stUser (114 bytes: the name), sddtr (8, ShortDTR: when the user saved this set), tabidMac (2, signed: the next free sheet identifier), and further fields not shown in this extract. |
| RRDInfo (0x0196, 2.4.227) | Information about the shared workbook. wXLVer (2: the major BIFF version last used), a flag word with fssShared (the workbook is shared), fssDiskHasRev (the history on disk has revisions), fssRevHist (revisions are deleted automatically), fssRevTrack (revisions are tracked), fssExclusive (exclusive mode); guid (16: the last set of revisions), guidRoot (16), revid (4: the current revision number), version (4), and flags fNoRevHist (history is not kept) and fProtRev (the history is protected). |
| RRTabId (0x013D, 2.4.241) | An array of unique sheet identifiers, one per sheet in workbook order. The spec mentions a case of 4112 sheets in which the record is not present and each identifier is given by the order of the sheets (the condition’s first words were lost in the text extract). |
| RRDChgCell (0x013B, 2.4.223) | A cell change. A flag word with vt (3 bits: the type of the new content: 0 blank, 1 RkNumber, 2 Xnum, 3 XLUnicodeRichExtendedString, 4 a Bes (boolean or error), 5 a CellParsedFormula), vtOld (3 bits: the same for the old content), f123Prefix (prefix characters are present), unused, fOldFmt (old formatting exists), fOldFmtNull, fXfDxf (the cells’ format resets to that of the XF), fStyXfDxf (the format is cleared before applying), fDxf (the format changed; the dxf then exists unless fDxfNull), fDxfNull, ifmtDisp (8 bits: a number format id), fPhShow and fPhShowOld (the new and old cell have a phonetic string), fEOLFmlaUpdate; then loc (4, an RgceLoc: the cell), cbOldVal (4: the size of the old content: 0 for blank, 4 for RK, 8 for Xnum, the string’s size for text, 2 for Bes, at least 0x18 for a formula), cetxpRst (2: the number of RRDRstEtxp records that follow), then the old content (rkOld 4, numOld 8, besOld 2, or a string or formula) and the new (rk, num, bes, string or formula), each present exactly when its type says so, and the old and new formats. |
| RRDRstEtxp (0x0154, 2.4.235) | Font information of a run in rich text; follows an RRDChgCell. iFnt (2: the zero-based index of this record in the set), cchFontName (1), fFullStr (1, Boolean: the name has double-byte characters), stFontName (62 bytes, fixed), stxp (16: an Stxp, the font attributes), icvFore (2: palette colour). |
| RRDInsDel (0x0137, 2.4.228) | Insertion or deletion of rows or columns; opens a collection. A flag fEndOfList (a row was inserted at the bottom of the filled cells), refn (8, Ref8U: the cells affected), cUcr (4: the number of items in rgDucr, the changes to other revisions’ positions). Begin: RRDInsDelBegin (0x0150, 2.4.229); end: RRDInsDelEnd (0x0151, 2.4.230). |
| RRDMove (0x0140, 2.4.231) | Cells that moved; the RRD has revt 0x0004 and a specific tabid. refSrc (8, Ref8U: the original range), refDst (8: the new range), tabidSrc (2: the sheet of the source), cUcr (4: the number of rgDucr elements). Begin: RRDMoveBegin (0x014E, 2.4.232); end: RRDMoveEnd (0x014F, 2.4.233). |
| RRInsertSh (0x014D, 2.4.239) | A sheet was inserted. itabPos (2: its position), cch (2), stName (256 bytes, the name). |
| RRDRenSheet (0x013E, 2.4.234) | A sheet was renamed. cchOldName (2), stOldName (255 bytes), cchNewName (2), stNewName (255 bytes). |
| RRSort (0x013F, 2.4.240) | A sort. ref8 (8: the range sorted), a flag fCol (sorting is by columns) and the sort keys (not shown in this extract). |
| RRDDefName (0x0153, 2.4.225) | A defined name changed. tabidLocal (2: the sheet of a local name), fViewName (1: 1 if the name belongs to a custom view), grbit (6) and grbitOld (6) (RRDDefNameFlags: data for the new and the old name), builtinIndex (1: 0 not built-in, 1 Consolidate_Area, 2 Auto_Open, 3 Auto_Close, 4 Extract, 5 Database, 9 Recorder, 10 Data_Form, 11 Auto_Activate, 12 Auto_Deactivate, 13 Sheet_Title), 3 optional unused bytes (present if and only if builtinIndex is not 0), then the formulas. |
| RRFormat (0x014A, 2.4.238) | A formatting change; split over several records when too large. Flags fXfDxf (the cells’ format resets to the XF’s), fXfDxfNull (whether dxfn exists), fStyXfDxf (the format is cleared first), then the DXFN (see styles). |
| RRAutoFmt (0x014B, 2.4.222) | An AutoFormat. ref8 (8: the range), itbl (2, an AutoFmt8: which one) and flags for what was applied: fApplyNumberFormats, fApplyFontFormats, fApplyAlignmentFormats, fApplyBorderFormats, fApplyPatternFormats, fApplyWidthHeightFormats. |
| RRDConflict (0x0152, 2.4.224) | The resolution of a conflict between two users’ revisions; only the RRD. |
| RRDTQSIF (0x0808, 2.4.236) | A query table field removed. rt (2, 0x0808), grbitfrt (2, 0x0001), the RRD (revid must be 0, per the spec’s text), idField (4: the identity of the field in the query table). |
| RRDUserView (0x01AC, 2.4.237) | The changes caused by a custom view revision: guid (16: the view) and more. |
Custom views
| Record | Fields |
|---|---|
| UserBView (0x01A9, 2.4.333) | The workbook-wide settings of a custom view; one UserSViewBegin block per sheet goes with it. 4 unused, tabId (2: the active sheet), guid (16: the view’s identity), x, y, dx, dy (4 each, signed, pixels: the workbook window), wTabRatio (2: the share of the window used by the sheet tabs), a flag word: bit 0 fDspFmlaBar, 1 fDspStatus, 2–3 mdNoteDisp (0 comments and cues off, 1 a visual cue, 2 comments and cue on), 4 fDspHScroll, 5 fDspVScroll, 6 fBotAdornment (sheet tabs), 7 fZoom (maximised), 8–9 fHideObj (a HideObjEnum: how objects are shown), 10 fPrintIncl (includes the workbook’s print settings), 11 fRowColIncl (includes hidden rows and columns and filter settings), 12 fInvalidTabId (tabId is ignored), 13 fTimedUpdate, 14 fAllMemChanges, 15 fOnlySync; 2 unused; a second word with fPersonalView (the personal view of a user), fIconic (minimised) and 14 unused bits; wMergeInterval (2: minutes between automatic updates, at least 5, or 65535 for none). |
| UserSViewBegin (0x01AA, 2.4.334) | Opens the settings of one sheet in a view. guid (16: the UserBView it belongs to), iTabid (2: the sheet), wScale (4: the zoom), icvHdr (2: the gridline colour), pnnSel (1, a PaneType: the active pane), then flags, starting fShowBrks (page breaks shown), fDspFmlaSv (formulas shown instead of values), fDspGridSv, fDspRwColSv (row and column headings), fDspGutsSv (outline symbols; 0 for chart sheets), fDspZerosSv (1 suppresses zeros), fHorizontal, fVertical (centred on the page), fPrintRwCol, fPrintGrid, fFitToPage, fPrintArea (at least one print area), fOnePrintArea, fFilterMode (hidden cells because of a filter), fEzFilter (the AutoFilter icon shows), fFrozen, fFrozenNoSplit, fSplitV, fSplitH, fHiddenRw (2 bits: 0 a hidden row exists, 1 none), fHiddenCol, 3 unused, fFilterUnique (advanced filter), fSheetLayoutView (page break preview), fPageLayoutView; then ref8TopLeft (8: the visible area of the top-left pane), operNumX and operNumY (8 each, floating point: where the split begins), colRPane and rwBPane (2 each: the first visible column of the right pane and row of the bottom pane), and further fields. |
| UserSViewBegin_Chart (0x01AA, 2.4.335) | The chart sheet form of the same record (the same number): guid (16), iTabid (4), wScale (4), 4 unused, a flag word (hsState, 2 bits: 0 visible, 1 hidden, 2 very hidden, which the user interface cannot show; fZoomToFit), and 8 + 8 + 8 + 2 + 2 unused bytes. |
| UserSViewEnd (0x01AB, 2.4.336) | Closes the settings block: reserved (2, always 1). |
Source
[MS-XLS] Excel Binary File Format (.xls) Structure, v20250819, sections 2.4.16, 2.4.40, 2.4.72, 2.4.116, 2.4.222–2.4.241, 2.4.333–2.4.340 and the structures RRD (2.5.220) and RevisionType (2.5.212). Not covered: the Revision Stream and user names stream ABNF (the order of these records and which stream each lives in), the DXFN and RRDDefNameFlags layouts, the rgDucr and sort key arrays, the trailing fields of RRDHead, RRSort and UserSViewBegin, and the exact text of two FileLock purposes, all of which the text extract read for this page cut short.