1. 程式人生 > >RTF檔案格式研究報告

RTF檔案格式研究報告

這幾天正在寫一個編輯器,需要研究RTF檔案格式,以下是我收集的一個資料,非常實用。在隨後不長的時間內,我將釋出一款VB程式碼格式化的源程式。

RTF檔案格式研究報告(代開版辭)

摘要:本文對RTF檔案格式進行分析研究,對RTF檔案結構及特性進行了闡述,並分別列舉了幾個實用性的例子進行詳細分析,最終通過VB程式程式碼實現了一個RTF書寫器(不具有所見即所得特性)。本文對軟體開發人員及RTF檔案格式感興趣的人員具有參考價值。

關鍵字:RTF、Rich Text Format、Office、檔案格式。

一、引言

富文字格式(RTF)規範是為了便於在應用程式之間輕鬆轉儲格式化文字和圖形的一種編碼方法。現在,使用者可以利用特定轉換軟體,在不同系統如MS-DOS、Windows、OS/2、Macintosh和Power Macintosh的應用程式之間轉移字處理文件。RTF規範提供一種在不同的輸出裝置、操作環境和作業系統之間交換文字和圖形的一種格式。RTF使用ANSI, PC-8, Macintosh, 或IBM PC字符集控制文件的表示法和格式化,包括螢幕顯示和列印。憑藉RTF規範,不同的作業系統和不同的軟體程式建立的文件能夠在這些作業系統和應用程式之間傳遞。

將一個格式化的檔案轉換為RTF檔案的軟體稱為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》,這裡不作更詳細的說明。

三、HelloWord

國際慣例,一個Hello Word!演示例子,內容如下:

{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052

{\fonttbl{\f0\fmodern\fprq6\fcharset134\'cb\'ce\'cc\'e5;}}

{\*\generator Msftedit5.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 AsString) As String

    '將中文字串轉換為ASC串(包括英文一起)

    '先將特殊字元進行轉義:

    strIn =Replace(strIn, Chr(9), "\TAB ")

    strIn =Replace(strIn, Chr(13) + Chr(10), "\par ")

    Dim i As Long, s AsString, lsChar As String, lsPart1 As String, lsPart2 As String

    Dim lsCharHex AsString

    For i = 1 ToLen(strIn)

        lsChar= Mid(strIn, i, 1)

        IflsChar = "?" Then

            lsCharHex= LCase(Hex(Asc(lsChar)))

            IfLen(lsCharHex) = 4 Then

                lsCharHex= "\'" + Mid(lsCharHex, 1, 2) + "\'" + Mid(lsCharHex, 3, 2)

            Else

                lsCharHex= lsChar

            EndIf

            s= s + lsCharHex

        Else

            lsCharHex= LCase(Hex(Asc(lsChar)))

            IfLen(lsCharHex) = 4 Then

                lsCharHex= "\'" + Mid(lsCharHex, 1, 2) + "\'" + Mid(lsCharHex, 3, 2)

            Else

                lsCharHex= lsChar

            EndIf

            s= s + lsCharHex

        EndIf

    Next

    StrToASC = s

End Function

四、文字的更高階表示

掌握了基本文字表述方法後,你一定會試著進一步探索文字更高階的表示方法,如下劃線、顏色、粗體、斜體等等,而這些在V1.7規範中都作了詳細描述,本文只列出部分常用關鍵字,以供參考。

l 對於字體表和顏色表的說明:

對於我們在文件中使用的每一個字型和顏色,我們都必須在文件頭的字體表和顏色表中預先定義。

字體表定義的例子如下:

{\fonttbl

{\f0\froman\fcharset0\fprq2{\*\panose02020603050405020304}Times New Roman;}

{\f1\fswiss\fcharset0\fprq2{\*\panose020b0604020202020204}Arial;}

{\f10\fnil\fcharset2\fprq2{\*\panose05000000000000000000}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{\snshapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}{\sp{\sn fFlipV}{\sv 0}}{\sp{\snpibFlags}{\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

{\*\blipuidd48e1d9b2268ef9f2741709749fb439c}

ffd8ffe000104a46494600010101004800480000ffdb0043000604040405040605050609060506090b080606080b0c0a0a0b0a0a0c100c0c0c0c0c0c100c0e0f……}}

{\nonshppict {\pict\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw4516\pich4516\picwgoal2560\pichgoal2560\wmetafile8\bliptag-728883813\blipupi72

{\*\blipuidd48e1d9b2268ef9f2741709749fb439c}

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

{\*\blipuidd48e1d9b2268ef9f2741709749fb439c}

圖片16進位制資料:

ffd8ffe000104a46494600010101004800480000ffdb0043000604040405040605050609060506090b080606080b0c0a0a0b0a0a0c100c0c0c0c0c0c100c0e0f}16進製圖片資料結束

}

相容性wMetaFile檔案內容(可用省略):

{\nonshppict只用於相容,不讀取

{\pict圖片開始\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0\picw4516\pich4516\picwgoal2560\pichgoal2560\wmetafile8\bliptag-728883813\blipupi72

{\*\blipuidd48e1d9b2268ef9f2741709749fb439c}

下面是MetaFile型別的16進位制資料:

0100090000034660000000002160000000000400000003010800050000000b0200000000050000000c02ac00ac00030000001e00040000000701040021600000

}MetaFile型別16進製圖片資料結束

}

為了簡化分析,我們除去所以可以省略的內容,則一副圖片可以這樣表示:

{\*\shppict{\pictpiccropl0\piccropr0\piccropt0\piccropb0\picw寬度\pich高度\picwgoal顯示寬度\pichgoal顯示高度\jpegblipJPEG型別\bliptag-728883813ID值(為一個負的長整形值)

下面是該圖片的實際16進位制資料:

ffd8ffe0001… …}}

如果需要通過程式獲取指定圖片合法的16進位制字串,可以採用如下的VB函式:

Public Function PicToASC(ByVal strFileNameAs String) As String

    '獲取圖片16進位制資料

    Dim bData() As Byte

    Dim i As Long

    Dim lNum As Long

    Dim strData AsString, strTMP As String

    lNum = FreeFile

    Open strFileNameFor Binary As #lNum

    ReDimbData(LOF(lNum) - 1)

    Get #lNum, , bData

    Close #lNum

    strData =Space((UBound(bData) + 1) * 2)

    For i = 0 ToUBound(bData)

        strTMP= Hex$(bData(i))

        IfLen(strTMP) = 1 Then

            strTMP= "0" + strTMP

        EndIf

        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檔案基本結構如下:

     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檔案書寫器設計

基於對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 物件模型:

RTFCreator

RTFTexts

RTFText

RTFPictures

RTFPicture

RTFTables

RTFTables

RTFRows

RTFRow

RTFCells

RTFCell

RTFNodes

RTFNode

八、參考文獻

1、Rich Text Format(RTF) Specification v1.5,Microsoft TechnicalSupport, 5/97- GC0165

2、Rich TextFormat (RTF) Specification v1.7,MicrosoftTechnical Support, 8/2001– Word 2002 RTF Specification,下載地址:http://www.microsoft.com/downloads/details.aspx?familyid=e5b8ebc2-6ad6-49f0-8c90-e4f763e3f04f&displaylang=en