EXLTand it's version following that. Each sequential line after the 'header' is a path, relative to the
exd/category, and its immutable ID. The immutable ID is optional and in cases where not relevant (eg. quest dialogue files) it's value is
EXHF. If it's not, the file is probably not the file you're trying to read.
DataOffsetisn't relevant to this file at all, but is required when loading certain data from Excel Data files such as strings. It points to the end of the fixed size data of a row. For example, a row can be made of a bunch of integral types which have a known length at compile time, however a string length is variable. This offset allows you to then seek to the end of the row and access any additional data that may be on the end. If this is weird, don't worry, because it'll make sense later.
ColumnCountis how many columns exist within the file and is the first thing you'll read after the header. In other words, you'll need to read
sizeof( ColumnDefinition ) * ColumnCountimmediately after the header.
Offsetis relative to the row offset, which you don't have until you read the offset table from a data file.
Typeis the type of data stored. Most don't have any special handling outside of
PackedBoolXbut we'll cover that later.
PageCountis the number of 'pages' an excel data sheet is split into. Many sheets only have a single page and every row will exist in a single page, however larger sheets such as
Itemhave many pages. This information is another structure and immediately follows the column definition data.
startIdis the row id where a page starts. You'll need this to build file paths for data files.
rowCountis how many parent rows a sheet contains. As a quick example before we cover it more in depth later is that given a row id, you can calculate which page a row is on with
row >= startId && row < startId + rowCount - 1.
Defaultrequires no extra processing and you can just iterate over the offset list inside a data file.
SubRowsmakes each row contain it's own rows. As a better example, it's like having a compound key on a database table. Instead of one column being the identifier for a row, you have two instead.
None), the following format applies:
magicshould always be
indexSizeis how large the row offset index is, in terms of total size. To convert that to a number of entries, you'd do
indexSize / sizeof( ExcelDataOffset ).
ExcelDataHeader, the root row offsets are stored. The reason it's called the 'root row offset' is because on variant 2 sheets (or sheets with subrows), this offset won't point to data that can be read following the column data.
rowIdis the absolute row id, so a simple way to map these in whatever you're doing is to convert the list of data offsets in this file to a key value map, where the key is the
rowIdand the value is the
offset. Then you can directly index
rowIds on any given data page.
offsetis the absolute offset to where the data is located in the file. It can be used as is.
dataSizeis the entire size of the row, including any data for subrows (if they exist). You can use this field to copy out the exact amount of data for a row (or subrows) to then later parse if you choose not to do it in place.
rowCountis always 1 on variant 1 sheets and you can ignore that field entirely if you choose to. However, on variant 2 sheets, the
rowCountis how many subrows belong to a row.
rowOffsetis the offset from the offset list.
rowOffset + 6is the skipping the size of the row header. You could just store the offset once you read the row header and use that.
header.dataOffsetpoints to the end of the raw data of the row, or is basically the 'fixed' size of a row, not including strings. This lets you seek to the end of a row and immediately go to the next subrow.
uint32where there string column is. You can then obtain the offset of the string by doing the following:
rowOffsetis the offset of the first column of a row, the
dataOffsetfrom the header and the
uint32that you read out from the column.