微軟的Excel格式有兩種:.xls和.xlsx。Excel2003及之前的版本是.xls格式,從Excel2007開始支持.xlsx格式。只使用基本功能的話兩種格式看起來並沒有多大差別,但是兩者文件格式確實截然不同的。
excel97-2003(xls格式)
XLS文件最爲一個文件流(FileStream),是由多個子流(SubStream)構成的,下面這張圖是將各個SubStream按順序依次展現出來,這些SubStream都是有若干個整數倍Block(1 block = 512 bytes)組成。
SubStream |
|
XLS Header |
佔1個block(512bytes)固定大小 |
WorkBook |
最小佔8個block(4096bytes) |
Summary Information |
佔8個block(4096bytes)固定大小 |
Document Summary Information |
佔8個block(4096bytes)固定大小 |
XLS Header擴展區 |
只有.xls文件超過一定大小時,纔會出現 |
BigBolck pointer |
最小佔1個(512bytes) |
RootEntry |
佔1個block(512bytes) |
其中所有單元格數據記錄在WorkBook子流中,以下爲WorkBook區的重要內容結構。
0x0809 WorkbookHeader,即BOF,長度範圍1~20
offset |
size |
content |
0 |
2 |
存放XLS文件的版本類型 BIFF8/BIFF8X 0x0600 BIFF7 0x0500 |
2 |
2 |
WorkBookGlobals,0x0005 |
0x0031 FONT,長度24bytes。0x041EFORMAT
0x00E0 XF ExtendFORMAT
0x0293 STYLE
0x0085 BOUNDSHEET,即Sheet指針區,N個Sheet則有N個0x0085,包含每個Sheet的名稱、sheet數據內容在xls文件中的偏移量。
offset |
size |
content |
0 |
2 |
數據段長度(Sheet指針區和名稱區長度) |
2 |
4 |
該Sheet的BOF的絕對位移量,相對於Workbook |
6 |
Sheet名稱區,長度爲數據段長度-2 |
0x008C Country,語言和地區設置。
0x00FC SST內容(SharingStringTable用來存放字符串,目的是爲了讓各個sheet都能夠共享該SST中字符串內容)(Excel表數據,所有Sheet數據均放於此)
offset |
size |
content |
0 |
4 |
數據中所有字符串的數量 |
4 |
4 |
將要放在SST中字符串的數量 |
以下開始針對每個字符串進行循環處理 |
||
8 |
2 |
該字符串的長度,若爲雙字節字符也算做一個 |
10 |
1 |
字符串中若包含雙字節字符(如中文),則爲0x01,若爲純ASCII字符,則爲0x00 |
11 |
n |
存放字符串信息 |
0x00FF ExtendedSST內容 在讀取XLS文件時顯得不重要,但當創建XLS文件時卻非常重要
offset |
size |
content |
0 |
2 |
每一區塊字符串的個數,其值>=8 |
以下開始針對每一區塊字符串進行循環處理 |
||
2 |
4 |
每一區塊第一個字符的絕對位置 |
6 |
2 |
每一區塊第一個字符的相對位置 |
8 |
2 |
保留 |
0x0809 Sheet1內容
0x0809 Header,20bytes
0x020BIndex,16+4*N個字節
(注:注意標誌後有兩位Size位,要從Size位計起)
offset |
size |
content |
0 |
4 |
保留 |
4 |
4 |
第一行的序號 |
8 |
4 |
最後一行的序號(OpenOffice上介紹是sheet結尾的第一個未使用行的序號,行數的基數按0開始) |
10 |
4 |
指向DEFCOLWIDTH(0x0055)相對於Workbook Header的位置 |
14 |
4*N |
指向DBCELL(0x00D7)相對於WorkbookHeader的位置,當存在多個DBCELL時,需要設置多個。N爲該sheet的行數/32 |
0x0055 DEFCOLWIDTH,6bytes
0x0200 Dimensions,18byte,存放sheet1的行數和列數。
offset |
size |
content |
0 |
2 |
段大小(下列數據段大小) |
2 |
4 |
第一行的序號 |
6 |
4 |
最後一行的序號 |
10 |
2 |
第一列的序號 |
12 |
2 |
最後一列的序號 |
12 |
2 |
保留 |
RowBlock
0x0208 Row,20bytes,Sheet中有多少行就有對應多少個0x0208開頭的行信息,如果sheet中有5行,那麼RowBlock的大小就是20*5bytes
offset |
size |
content |
0 |
2 |
行的序號 |
2 |
2 |
列的序號 |
CellBlock
設置sheet中每一個單元格的信息,順序爲針對每一行的每一列依次設置,如00,01,02……10,11,12……20,21,22……
0x00FD LABELSST,14bytes,針對字符串值已經在SST中保存,這裏只保存其對應的序號。記錄文字串(在共享資料表裡)的Cell,格式爲:
2byte:第幾行(由0編起)
2byte:第幾列(由0編起)
2byte:XFrecord索引值
4byte:共享字串表的索引值
0x027E RK2,14bytes,針對RK值(指編過碼的整型或浮點型值)
0x00BD MULRK,28bytes記錄數字(多個連續列)的Cell,格式爲:
2byte:第幾行(由0編起)
2byte:起始列(由0編起)
?byte:RKCell資訊(每個6byte)
2byte:XFrecord索引值
4byte:RK數值(後述)
2byte:結束列(由0編起)
0x00D7 DBCELL,隨着行數的變化而發生變化
offset |
size |
content |
0 |
4 |
DBCELL的偏移量減去RowBlock中第一個Row的偏移量 |
4 |
2 |
CellBlock中首行的第一個Cell的偏移量減去RowBlock中第二個Row的偏移量 |
以下爲循環處理部分,1<n<=Max_Row |
||
6 |
2 |
CellBlock中第n行的第一個Cell的偏移量減去第n-1行的第一個Cell的偏移量 |
當XLS中的行數大於32時,系統將循環處理,對於每個32行內容單獨生成RowBlock、CellBlock和DBCELL。
0x0809 Sheet2內容
0x0809 Sheet3內容(如果有Sheet2、Sheet3)
0x000A EOF,Workbook結束標示符
==========這是吐槽線===========
這格式確實已經落後了,實在是太複雜。。。如果可以,我不再想碰這。
excel2007(xlsx格式)
xlsx格式相比舊的xls格式的數據結構要簡單的多,其使用xml格式進行存儲。
如下的表格:
A |
B |
C |
|
1 |
姓名 |
性別 |
年齡 |
2 |
張三 |
男 |
30 |
3 |
小明 |
男 |
16 |
4 |
小紅 |
女 |
20 |
然後將xlsx文件後綴改爲zip,用壓縮軟件打開,其內容存儲在sheet1.xml文件裏:
<sheetData>
<row r="1" spans="1:3" x14ac:dyDescent="0.2">
<c r="A1" t="s">
<v>0</v>
</c>
<c r="B1" t="s">
<v>2</v>
</c>
<c r="C1" t="s">
<v>1</v>
</c>
</row>
<row r="2" spans="1:3" x14ac:dyDescent="0.2">
<c r="A2" t="s">
<v>3</v>
</c>
<c r="B2" t="s">
<v>6</v>
</c>
<c r="C2">
<v>30</v>
</c>
</row>
<row r="3" spans="1:3" x14ac:dyDescent="0.2">
<c r="A3" t="s">
<v>4</v>
</c>
<c r="B3" t="s">
<v>6</v>
</c>
<c r="C3">
<v>16</v>
</c>
</row>
<row r="4" spans="1:3" x14ac:dyDescent="0.2">
<c r="A4" t="s">
<v>5</v>
</c>
<c r="B4" t="s">
<v>7</v>
</c>
<c r="C4">
<v>20</v>
</c>
</row>
</sheetData>
<c></c>標籤就代表每個單元格,t="s"表示值爲字符串,對應的字符串值可以在sharedStrings.xml裏找到:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<sst xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main" count="9" uniqueCount="8">
<si>
<t>姓名</t>
</si>
<si>
<t>年齡</t>
</si>
<si>
<t>性別</t>
</si>
<si>
<t>張三</t>
</si>
<si>
<t>小明</t>
</si>
<si>
<t>小紅</t>
</si>
<si>
<t>男</t>
</si>
<si>
<t>女</t>
</si>
</sst>
從兩個xml內容對比可知,第二個xml是Excel的內容去重後的內容集合,第一個項目xml通過集合的index來關聯第二個xml的內容