405
技術社區[雲棲]
RTF文件格式
摘要:本文對RTF文件格式進行分析研究,對RTF文件結構及特性進行了闡述,並分別列舉了幾個實用性的例子進行詳細分析,最終通過VB程序代碼實現了一個RTF書寫器(不具有所見即所得特性)。本文對軟件開發人員及RTF文件格式感興趣的人員具有參考價值。
關鍵字:RTF、Rich Text Format、Office、文件格式。
將一個格式化的文件轉換為RTF文件的軟件稱為RTF書寫器。RTF書寫器用於分離現有文本中的程序控製信息,並且生成一個包含文本和與之相關的RTF組的新文件。將RTF文件轉換成格式化文件的軟件則稱為RTF閱讀器。
RTF文件由未格式化本文、控製字、控製符和組組成。RTF文件沒有限製文件的行的最大長度。
控製字是RTF用來標記打印控製符和管理文檔信息的一種特殊格式的命令。一個控製字最長32個字符。控製字的使用格式如下:
/字母序列<分隔符>
注意:每個控製字均以一個反斜杠/開頭。字母序列由a~z 的小寫字母組成。控製字(或者稱為關鍵字)通常應該不包含任何大寫字母。
分隔符標記RTF控製字的結束, 可以是下列各項之一:
· 一個空格,這時空格是控製字的一部份。
· 一個數字或連字符(-), 表示跟隨的一個數值參數。該數字序列的長度由其後的一個空格或除了字母和數字的其他字符劃定。這個參數可以是正數或者負數,它的取值範圍通常是從-32767到32767。
· 任何非字母和數字的其他字符。這種情況下,此分隔字符結束控製字,而它並不屬於控製字的一部分。
控製符由一個反斜線/跟隨單個非字母字符組成。例如,/~代表一個不換行空格。控製符不需要分隔符。
組由包括在({})中的文本、控製字或控製符組成。左擴符({)表示組的開始,右擴符(})表示組的結束。每個組包括文本和文本的不同屬性。RTF文件也能同時包括字體、格式、屏幕顏色、圖形、腳注、注釋(注解)、文件頭和文件尾、摘要信息、域和書簽的組合,以及文檔、區段、段落和字符的格式屬性。如果包括字體、文件、格式、屏幕顏色、校訂標記,以及摘要信息組、文檔格式屬性,則他們一定要在文件的第一純文本字符之前,這些組形成RTF的文件頭。如果包括字體組,則它應該在格式組之前。如果組未使用,可以省略。
對於RTF文件的詳細語法及關鍵字說明請參閱《Rich Text Format (RTF) Specification v1.7》,這裏不作更詳細的說明。
國際慣例,一個Hello Word!演示例子,內容如下:
{/rtf1/ansi/ansicpg936/deff0/deflang1033/deflangfe2052
{/fonttbl{/f0/fmodern/fprq6/fcharset134 /'cb/'ce/'cc/'e5;}}
{/*/generator Msftedit 5.41.21.2500;}/viewkind4/uc1/pard/lang2052/f0/fs20 Hello World!/par}
該文件分析如下(紅色):
1、文件基本屬性:
{/rtf1 RTF版本/ansi字符集/ansicpg936簡體中文/deff0默認字體0/deflang1033美國英語/deflangfe2052中國漢語
2、字體表:
{/fonttbl{/f0字體0/fmodern/fprq6字體間距為6/fcharset134GB2312國標碼 /'cb/'ce/'cc/'e5宋體;}}
3、生成器信息:
{/*/generator Msftedit 5.41.21.2500;}
4、文檔屬性:
/viewkind4正常視圖/uc1單字節/pard默認段落屬性/lang2052中國漢語/f0字體0/fs20字體大小20磅
5、正文文本:
Hello World!/par段落標記
}文件結束
注意:在RTF文件中,中文等雙字節字符采用其單字節ASCII碼序列表示,例如文本“宋體ABC”應該表示為:/'cb/'ce/'cc/'e5ABC,這就是為什麼RTF可讀性差的原因。如果需要通過程序獲取某個字符串的合法ASCII序列,可以采用如下的VB函數:
Public Function StrToASC(ByVal strIn As String) As String
'將中文字符串轉換為ASC串(包括英文一起)
'先將特殊字符進行轉義:
strIn = Replace(strIn, Chr(9), "/TAB ")
strIn = Replace(strIn, Chr(13) + Chr(10), "/par ")
Dim i As Long, s As String, lsChar As String, lsPart1 As String, lsPart2 As String
Dim lsCharHex As String
For i = 1 To Len(strIn)
lsChar = Mid(strIn, i, 1)
If lsChar = "?" Then
lsCharHex = LCase(Hex(Asc(lsChar)))
If Len(lsCharHex) = 4 Then
lsCharHex = "/'" + Mid(lsCharHex, 1, 2) + "/'" + Mid(lsCharHex, 3, 2)
Else
lsCharHex = lsChar
End If
s = s + lsCharHex
Else
lsCharHex = LCase(Hex(Asc(lsChar)))
If Len(lsCharHex) = 4 Then
lsCharHex = "/'" + Mid(lsCharHex, 1, 2) + "/'" + Mid(lsCharHex, 3, 2)
Else
lsCharHex = lsChar
End If
s = s + lsCharHex
End If
Next
StrToASC = s
End Function
掌握了基本文字表述方法後,你一定會試著進一步探索文本更高級的表示方法,如下劃線、顏色、粗體、斜體等等,而這些在V1.7規範中都作了詳細描述,本文隻列出部分常用關鍵字,以供參考。
l 對於字體表和顏色表的說明:
對於我們在文檔中使用的每一個字體和顏色,我們都必須在文檔頭的字體表和顏色表中預先定義。
字體表定義的例子如下:
{/fonttbl
{/f0/froman/fcharset0/fprq2{/*/panose 02020603050405020304}Times New Roman;}
{/f1/fswiss/fcharset0/fprq2{/*/panose 020b0604020202020204}Arial;}
{/f10/fnil/fcharset2/fprq2{/*/panose 05000000000000000000}Wingdings;}
… …
}
我們在使用字體時,就可以直接指定字體表的一個索引,如:“/f1Happy”表示字體為Arial 的文本Happy。如果我們想加入其他字體,如“華文中宋”,那麼隻需要在字體表中加入該字體說明,並在需要時引用該字體索引值即可。方法為(華文中宋的ASCII串為“/'bb/'aa/'ce/'c4/'d6/'d0/'cb/'ce”):{f222/fnil/fcharset134/fprq2/'bb/'aa/'ce/'c4/'d6/'d0/'cb/'ce;},然後通過/f222來引用該字體即可。
{/colortbl;/red0/green0/blue0;/red0/green0/blue255;/red0/green255/blue255;/red0/green255/blue0;/red255/green0/blue255;/red255/green0/blue0;/red255/green255/blue0;/red255/green255/blue255;/red0/green0/blue128;/red0/green128/blue128;/red0/green128/blue0;/red128/green0/blue128;/red128/green0/blue0;/red128/green128/blue0;/red128/green128/blue128;/red192/green192/blue192; … …}
顏色表中每個顏色值采用RGB格式書寫,每個顏色用分號格開,注意第一個顏色值/c0為空,表示係統默認顏色(一般為黑色)。依次為:/0、/1、/2、… …。我們在使用顏色時(如字體顏色)就可以指定某一個顏色索引值,如“/cf2Sunday”表示字體顏色為RGB(0,0,255)藍色的文字Sundy。“/cb6ABC”表示字體背景色為RGB(255,0,0)的文字“ABC”。如果我們需要加入其他顏色值,隻需要在顏色表中加入顏色定義,並通過相應的索引值來引用它即可。
l 字符底紋語法如下:
控製字 |
涵義 |
/chbrdr |
字符邊框(每邊均有邊框)。 |
/chshdngN |
字符陰影。參數N的值文字陰影的百分比。 |
/chcfpatN |
N是背景圖案的顏色,指定文檔顏色表的一個索引。 |
/chcbpatN |
N是填充色,指定文檔顏色表的一個索引。 |
/chbghoriz |
指定水平線文本背景圖案。 |
/chbgvert |
指定垂直線文本背景圖案。 |
/chbgfdiag |
指定正向對角線文本背景圖案(////)。 |
/chbgbdiag |
指定反向對角線文本背景圖案(////)。 |
/chbgcross |
指定十字線文本背景圖案。 |
/chbgdcross |
指定對角十字線文本背景圖案。 |
/chbgdkhoriz |
指定粗水平線文本背景圖案。 |
/chbgdkvert |
指定粗垂直線文本背景圖案。 |
/chbgdkfdiag |
指定粗前斜線文本背景圖案(////)。 |
/chbgdkbdiag |
指定粗後斜線文本背景圖案(////)。 |
/chbgdkcross |
指定粗十字線文本背景圖案。 |
/chbgdkdcross |
指定粗對角十字線文本背景圖案。 |
假設我們希望得到背景為水平線、字體為華文中宋(字體索引為222)、顏色為紅色(顏色索引為6)的文本“星期天”,則隻需輸入:/f222/cf6/'bb/'aa/'ce/'c4/'d6/'d0/'cb/'ce 即可。
l 字符下劃線語法如下:
控製字 |
涵義 |
/ul |
連續的下劃線。/ul0關閉所有下劃線。 |
/ulcN |
下劃線顏色。(注意:大寫N表示一個索引數字,下同) |
/uld |
點下劃線。 |
/uldash |
短劃下劃線。 |
/uldashd |
點劃下劃線。 |
/uldashdd |
雙點劃下劃線。 |
/uldb |
雙下劃線。 |
/ulhwave |
加重波浪下劃線。 |
/ulldash |
長劃下劃線。 |
/ulnone |
停止所有下劃線。 |
/ulth |
粗下劃線。 |
/ulthd |
粗點下劃線。 |
/ulthdash |
粗短劃下劃線。 |
/ulthdashd |
粗點劃下劃線。 |
/ulthdashdd |
粗雙點劃下劃線。 |
/ulthldash |
粗長劃下劃線。 |
/ululdbwave |
雙波浪下劃線。 |
/ulw |
字下加下劃線。 |
/ulwave |
波浪下劃線。 |
下劃線語法與前麵底紋的使用相同。
l 其他文本顯示高級屬性:
控製字 |
涵義 |
/outl |
邊框。/ outl 0關閉之。 |
/scaps |
小體大寫字母。/ scaps 0關閉之。 |
/shad |
陰影。/ shad 0關閉之。 |
/strike |
刪除線。/strike0關閉之。 |
/striked1 |
雙刪除線。/striked0關閉之。 |
/sub |
按照字體信息的下標文本和縮小點的尺寸。 |
/super |
按照字體信息的上標文本和縮小點的尺寸。 |
l 對齊方式語法如下:
控製字 |
涵義 |
/qc |
居中對齊。 |
/qj |
兩端對齊。 |
/ql |
左對齊(默認)。 |
/qr |
右對齊。 |
/qd |
分散對齊。 |
/qkN |
使用Kashida規則調整行百分比(0-低、10-中、20-高)。 |
/qt |
.用於泰文的分散對齊。 |
l 文本縮進語法如下:
控製字 |
涵義 |
/fiN |
首行縮進(默認為0)。 |
/cufiN |
采用字符單位的百分比的首行縮進值,用以覆蓋/fiN的設置,雖然它們可以設為相同值。 |
/liN |
左端縮進(默認為0)。 |
/linN |
從左至右段落的左端縮進值;如果在從右至左段落則表示右端縮進值(默認為0)。/linN定義了段前空格數。 |
/culiN |
采用字符單位的百分比的左端縮進值,與/linN一樣,它用以覆蓋/liN和/linN的設置,雖然它們可以設為相同值。 |
/riN |
右縮進(默認為0)。 |
/rinN |
從左至右段落的右端縮進值;如果在從右至左段落則表示左端縮進值(默認為0)。/rinN定義了段前空格數。 |
/curiN |
采用字符單位的百分比的右端縮進值,與/rinN一樣,它用以覆蓋/riN和/rinN的設置,雖然它們可以設為相同值。 |
/adjustright |
當文檔網格被定義時自動調整右縮進。 |
l 文本間距語法如下:
/sbN |
段後間隔(默認為0)。 |
/saN |
段前間隔(默認為0)。 |
/sbautoN |
自動段前間隔: 0 段前間距取決於/sb。 1 自動段前間距(忽略/sb)。
默認為0。
|
/saautoN |
自動段後間隔: 0 段後間距取決於/sa。 1 自動段後間距(忽略/sa) 默認為0。 |
/lisbN |
采用字符單位的百分比的段前間隔值,用以覆蓋/sbN的設置,雖然它們可以設為相同值。 |
/lisaN |
采用字符單位的百分比的段後間隔值,用以覆蓋/saN的設置,雖然它們可以設為相同值。 |
/slN |
行間距。如果沒有使用該控製字或者使用/sl0,則行間距將根據行間字符最高值自動取值。若N為一個正值,則該值將僅僅在該值大於行間字符最高值時才使用(否則,使用字符最高值);分N是一個負值,即使在其小於行間字符最高值時,總是使用N的絕對值。 |
/slmultN |
多倍行間距。指出當前行間距是單倍行距的倍數。該控製字隻能跟在/sl後,聯合作用。 0 “最小”或者是“精確”的行距 1 多倍行距,相對於“單倍”行距。 |
/nosnaplinegrid |
取消對齊網格線。 |
因為篇幅限製,更詳細的文本格式分析請參閱附件裏的文本示例分析原文。
摸清RTF中圖片的表示頗費了一番周折,下麵的分析希望能夠加速你的學習進程。一個RTF圖片數據通常直接嵌入文件中,這些圖象可以是16進製(默認的)或2進製格式。圖象屬於目標引用,由/pict 控製字開始。如後麵的例子中將描述的,/pict關鍵字應在/*/shppict引用控製關鍵字之後。
一個圖象的例子如下:
{/*/shppict{/pict
{/*/picprop/shplid1025{/sp{/sn shapeType}{/sv 75}}{/sp{/sn fFlipH}{/sv 0}}{/sp{/sn fFlipV}{/sv 0}}{/sp{/sn pibFlags}{/sv 2}}{/sp{/sn fLine}{/sv 0}}{/sp{/sn fLayoutInCell}{/sv 1}}}
/picscalex100/picscaley100/piccropl0/piccropr0/piccropt0/piccropb0/picw4516/pich4516/picwgoal2560/pichgoal2560/jpegblip/bliptag-728883813
{/*/blipuid d48e1d9b2268ef9f2741709749fb439c}
ffd8ffe000104a46494600010101004800480000ffdb0043000604040405040605050609060506090b080606080b0c0a0a0b0a0a0c100c0c0c0c0c0c100c0e0f… …}}
{/nonshppict {/pict/picscalex100/picscaley100/piccropl0/piccropr0/piccropt0/piccropb0/picw4516/pich4516/picwgoal2560/pichgoal2560/wmetafile8/bliptag-728883813/blipupi72
{/*/blipuid d48e1d9b2268ef9f2741709749fb439c}
0100090000034660000000002160000000000400000003010800050000000b0200000000050000000c02ac00ac00030000001e00040000000701040021600000… …}}
其分析如下(紅色):
{/*/shppict圖片(引用)
{/pict圖片開始
繪圖對象屬性(這個組可以省略):
{/*/picprop表示這裏是應用於一個內嵌圖象的形狀屬性/shplid1025標識每個圖形的唯一數值
{/sp繪圖對象屬性定義
{/sn shapeType}{/sv 75}} 圖片類型為相框
{/sp{/sn fFlipH}{/sv 0}} 水平翻轉:False
{/sp{/sn fFlipV}{/sv 0}} 垂直翻轉:False
{/sp{/sn pibFlags}{/sv 2}} 鏈接圖片標誌
{/sp{/sn fLine}{/sv 0}}具有線條:False
{/sp{/sn fLayoutInCell}{/sv 1}}允許圖形錨點定位在單元格內部:True
}繪圖對象屬性定義結束
圖片屬性:
/picscalex100水平縮放比例/picscaley100垂直縮放比例
/piccropl0左端剪切值=0/piccropr0右端剪切值=0/piccropt0上端剪切值=0/piccropb0下端剪切值=0
/picw4516圖片的像素寬度/pich4516圖片的像素高度/picwgoal2560圖象期望寬度/pichgoal2560圖象期望高度/jpegblip圖片源為一個JPEG文件/bliptag圖象ID標識-728883813
{/*/blipuid d48e1d9b2268ef9f2741709749fb439c}
圖片16進製數據:
ffd8ffe000104a46494600010101004800480000ffdb0043000604040405040605050609060506090b080606080b0c0a0a0b0a0a0c100c0c0c0c0c0c100c0e0f}16進製圖片數據結束
}
兼容性wMetaFile文件內容(可用省略):
{/nonshppict隻用於兼容,不讀取
{/pict圖片開始/picscalex100/picscaley100/piccropl0/piccropr0/piccropt0/piccropb0/picw4516/pich4516/picwgoal2560/pichgoal2560/wmetafile8/bliptag-728883813/blipupi72
{/*/blipuid d48e1d9b2268ef9f2741709749fb439c}
下麵是MetaFile類型的16進製數據:
0100090000034660000000002160000000000400000003010800050000000b0200000000050000000c02ac00ac00030000001e00040000000701040021600000
}MetaFile類型16進製圖片數據結束
}
為了簡化分析,我們除去所以可以省略的內容,則一副圖片可以這樣表示:
{/*/shppict{/pict piccropl0/piccropr0/piccropt0/piccropb0/picw寬度/pich高度/picwgoal顯示寬度/pichgoal顯示高度/jpegblipJPEG類型/bliptag-728883813ID值(為一個負的長整形值)
下麵是該圖片的實際16進製數據:
ffd8ffe0001… …}}
如果需要通過程序獲取指定圖片合法的16進製字符串,可以采用如下的VB函數:
Public Function PicToASC(ByVal strFileName As String) As String
'獲取圖片16進製數據
Dim bData() As Byte
Dim i As Long
Dim lNum As Long
Dim strData As String, strTMP As String
lNum = FreeFile
Open strFileName For Binary As #lNum
ReDim bData(LOF(lNum) - 1)
Get #lNum, , bData
Close #lNum
strData = Space((UBound(bData) + 1) * 2)
For i = 0 To UBound(bData)
strTMP = Hex$(bData(i))
If Len(strTMP) = 1 Then
strTMP = "0" + strTMP
End If
Mid(strData, i * 2 + 1) = strTMP
Next
PicToASC = strData
End Function
上麵對文本和圖片都進行了分析,相信你已經對RTF文件格式有了一定體會,接下來說明RTF文件中表的表示方法。表的定義稍顯複雜,不過還是有規律可循的。不存在RTF表組,實際上表由段落屬性來描述。一個表表現為多個表行的順序排列。一個表行是一個由不同單元格組成的段落序列。簡言之,表格由行組成,行由單元格組成。不管有多複雜的表格,它都是通過一行接一行的描述來實現的,包括表格的嵌套。表行從控製字/trowd開始,/row結束。包含在一個表行中的每個段落必須指定/intbl控製字或者從前一段落繼承。一個單元內可能有多個段落;單元由單元格標誌(/cell控製字)結束,行由行標誌(/row控製字)結束。表行也可以被絕對定位。此時,表行的每個段落必須具有相同的定位控製字。表的屬性可以從前一行繼承;因此,連續的表行可以通過單一的<tbldef>來定義。
一個簡單表格例子如下:
1,1
|
1,2
|
1,3
|
2,1
|
2,2
|
2,3
|
RTF內容如下:
/trowd /irow0/irowband0/ts15/trgaph108/trleft-108/trbrdrt
/brdrs/brdrw10 /trbrdrl/brdrs/brdrw10 /trbrdrb/brdrs/brdrw10 /trbrdrr/brdrs/brdrw10 /trbrdrh/brdrs/brdrw10 /trbrdrv/brdrs/brdrw10
/trftsWidth1/trftsWidthB3/trautofit1/trpaddl108/trpaddr108/trpaddfl3/trpaddft3/trpaddfb3/trpaddfr3/tblrsid2113686/tbllkhdrrows/tbllklastrow/tbllkhdrcols/tbllklastcol /clvertalt/clbrdrt/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr
/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2840/clshdrawnil /cellx2732/clvertalt/clbrdrt/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2841/clshdrawnil /cellx5573/clvertalt/clbrdrt
/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2841/clshdrawnil /cellx8414/pard/plain /qj /li0/ri0/nowidctlpar/intbl/aspalpha/aspnum/faauto/adjustright/rin0/lin0/yts15
/fs21/lang1033/langfe2052/kerning2/loch/af0/hich/af0/dbch/af13/cgrid/langnp1033/langfenp2052 {/insrsid2113686 /hich/af0/dbch/af13/loch/f0 1,1/cell /hich/af0/dbch/af13/loch/f0 1,2/cell /hich/af0/dbch/af13/loch/f0 1,3/cell }/pard/plain
/ql /li0/ri0/widctlpar/intbl/aspalpha/aspnum/faauto/adjustright/rin0/lin0 /fs21/lang1033/langfe2052/kerning2/loch/af0/hich/af0/dbch/af13/cgrid/langnp1033/langfenp2052 {/insrsid2113686 /trowd /irow0/irowband0/ts15/trgaph108/trleft-108/trbrdrt
/brdrs/brdrw10 /trbrdrl/brdrs/brdrw10 /trbrdrb/brdrs/brdrw10 /trbrdrr/brdrs/brdrw10 /trbrdrh/brdrs/brdrw10 /trbrdrv/brdrs/brdrw10
/trftsWidth1/trftsWidthB3/trautofit1/trpaddl108/trpaddr108/trpaddfl3/trpaddft3/trpaddfb3/trpaddfr3/tblrsid2113686/tbllkhdrrows/tbllklastrow/tbllkhdrcols/tbllklastcol /clvertalt/clbrdrt/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr
/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2840/clshdrawnil /cellx2732/clvertalt/clbrdrt/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2841/clshdrawnil /cellx5573/clvertalt/clbrdrt
/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2841/clshdrawnil /cellx8414/row }/pard/plain /qj /li0/ri0/nowidctlpar/intbl/aspalpha/aspnum/faauto/adjustright/rin0/lin0/yts15
/fs21/lang1033/langfe2052/kerning2/loch/af0/hich/af0/dbch/af13/cgrid/langnp1033/langfenp2052 {/insrsid2113686 /hich/af0/dbch/af13/loch/f0 2,1/cell /hich/af0/dbch/af13/loch/f0 2,2/cell /hich/af0/dbch/af13/loch/f0 2,3/cell }/pard/plain
/ql /li0/ri0/widctlpar/intbl/aspalpha/aspnum/faauto/adjustright/rin0/lin0 /fs21/lang1033/langfe2052/kerning2/loch/af0/hich/af0/dbch/af13/cgrid/langnp1033/langfenp2052 {/insrsid2113686 /trowd /irow1/irowband1/lastrow /ts15/trgaph108/trleft-108/trbrdrt
/brdrs/brdrw10 /trbrdrl/brdrs/brdrw10 /trbrdrb/brdrs/brdrw10 /trbrdrr/brdrs/brdrw10 /trbrdrh/brdrs/brdrw10 /trbrdrv/brdrs/brdrw10
/trftsWidth1/trftsWidthB3/trautofit1/trpaddl108/trpaddr108/trpaddfl3/trpaddft3/trpaddfb3/trpaddfr3/tblrsid2113686/tbllkhdrrows/tbllklastrow/tbllkhdrcols/tbllklastcol /clvertalt/clbrdrt/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr
/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2840/clshdrawnil /cellx2732/clvertalt/clbrdrt/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2841/clshdrawnil /cellx5573/clvertalt/clbrdrt
/brdrs/brdrw10 /clbrdrl/brdrs/brdrw10 /clbrdrb/brdrs/brdrw10 /clbrdrr/brdrs/brdrw10 /cltxlrtb/clftsWidth3/clwWidth2841/clshdrawnil /cellx8414/row }
是不是很複雜?不過沒關係,我們通過對其進行分段,並加入適當注釋,你就會對RTF文件中的表結構一目了然。首先需要聲明的是,RTF1.7規範中規定,表行的格式如下:(<tbldef> <cell>+ <tbldef> /row) | (<tbldef> <cell>+ /row) | (<cell>+ <tbldef> /row),目前Word2003采用的方式就是第一種,即“定義+內容+重複定義”,如此一來就會有很大的數據冗餘,這就是為什麼Word2003的一個簡單文檔都會很大的原因,不過為了兼容性考慮,這樣處理也是必要的。其定義也由“行定義+單元格定義”組成,其中單元格定義可用重複。
分析代碼如下(紅色):
表格行1
/trowd表行1開始
表格屬性
/trgaph108表中單元格半間距/trleft-108表的最左邊位置
行邊框設置
/trbrdrt行的上邊框/brdrs單倍厚度/brdrw10線寬
/trbrdrl行的左邊框/brdrs單倍厚度/brdrw10線寬
/trbrdrb行的下邊框/brdrs單倍厚度/brdrw10線寬
/trbrdrr行的右邊框/brdrs單倍厚度/brdrw10線寬
單元格1邊框設置
/clbrdrt單元格上邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrl單元格左邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrb單元格下邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrr單元格右邊框/brdrw15線寬/brdrs單倍厚度
/cellx2732單元格右邊界
單元格2邊框設置
/clbrdrt單元格上邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrl單元格左邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrb單元格下邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrr單元格右邊框/brdrw15線寬/brdrs單倍厚度
/cellx5573單元格右邊界
單元格3邊框設置
/clbrdrt單元格上邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrl單元格左邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrb單元格下邊框/brdrw15線寬/brdrs單倍厚度
/clbrdrr單元格右邊框/brdrw15線寬/brdrs單倍厚度
/cellx8414單元格右邊界
行1數據
/pard重置段落屬性/intbl段落是表的一部分/kerning2緊縮字符尺寸/f0字體0/fs21尺寸21
1,1 1,1 /cell表單元格1結束
1,2 1,2 /cell表單元格2結束
1,3 1,3 /cell表單元格3結束
/f1字體1
/row表行1結束
/f0字體0
表格行2
/trowd表行2開始
/trgaph108表中單元格半間距/trleft-108表的最左邊位置
行邊框設置
/trbrdrt/brdrs/brdrw10
/trbrdrl/brdrs/brdrw10
/trbrdrb/brdrs/brdrw10
/trbrdrr/brdrs/brdrw10
單元格1邊框設置
/clbrdrt/brdrw15/brdrs
/clbrdrl/brdrw15/brdrs
/clbrdrb/brdrw15/brdrs
/clbrdrr/brdrw15/brdrs
/cellx2732
單元格2邊框設置
/clbrdrt/brdrw15/brdrs
/clbrdrl/brdrw15/brdrs
/clbrdrb/brdrw15/brdrs
/clbrdrr/brdrw15/brdrs
/cellx5573
單元格3邊框設置
/clbrdrt/brdrw15/brdrs
/clbrdrl/brdrw15/brdrs
/clbrdrb/brdrw15/brdrs
/clbrdrr/brdrw15/brdrs
/cellx8414
行2數據
/intbl 段落是表的一部分
2,1 2,1/cell表單元格1結束
2,2 2,2/cell表單元格2結束
2,3 2,3/cell表單元格3結束
/f1字體1
/row表行2結束
至此,你應該對RTF表格輸出有一定認識了吧。當然在表格中插入圖片、嵌入表格等的實現方法同理,嵌入的圖片可以等同於一段文本來處理,但是嵌套表格的實現可能比較複雜,因為它涉及段落文本嵌套層次等高級問題,這裏不再詳述,有興趣的讀者可以參考《Rich Text Format (RTF) Specification v1.7》。
通過對RTF文件的分析,我們得出一個RTF文件基本結構如下:
RTF文件<File>
文件頭<header>
RTF版本/rtf
字符集<charset>
默認字體區域設置<deffont>
默認字體號/deff?
字體表<fonttbl>
文件表<filetbl>?
顏色表<colortbl>?
樣式表<stylesheet>?
編目表<listtables>?
編目表{ /*/listtable }
編目替換表{ /*/listoverridetable }
段落組屬性{ /*/pgptbl }
跟蹤修訂<revtbl>?
RSID表<rsidtable>?
生成器信息<generator>?
文檔區<document>
文檔信息區<info>?
標題<title>?
主題<subject>?
作者<author>?
經理<manager>?
公司<company>?
最後修改者<operator>?
文檔類別<category>?
關鍵字<keywords>?
注釋<comment>?
文檔的版本號/version?
Word摘要信息中的注釋<doccomm>?
內部版本號/vern?
創建時間<creatim>?
修訂時間<revtim>?
最後打印時間<printim>?
備份時間<buptim>?
總編輯時間(單位:分鍾)/edmins?
頁數/nofpages?
字數/nofwords?
包含空格的總字符數/nofchars?
內部ID號/id?
文檔格式屬性<docfmt>*
節文本<section>+
節格式屬性<secfmt>*
頁眉頁腳設置<hdrftr>?
段落文本<para>+
文本<textpar>|
項目符號與編號<pn>?
段落邊框<brdrdef>?
段落格式屬性<parfmt>*
定位對象與邊框<apoctl>*
製表位設置<tabdef>?
段落底紋<shading>?
隱藏與否(/v /spv)?
表格<row>
行開始/trowd
行定義<tbldef>
單元格<cell>+
單元格定義+
單元格內容+
重複行定義<tbldef>
行結束/row
字符文本<char>+
圖片<pict>
圖片開始{/*/shppict {/pict }
圖片屬性
圖片數據
對象<obj>
繪圖對象/shp
腳注/footnote
注釋<annot>
域<field>
基於對RTF的學習運用,我通過VB實現了一個RTF輸出工具類,可以實現文本、圖片、表格(可以嵌入特殊文本、圖片和水平、垂直合並)。基於此工具的病曆示範輸出也通過了基本測試。更進一步的研究和完善將在接下來的時間進行。
詳細描述如下:
l RTF文檔:
可以添加文本、圖片、表格,支持頁眉、頁腳、頁碼、頁眉對齊方式、頁腳對齊方式、頁碼對齊方式。
基本方法:
Dim myRTF as New RTFCreator.clsRTFCreator
With myRTF
.PageHead = "頁眉" ‘頁眉
.PageHeadAlign = alm1_左端對齊 ‘頁眉對齊方式
.PageFooter = "時間:" & Format(Now, "YYYY年MM月DD日 HH:nn:ss") ‘頁腳
.PageNumber = True ‘是否顯示頁碼
.PageNumberAlign = alm3_居右對齊 ‘頁碼對齊方式
End With
l 文本:
可以實現粗體、斜體、前景色(目前為固定顏色表)、字體大小、字體樣式(目前為固定樣式)、字符樣式(目前為固定樣式)、動畫、水平縮放、雕刻、浮雕、字符間距、邊框、陰影、刪除線、雙刪除線、下標、上標、下劃線(17種)、下劃線顏色、隱藏文本、WEB下隱藏、字符邊框(陰文)、字符陰影(陽文)、底紋背景色、底紋前景色、底紋樣式(12種)、高亮顯示、高亮顏色、對齊方式、項目符號等。
基本方法:
.AddText ‘添加文本,也可用.AddText “文本內容”,或者通過i=.AddText(“AAA”)返回索引值I,然後通過myRTF.Texts(i).Bold=True來設置屬性。
.LastText.Bold = True ‘粗體設置
.LastText.FontStyle = ft1_標題1 ‘字體尺寸設置
.LastText = "文本" & vbCrLf ‘文本設置,如果需要回車,直接添加vbCrLf到文本中適當位置
.LastText.Alignment = alm2_居中對齊 ‘對齊方式
…其他設置
l 圖片:
可以插入JPEG、GIF等圖片,已經對輸出速度進行了優化。可以設置圖片對齊方式、文件名、大小、縮放比例、是否單獨一行等。
使用方法:
.AddPicture (CommonDialog2.FileName) ‘文件名
.LastPicture.AddCRLF = True ‘獨立一行
.LastPicture….其他設置(如對圖像尺寸的設置)
l 表格:
可以設置單元格水平對齊、垂直對齊、上下左右邊框是否存在、是否包含內部斜線(左上、左下)、邊框樣式(支持28種邊框)、邊框顏色、底紋類型、底紋背景色、底紋前景色、底紋明暗百分比、單元格寬度單位、單元格首選寬度、單元格右邊界、是否是水平合並的首單元格、是否與前一單元水平合並、是否是垂直合並的首單元格、是否與前一定義垂直合並、行數、列數、文本適應單元格、不允許文本換行、是否嵌套、數據類型(目前支持簡單文本、高級文本、圖片三種類型,嵌套表格暫時不支持)。
使用方法:
myRTF.Addtable
With myRTF.LastTable
.Alignment = ral2_居中對齊
.AddRow '插入第1行
.LastRow.AddCell '第1行,第1列(該單元格為簡單文本、默認)
.LastRow.BorderStyle = cbs03_雙倍厚度邊框
.LastRow.BorderColor = clr02_藍色
.LastRow.BorderWidth = 75
.LastRow.AddCell '第1行,第2列(該單元格為高級文本,需要賦值)
Dim rtfTxt1 As cRTFText
Set rtfTxt1 = New cRTFText
.LastCell.DataType = cct1_高級文本
rtfTxt1.Bold = True
rtfTxt1.Text = "第(1,2)單元格內容:高級文本"
rtfTxt1.ForeColor = clr06_大紅
rtfTxt1.FontSize = fs09_四號
Set .LastCell = rtfTxt1
.LastCell.MergeStart = True
.LastCell.BorderStyle = cbs25_雙波浪線邊框
.LastCell.BorderWidth = 75
.LastCell.BorderColor = clr10_深青
…其他設置
l 對象模型:最後更新:2017-04-03 18:51:47