Shapes, pictures, charts, form controls, text boxes and cell comments are stored as
drawings. The shapes themselves are Office drawing (OfficeArt) records, defined in
[MS-ODRAW], carried inside MsoDrawingGroup and MsoDrawing
records; the properties that belong to Excel are in Obj, TxO
and Note records that follow them. Section numbers are those of [MS-XLS]
v20250819; integers are little-endian.
How the records are ordered
In a worksheet, macro sheet or dialog sheet substream the drawing records are
(ABNF): OBJECTS = *(MSODRAWING *(TEXTOBJECT / OBJ)) [MsoDrawingSelection]
and MSODRAWING = MsoDrawing *Continue. In the Globals substream a single
MSODRAWINGGROUP = MsoDrawingGroup *Continue holds the file-wide drawing
data. When a shape in an MsoDrawing has a client-data record, the very
next record must be an Obj; when it has a client text box, the next record
must be a TxO (the sizes of these client records do not include the
Obj or TxO that follows).
| Type | Record | Data |
|---|---|---|
0x00EB | MsoDrawingGroup (2.4.171) | rgChildRec: one OfficeArtDggContainer ([MS-ODRAW]), the drawing group data for the file, in the Globals substream. |
0x00EC | MsoDrawing (2.4.170) | rgChildRec: one OfficeArtDgContainer, the drawing of one sheet. In a worksheet, macro or dialog sheet the OfficeArtClientAnchor of [MS-ODRAW] is the OfficeArtClientAnchorSheet below; in a chart sheet it is OfficeArtClientAnchorChart. |
0x00ED | MsoDrawingSelection (2.4.172) | selection: an OfficeArtFDGSL ([MS-ODRAW] 2.2.33), the selected drawing objects and the one in focus. |
0x005D | Obj (2.4.181) | An object’s properties, see below. |
0x01B6 | TxO (2.4.329) | A text box’s text and settings, see below. |
0x001C | Note (2.4.179) | A cell comment, see below. |
0x00E9 | BkHim (2.4.19) | A sheet background image, see below. |
0x00DE | OleObjectSize (2.4.187) | Unused (2), then ref (6, a RefU): the visible range of cells when the workbook is shown as an embedded object, if the active sheet (itabCur of Window1) is a worksheet, macro sheet or dialog sheet; otherwise undefined. |
0x0874 | DropDownObjIds (2.4.93) | frtHeader (12, rt = 0x0874), cidObj (2) and rgidObj: that many 2-byte object identifiers the application may reuse for the AutoFilter drop-down objects it creates at run time; none may equal an existing ObjId in the worksheet substream. |
0x0866 | HFPicture (2.4.138) | A header or footer picture; see worksheet settings. |
The records inside rgChildRec use the OfficeArt record header (8
bytes, rh: recVer, recInstance,
recType, recLen, from [MS-ODRAW] 2.2.1). The container types
(OfficeArtDggContainer, OfficeArtDgContainer, shape and shape-property records, BLIP
stores and pictures) are not defined in [MS-XLS], and [MS-ODRAW] was not read for
this page; so this page lists only the structures [MS-XLS] itself defines for BIFF8,
below. A drawing larger than a record’s limit is continued in Continue
records.
OfficeArt records defined by [MS-XLS]
Each begins with an 8-byte OfficeArtRecordHeader whose recVer and
recInstance are 0 and whose recType is 0xF010
(client anchor), 0xF011 (client data) or 0xF00D (client
text box).
OfficeArtClientAnchorSheet (2.5.193)
The position of a shape on a sheet; recType 0xF010,
recLen 18.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 8 | rh | The record header. |
8 | 2 | flags | Bit 0 fMove (the shape keeps its shape when cells move); bit 1 fSize (when cells are resized; must be 1 if fMove is); bits 2–4 reserved 0; bits 5–15 unused. |
10 | 2 | colL | Column of the cell under the top-left corner. |
12 | 2 | dxL | Signed x of that corner relative to the cell’s corner, in 1/1024 of the cell’s width. |
14 | 2 | rwT | Row of the cell under the top-left corner. |
16 | 2 | dyT | Signed y, in 1/256 of the cell’s height. |
18 | 2 | colR | Column under the bottom-right corner. |
20 | 2 | dxR | Signed x, in 1/1024 of the cell’s width. |
22 | 2 | rwB | Row under the bottom-right corner. |
24 | 2 | dyB | Signed y, in 1/256 of the cell’s height. |
OfficeArtClientAnchorChart (2.5.191)
The position of a shape in a chart: rh (recType
0xF010, recLen 0x12), 2 bytes of flags (bit 0 fMove
0; bit 1 fSize: 0 the shape resizes with the chart area, 1 it does not;
bits 2–4 reserved or undefined; 11 bits unused), then four signed 4-byte values
lx1, ly1, lx2, ly2: the upper-left
and lower-right corners relative to the upper-left corner of the chart area, in SPRC
(1/4000 of the chart’s width or height).
OfficeArtClientAnchorHF (2.5.192)
The size of a header or footer picture: rh (recType
0xF010, recLen 8), width (4, signed, pixels,
above 0) and height (4, signed, pixels, above 0).
OfficeArtClientData and OfficeArtClientTextbox
Each is just an 8-byte header with recLen 0: recType
0xF011 for the client data (2.5.194), after which the next record must be
Obj; 0xF00D for the client text box (2.5.195), after which the next record
must be TxO. Each must be the last structure in the rgChildRec of its
MsoDrawing.
Obj (0x005D)
The properties of one object (2.4.181). It is a sequence of subrecords, each of which
begins with a 2-byte ft and, for most, a 2-byte cb; the
ot field of the first (FtCmo) decides which others are present.
| Field | Size | Present |
|---|---|---|
cmo (FtCmo) | 22 | Always. |
gmo (FtGmo) | 6 | If and only if ot is 0 (group). |
pictFormat (FtCf), pictFlags (FtPioGrbit) | 6 each | If and only if ot is 8 (picture). |
cbls (FtCbls) | 16 | If and only if ot is 0x0B or 0x0C. |
rbo (FtRbo) | 10 | If and only if ot is 0x0C. |
sbs (FtSbs) | 24 | If and only if ot is 0x10, 0x11, 0x12 or 0x14. |
nts (FtNts) | 26 | If and only if ot is 0x19. |
macro (FtMacro) | variable | Optional: the macro run by the object. |
pictFmla (FtPictFmla) | variable | Only when ot is 8. |
linkFmla (ObjLinkFmla) | variable | Only when ot is 0x0B, 0x0C, 0x10, 0x11, 0x12 or 0x14: the range with the linked value. Its ft is 0x14 for 0x0B and 0x0C, 0x0E for the others. |
checkBox (FtCblsData) | 12 | If and only if ot is 0x0B or 0x0C. |
radioButton (FtRboData) | 8 | If and only if ot is 0x0C. |
edit (FtEdoData) | 12 | If and only if ot is 0x0D. |
list (FtLbsData) | variable | If and only if ot is 0x12 or 0x14. |
gbo (FtGboData) | 10 | If and only if ot is 0x13. |
reserved | 4 | Zero; present if and only if ot is not 0x12 or 0x14. |
FtCmo (2.5.143)
ft = 0x15, cb = 0x12, then:
| Offset | Size | Field | Meaning |
|---|---|---|---|
4 | 2 | ot | Object type: 0x00 group, 0x01 line, 0x02 rectangle, 0x03 oval, 0x04 arc, 0x05 chart, 0x06 text, 0x07 button, 0x08 picture, 0x09 polygon, 0x0B checkbox, 0x0C radio button, 0x0D edit box, 0x0E label, 0x0F dialog box, 0x10 spin control, 0x11 scrollbar, 0x12 list, 0x13 group box, 0x14 dropdown list, 0x19 note, 0x1E OfficeArt object. |
6 | 2 | id | The object identifier other records refer to; unique among the Obj records of the chart, macro and worksheet substreams. |
8 | 2 | flags | Bit 0 fLocked; 1 reserved; 2 fDefaultSize (the application chooses the size); 3 fPublished (a chart to publish; ignored when fPublishedBookItems is 0); 4 fPrint (included when printing); 5–6 unused; 7 fDisabled; 8 fUIObj (an auxiliary object only the application inserts); 9 fRecalcObj (update on load from the associated range; used only if pictFmla.key.fmlaListFillRange.cbFmla is not 0); 10–11 unused; 12 fRecalcObjAlways (update whenever a cell in the range changes; same condition); 13–15 unused. |
10 | 12 | unused | Three 4-byte unused fields. |
Fixed subrecords
| Structure | ft, cb | Fields after them |
|---|---|---|
| FtGmo (2.5.146) | 0x0006, 0x0002 | unused (2). |
| FtCf (2.5.142) | 0x0007, 0x0002 | cf (2): the Windows clipboard format of the picture: 0x0002 enhanced metafile, 0x0009 bitmap, 0xFFFF neither. |
| FtPioGrbit (2.5.151) | 0x0008, 0x0002 | 2 bytes of flags, from bit 0: fAutoPict (aspect ratio kept in all views and printing), fDde (pictFmla is a DDE reference), fPrintCalc (update on print), fIcon, fCtl (an ActiveX control; not with fDde), fPrstm (0 data in an embedding storage, 1 in the controls stream Ctls), unused, fCamera (a camera picture), fDefaultSize (0 size set explicitly, 1 not), fAutoLoad (the OLE server loads the data when the workbook opens), 6 unused bits. |
| FtCbls (2.5.140) | 0x000A, 0x000C | Three unused 4-byte fields. |
| FtRbo (2.5.152) | 0x000B, 0x0006 | unused (4) and unused (2). |
| FtSbs (2.5.154) | 0x000C, 0x0014 | unused (4); signed 2-byte iVal (current value, between iMin and iMax), iMin, iMax, dInc (change per click on a minor increment, 0 or more), dPage (per click on a page region, 0 or more); fHoriz (2: 0 vertical, 1 horizontal); dxScroll (2, signed, the scrollbar’s width in pixels, 0 or more); 2 bytes of flags: fDraw (displayed), fDrawSliderOnly, fTrackElevator (tracks a drag of the thumb), fNo3d, 12 unused. |
| FtNts (2.5.149) | 0x000D, 0x0016 | guid (16, the comment’s GUID), fSharedNote (2: 0 not shared, 1 shared), unused (4). |
| FtCblsData (2.5.141) | 0x0012, 0x0008 | fChecked (2: 0 unchecked, 1 checked, 2 mixed, only for a checkbox, ot 0x0B); accel (2, the accelerator key as a Unicode character, 0 for none, used only in dialog sheets); reserved (2); 2 bytes of flags: fNo3d and 15 unused bits. |
| FtRboData (2.5.153) | 0x0011, 0x0004 | idRadNext (2, an ObjId: the next radio button in the group; 0 or its own id means none) and fFirstBtn (2: 1 first in its group). |
| FtEdoData (2.5.144) | 0x0010, 0x0008 | ivtEdit (2: validation: 0 any string, 1 integer, 2 number, 3 range reference, 4 formula); fMultiLine (2); fVScroll (2); id (2, an ObjId of the associated list control, 0 for none). |
| FtGboData (2.5.145) | 0x000F, 0x0006 | accel (2, dialog sheets only); reserved (2); 2 bytes: fNo3d and 15 unused bits. |
FtLbsData (2.5.147)
A list or drop-down list. ft = 0x0013, then cbFContinued (2:
0 means nothing else follows; otherwise at least the size of the rest of the
structure when it fits in one record, and when it is continued in Continue records,
the size of this record’s share minus 1), then:
| Size | Field | Meaning |
|---|---|---|
| variable | fmla | An ObjFmla: the range holding the list items. |
| 2 | cLines | Number of items, at most 0x7FFF. |
| 2 | iSel | One-based index of the first selected item; 0 for none; at most cLines. |
| 2 | flags | Bit 0 fUseCB (lct is used); 1 fValidPlex (rgLines present); 2 fValidIds (idEdit is used); 3 fNo3d; bits 4–5 wListSelType (0 one item, 1 several by clicking each, 2 several by Ctrl-click); 6 unused; 7 reserved; bits 8–15 lct (the behaviour class when fUseCB: 0x00 regular sheet dropdown, 0x01 PivotTable page-field dropdown, 0x03 AutoFilter dropdown (worksheets and macro sheets only), 0x05 AutoComplete dropdown, 0x06 data-validation list dropdown (worksheets and macro sheets only), 0x07 PivotTable row or column field dropdown, 0x09 dropdown for a table’s Total Row). |
| 2 | idEdit | An ObjId of the associated edit box; 0, or fValidIds 0, means none. |
| variable | dropData | An LbsDropData, present if and only if the Obj’s ot is 0x14. |
| variable | rgLines | cLines XLUnicodeStrings of at most 255 characters each, wholly inside one record (Continue records are used when needed); present if and only if fValidPlex is 1. |
| variable | bsels | cLines one-byte Booleans, 1 for each item in the multiple selection; present if and only if wListSelType is not 0. |
LbsDropData (2.5.171): 2 bytes of flags
(bits 0–1 wStyle: 0 combo dropdown, 1 combo edit dropdown, 2 simple
dropdown, just the button; bit 2 unused; bit 3 fFiltered; 12 bits unused),
cLine (2, lines shown, at most 0x7FFF), dxMin (2, the
smallest dropdown width in pixels, at most 0x7FFF), str
(XLUnicodeString, the current value) and one unused byte if the size of
str in bytes is odd.
Formula subrecords
| Structure | Layout |
|---|---|
| FtMacro (2.5.148) | ft = 0x0004, then an ObjFmla naming a macro: a name defined by an Lbl whose fProc is 1. |
| ObjFmla (2.5.187) | cbFmla (2, the size of the rest, even), fmla (an ObjectParsedFormula, present if and only if cbFmla is above 0), embedInfo (a PictFmlaEmbedInfo, present if and only if the structure is an FtPictFmla and fmla starts with a PtgTbl) and padding to cbFmla (ignore). |
| ObjLinkFmla (2.5.189) | ft (2: 0x0014 or 0x000E as above) and an ObjFmla. |
| FtPictFmla (2.5.150) | ft = 0x0009, cb (2, the length of the rest); fmla (an ObjFmla: with fDde a name from an ExternName with fOle 1; with fCamera a range; otherwise cce is 5 and the formula is a PtgTbl and 4 ignored bytes); lPosInCtlStm (4: present when the formula starts with a PtgTbl; if fPrstm is 0 the data is in an embedding storage named “MBD” plus the 8-digit hexadecimal value, if 1 it is the offset of the data in the controls stream); cbBufInCtlStm (4: the size of the data in the controls stream, present if and only if fPrstm is 1); key (a PictFmlaKey, present if and only if fCtl is 1). |
| PictFmlaKey (2.5.203) | cbKey (4), keyBuf (cbKey bytes: the ActiveX control’s runtime licence key), fmlaLinkedCell (an ObjFmla for the range whose first cell is linked to the control’s selection; empty if none) and fmlaListFillRange (an ObjFmla for the range that fills the control’s content; its cbFmla must be 0 unless the ActiveX control’s type library has a bindable property with GUID {0C733A7C-2A1C-11CE-ADE5-00AA0044773D}). |
| PictFmlaEmbedInfo (2.5.202) | ttb (1, 0x03), cbClass (1, the length of strClass in bytes), reserved (1), strClass (XLUnicodeStringNoCch: the class name of the ActiveX control, OLE object or camera picture; present if and only if cbClass is non-zero). |
| ObjId (2.5.188) | id (2): the cmo.id of an Obj in the same drawing; 0 references none. |
TxO (0x01B6)
The text in a text box or form control (2.4.329). If cchText is not 0,
Continue records follow: first those holding the text (each an
XLUnicodeStringNoCch with part of the string, the total being cchText
characters), then those holding the formatting runs (a TxORuns, split across Continue
records if longer than 8,224 bytes).
| Size | Field | Meaning |
|---|---|---|
| 2 | flags | Bit 0 reserved; bits 1–3 hAlignment (1 left, 2 centred, 3 right, 4 justify, 7 justify distributed); bits 4–6 vAlignment (1 top, 2 middle, 3 bottom, 4 justify, 7 justify distributed); bits 7–8 reserved; bit 9 fLockText; bits 10–13 reserved; bit 14 fJustLast (justify applies to the last line too, in some versions); bit 15 fSecretEdit (a password box that hides what is typed). |
| 2 | rot | Text orientation: 0 none, 1 stacked or vertical, 2 rotated 90° counter-clockwise, 3 rotated 90° clockwise. |
| 2 + 4 | reserved4, reserved5 | Present if and only if the preceding Obj’s ot is not 0, 5, 7, 11, 12 or 14; zero. |
| 6 | controlInfo | A ControlInfo, present if and only if ot is 0, 5, 7, 11, 12 or 14. |
| 2 | cchText | Characters of text in the Continue records. |
| 2 | cbRuns | Bytes of formatting runs: 0 if cchText is 0, otherwise at least 16 and a multiple of 8. |
| 2 | ifntEmpty | A FontIndex: the font used when cchText is 0. |
| variable | fmla | An ObjFmla: the formula for the text. |
ControlInfo (2.5.61), for form controls on a dialog
sheet: 2 bytes of flags (bit 0 fDefault dismisses the dialog and does the
default action; 1 fHelp loads context help; 2 fCancel
dismisses and does nothing; 3 fDismiss dismisses; each 0 unless the control
is a button; 12 reserved bits), accel1 (2, signed, the accelerator
character; 0 for none) and reserved (2, zero).
TxORuns (2.5.272) is an array of Run structures, of
cbRuns / 8 - 1 elements, then lastRun, which is present only
in the last Continue record. A Run (2.5.226) is a FormatRun
(ich 2, the zero-based index of the first character of the run, strictly
increasing and at most cchText; ifnt 2, a FontIndex),
followed by 4 unused bytes. TxOLastRun (2.5.271): cchText
(2, equal to the TxO’s), unused (2) and unused (4).
BkHim (0x00E9)
The background image of a sheet (2.4.19): cf (2, signed: 0x0009 a bitmap,
as in [MSDN-BMP]; 0x000E the native format of another application, which cannot be
processed directly), reserved (2, 0x0001), lcb (4, signed, at least 1:
the size of the image) and imageBlob (lcb bytes of image
data).
Source
[MS-XLS] Excel Binary File Format (.xls) Structure, v20250819, sections 2.4.19, 2.4.93, 2.4.170–2.4.172, 2.4.179, 2.4.181, 2.4.187, 2.4.329, 2.5.61, 2.5.140–2.5.154, 2.5.171, 2.5.186–2.5.189, 2.5.191–2.5.195, 2.5.202–2.5.203, 2.5.226, 2.5.271–2.5.272 and the substream ABNF. Not covered: the OfficeArt records themselves ([MS-ODRAW]), the contents of ObjectParsedFormula, and NoteRR.
Note (0x001C)
A cell comment (2.4.179). In the Workbook stream, within a worksheet, dialog sheet or macro sheet substream, the body is a NoteSh; in a revision log it is a NoteRR (a revision of a comment; its layout is not given here). The comment text is in the TxO belonging to the Obj named by
idObj.rowcolfShow(the comment is always shown); 2 reserved; 3 unused; 4–6 reserved; 7fRwHidden(the row is hidden); 8fColHidden(the column is hidden); 9–15 reserved.idObjstAuthor