Excel 文件格式解析

微軟的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的內容


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章