A worksheet holds 65,536 rows (0 to 65,535) and 256 columns (0 to 255, A to IV).
Each non-empty or formatted cell is one record; rows come in blocks of up to 32, with
the block’s Row records first and its cells after them, in row order (see
Index and
DBCell). Sections are those of [MS-XLS]; all numbers little-endian.
The Cell header
Most cell records start with this 6-byte Cell structure (section 2.5.19):
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 2 | rw | Row, from 0. |
2 | 2 | col | Column, from 0. |
4 | 2 | ixfe | Index of the cell’s XF record. |
Value records
| Type | Record | After the Cell header |
|---|---|---|
0x0201 | Blank | Nothing: an empty cell with a format. |
0x0203 | Number | 8-byte IEEE double. |
0x027E | RK | 4-byte RK number (the record is row, column, then an RkRec of XF index and RK). |
0x00FD | LabelSst | 4-byte index into the shared string table. |
0x0204 | Label | The text itself as an XLUnicodeString (BIFF8 writers normally use LabelSst). |
0x0205 | BoolErr | Value byte, then a byte that is 0 for a Boolean (0 false, 1 true) or 1 for an error code. |
0x0006 | Formula | Cached value, flags and the formula. |
Two records pack a run of cells in one row: MulRk (0x00BD)
holds the row, the first column, then for each cell a 6-byte RkRec (2-byte XF index and
4-byte RK number), and finally the last column; MulBlank
(0x00BE) holds the row, first column, one 2-byte XF index per cell and the
last column. The number of entries is last − first + 1, and the first column is at
most 254.
RK numbers
An RK number (section 2.5.217) packs common numbers into 4 bytes:
| Bits | Field | Meaning |
|---|---|---|
| 0 | fX100 | 1: divide the result by 100. |
| 1 | fInt | 1: bits 2–31 are a signed 30-bit integer. 0: they are the top 30 bits of an IEEE double whose low 34 bits are 0. |
| 2–31 | num | The value. |
For example 0x3FF00000 has both flags clear: it is the double
0x3FF0000000000000, 1.0. 0x00000193 has fInt
and fX100 set and num = 100, so it is 100 ÷ 100 = 1.0 as
well; 0x00000192 is the integer 100.
Error codes
Used by BoolErr, cached formula results and formula error constants (section 2.5.10):
| Code | Error | Code | Error |
|---|---|---|---|
0x00 | #NULL! | 0x1D | #NAME? |
0x07 | #DIV/0! | 0x24 | #NUM! |
0x0F | #VALUE! | 0x2A | #N/A |
0x17 | #REF! | 0x2B | #GETTING_DATA |
Formula (0x0006)
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 6 | Cell | Row, column, XF. |
6 | 8 | val | The last calculated value (below). |
14 | 2 | flags | Bit 0 fAlwaysCalc (recalculate next time), bit 2 fFill (fill or centre-across alignment), bit 3 fShrFmla (part of a shared formula; the formula then starts with PtgExp), bit 5 fClearErrors (excluded from error checking). |
16 | 4 | chn | Application cache; may be ignored. |
20 | varies | formula | 2-byte length, the parsed formula, then any extra data. |
The value (FormulaValue, section 2.5.133) is a double unless its last two bytes are
0xFFFF. Then byte 0 gives the type: 0 text, held in a
String record (0x0207, an XLUnicodeString) that follows the
Formula record; 1 Boolean, in byte 2; 2 error, code in byte 2; 3 empty text.
A formula shared by several cells, an array formula and a data table store their
definition once in a following ShrFmla (0x04BC),
Array (0x0221) or Table (0x0236)
record; each cell’s own formula is then just a PtgExp or PtgTbl naming the top-left
cell.
Array (0x0221)
An array formula for a range (2.4.4). It follows the Formula record of the first
cell of the range; every other cell of ref has its own Formula record
(not necessarily next to it) whose formula begins with PtgExp, and every cell of
ref must have one.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 6 | ref | A Ref: the range of the array formula (rwFirst 2, rwLast 2, colFirst 1, colLast 1). |
6 | 2 | flags | Bit 0 fAlwaysCalc (calculate at the next recalculation); bits 1–15 reserved, zero. |
8 | 4 | unused | Ignore. |
12 | varies | formula | An ArrayParsedFormula (the parsed formula with its 2-byte size and extra data). |
ShrFmla (0x04BC)
A formula shared by many cells, a size optimisation (2.4.260). It follows the Formula
record of the first cell of the range; the other cells’ Formula records have
fShrFmla set and a cell inside ref.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 6 | ref | A RefU: rwFirst (2), rwLast (2), colFirst (1), colLast (1). The cells that may use the formula; cells in the range need not use it. |
6 | 1 | reserved | Zero. |
7 | 1 | cUse | Number of cells that use the formula. |
8 | varies | formula | A SharedParsedFormula. |
Table (0x0236)
A what-if data table (2.4.319). It follows the Formula record of the first cell of
the table; the other cells of ref have Formula records beginning with
PtgTbl, and each cell of ref belongs to the table. The first row and
column of ref are 1 or more, because the input values lie above and to
the left.
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 6 | ref | A Ref: the range of the data table. |
6 | 2 | flags | Bit 0 fAlwaysCalc; 1 reserved; 2 fRw (input cell of a one-variable table is a row input cell; ignored when fTbl2); 3 fTbl2 (two-variable table); 4 fDeleted1 (the cell at rwInpRw, colInpRw was deleted); 5 fDeleted2 (the cell at rwInpCol, colInpCol was deleted); bits 6–15 reserved. |
8 | 2 | rwInpRw | The row of a row input cell, or, when fTbl2 and fRw are both 0, the row of the (column) input cell. 65535 when fDeleted1. |
10 | 2 | colInpRw | The matching column; -1 when fDeleted1, otherwise 0 or more. |
12 | 2 | rwInpCol | The row of the column input cell of a two-variable table; 65535 when fDeleted2; ignored when fTbl2 is 0. |
14 | 2 | colInpCol | Its column; -1 when fDeleted2, otherwise 0 or more; ignored when fTbl2 is 0. |
For a one-variable table the input cell lies outside the rows
rwFirst - 1 to rwLast and columns colFirst - 1
to colLast, or equals (rwFirst - 1, colFirst - 1).
For a two-variable table, the row input cell and the column input cell may not both
lie inside those bounds in the same dimension: if colInpCol is within
colFirst - 1 to colLast, then rwInpCol is
outside rwFirst - 1 to rwLast, and the reverse.
String (0x0207)
The text result of a formula (2.4.268), written straight after that Formula record
(after any Array, ShrFmla or Table record) when its value type is 0. One field:
string, an XLUnicodeString of at most 32,767 characters, and it may be
continued in Continue records like any long string.
Rows, columns and the used range
| Record | Fields |
|---|---|
Row (0x0208) | Row (2); first used column (2); one past the last used column (2); height in twips (2, 2 to 8,192); 2 reserved; 2 unused; flags (4): bits 0–2 outline level, 4 fCollapsed, 5 fDyZero (hidden), 6 fUnsynced (height set by hand), 7 fGhostDirty (row has a format), byte 1 reserved (1), bits 16–27 the row’s XF index, 28 fExAsc, 29 fExDes (thick borders above or below), 30 fPhonetic. |
ColInfo (0x007D) | First and last column (2 each); width in 1/256 of the width of a digit in the Normal style’s font (2); XF index (2); flags (2): bit 0 hidden, 1 fUserSet, 2 fBestFit, 3 fPhonetic, bits 8–10 outline level, bit 12 fCollapsed; 2 unused. |
Dimensions (0x0200) | First used row (4); one past the last used row (4, at most 65,536); first used column (2); one past the last (2, at most 256); 2 reserved. All zero for an empty sheet. |
DefaultRowHeight, DefColWidth | Height of rows and width of columns that have no record of their own. |
Fonts, number formats and XF records
The globals substream holds the formatting tables that cells point into.
Font (0x0031)
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 2 | dyHeight | Height in twips (1/20 point), 20 to 8,191. |
2 | 2 | flags | Bit 1 italic, 3 strikeout, 4 outline, 5 shadow, 6 condensed, 7 extended. |
4 | 2 | icv | Colour index. |
6 | 2 | bls | Weight, normally 400 or 700 (bold). |
8 | 2 | sss | 0 normal, 1 superscript, 2 subscript. |
10 | 1 | uls | Underline: 0 none, 1 single, 2 double, 0x21 single accounting, 0x22 double accounting. |
11 | 1 | bFamily | 0 n/a, 1 Roman, 2 Swiss, 3 Modern, 4 Script, 5 Decorative. |
12 | 1 | bCharSet | Windows character set: 0 ANSI, 1 default, 2 symbol, 0x4D Mac, 0x80 Shift-JIS, 0x81 Hangul, 0x82 Johab, 0x86 GB2312, 0x88 Big5, 0xA1 Greek, 0xA2 Turkish, 0xA3 Vietnamese, 0xB1 Hebrew, 0xB2 Arabic, 0xBA Baltic, 0xCC Russian, 0xDD Thai (as [MS-XLS] gives it; Windows itself uses 0xDE), 0xEE Eastern European, 0xFF OEM. |
13 | 1 | unused | |
14 | varies | fontName | ShortXLUnicodeString. |
The first four Font records must be the default font, then bold, italic, and bold italic. A font index below 4 counts from 0; above 4 it counts from 1, so index 4 is never used and index 5 means the fifth Font record (section 2.5.129, FontIndex).
Format (0x041E)
A 2-byte number format id and its format string (XLUnicodeString, 1 to 255
characters). An XF’s format id is either a built-in format, listed in ECMA-376 Part 1
section 18.8.30 and shared with XLSX, or a
custom format defined by a Format record with an id from 164 to 392
(0x00A4–0x0188; Excel 97 to 2010 also write 383 to 392).
Format records may also carry the locale-dependent built-in ids 5–8, 23–26, 41–44
and 63–66 (sections 2.4.126 and 2.5.165).
XF (0x00E0)
| Offset | Size | Field | Meaning |
|---|---|---|---|
0 | 2 | ifnt | Font index. |
2 | 2 | ifmt | Number format id. |
4 | 2 | flags | Bit 0 locked, 1 hidden (formula hidden when protected), 2 fStyle (a style XF, not a cell XF), 3 f123Prefix (cell text has a Lotus prefix character), bits 4–15 the parent style XF (0xFFF for a style). |
6 | 14 | CellXF or StyleXF | Alignment, borders and fill, below. |
| CellXF field | Bits | Values |
|---|---|---|
alc | 3 | Horizontal alignment: 0 general, 1 left, 2 centre, 3 right, 4 fill, 5 justify, 6 centre across selection, 7 distributed (0xFF not specified, in other structures). |
fWrap | 1 | Wrap text. |
alcV | 3 | Vertical alignment: 0 top, 1 centre, 2 bottom, 3 justify, 4 distributed. |
fJustLast | 1 | Justify the last line too (East Asian distributed). |
trot | 8 | Rotation: 0–90 anticlockwise degrees, 91–180 clockwise 1–90 degrees, 255 vertical stacked text. |
cIndent | 4 | Indent level. |
fShrinkToFit | 1 | Shrink to fit. |
iReadOrder | 2 | 0 context, 1 left to right, 2 right to left. |
fAtrNum … fAtrProt | 6 × 1 | Whether the number format, font, alignment, borders, fill and protection come from this XF rather than its parent style. |
dgLeft, dgRight, dgTop, dgBottom, dgDiag | 4 each | Border style: 0 none, 1 thin, 2 medium, 3 dashed, 4 dotted, 5 thick, 6 double, 7 hair, 8 medium dashed, 9 dash-dot, 10 medium dash-dot, 11 dash-dot-dot, 12 medium dash-dot-dot, 13 slanted dash-dot. |
icvLeft, icvRight, icvTop, icvBottom, icvDiag | 7 each | Border colour indexes. |
grbitDiag | 2 | Diagonals: 0 none, 1 down, 2 up, 3 both. |
fHasXFExt | 1 | An XFExt record extends this XF. |
fls | 6 | Fill: 0 none, 1 solid, 2 50% grey, 3 75% grey, 4 25% grey, 5 horizontal stripe, 6 vertical stripe, 7 reverse diagonal stripe, 8 diagonal stripe, 9 diagonal crosshatch, 10 thick diagonal crosshatch, 11–14 thin horizontal, vertical, reverse diagonal and diagonal stripes, 15 thin horizontal crosshatch, 16 thin diagonal crosshatch, 17 12.5% grey, 18 6.25% grey. |
icvFore, icvBack | 7 each | Pattern foreground and background colour indexes. |
fsxButton | 1 | The XF belongs to a PivotTable drop-down button. |
Colour indexes
Colour indexes (section 2.5.161, Icv): 0 to 7 are fixed (black, white, red, green,
blue, yellow, magenta, cyan); 8 to 63 are the palette, taken from the
Palette record if there is one; 0x40 default foreground
(window text), 0x41 default background (window), 0x4D and
0x4E chart foreground and background, 0x4F chart neutral
(black), 0x51 tooltip text, 0x7FFF automatic font
colour. The default palette, as red, green, blue:
| Index | RGB | Index | RGB | Index | RGB | Index | RGB |
|---|---|---|---|---|---|---|---|
| 8 | 0 0 0 | 22 | 192 192 192 | 36 | 128 0 128 | 50 | 153 204 0 |
| 9 | 255 255 255 | 23 | 128 128 128 | 37 | 128 0 0 | 51 | 255 204 0 |
| 10 | 255 0 0 | 24 | 153 153 255 | 38 | 0 128 128 | 52 | 255 153 0 |
| 11 | 0 255 0 | 25 | 153 51 102 | 39 | 0 0 255 | 53 | 255 102 0 |
| 12 | 0 0 255 | 26 | 255 255 204 | 40 | 0 204 255 | 54 | 102 102 153 |
| 13 | 255 255 0 | 27 | 204 255 255 | 41 | 204 255 255 | 55 | 150 150 150 |
| 14 | 255 0 255 | 28 | 102 0 102 | 42 | 204 255 204 | 56 | 0 51 102 |
| 15 | 0 255 255 | 29 | 255 128 128 | 43 | 255 255 153 | 57 | 51 153 102 |
| 16 | 128 0 0 | 30 | 0 102 204 | 44 | 153 204 255 | 58 | 0 51 0 |
| 17 | 0 128 0 | 31 | 204 204 255 | 45 | 255 153 204 | 59 | 51 51 0 |
| 18 | 0 0 128 | 32 | 0 0 128 | 46 | 204 153 255 | 60 | 153 51 0 |
| 19 | 128 128 0 | 33 | 255 0 255 | 47 | 255 204 153 | 61 | 153 51 102 |
| 20 | 128 0 128 | 34 | 255 255 0 | 48 | 51 102 255 | 62 | 51 51 153 |
| 21 | 0 128 128 | 35 | 0 255 255 | 49 | 51 204 204 | 63 | 51 51 51 |