摘要: 本文对RTF文件格式进行分析研究,对RTF文件结构及特性进行了阐述,并分别列举了几个有用性的样例进行具体分析,

终于通过VB程序代码实现了一个RTF书写器(不具有所见即所得特性)。本文对软件开发者及RTF文件格式感兴趣的人员具有參考价值。

keyword: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 的小写字母组成。控制字(或者称为keyword)通常应该不包括不论什么大写字母。

分隔符标记RTF控制字的结束, 能够是下列各项之中的一个:

·      一个空格,这时空格是控制字的一部份。

·      一个数字或连字符(-), 表示尾随的一个数值參数。该数字序列的长度由其后的一个空格或除了字母和数字的其它字符划定。这个參数能够是正数或者负数,它的取值范围一般是从-32767到32767。

·      不论什么非字母和数字的其它字符。这样的情况下,此分隔字符结束控制字,而它并不属于控制字的一部分。

控制符由一个反斜线\尾随单个非字母字符组成。比如,\~代表一个不换行空格。控制符不须要分隔符。

组由包含在({})中的文本、控制字或控制符组成。左扩符({)表示组的開始,右扩符(})表示组的结束。每一个组包含文本和文本的不同属性。RTF文件也能同一时候包含字体、格式、屏幕颜色、图形、脚注、凝视(注解)、文件头和文件尾、摘要信息、域和书签的组合,以及文档、区段、段落和字符的格式属性。假设包含字体、文件、格式、屏幕颜色、校订标记,以及摘要信息组、文档格式属性,则他们一定要在文件的第一纯文本字符之前,这些组形成RTF的文件头。假设包含字体组,则它应该在格式组之前。假设组未使用,能够省略。

对于RTF文件的具体语法及keyword说明请參阅《Rich Text Format (RTF) Specification v1.7》,这里不作更具体的说明。

三、Hello Word

国际惯例,一个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规范中都作了具体描写叙述,本文仅仅列出部分经常使用keyword,以供參考。

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 控制字開始。如后面的样例中将描写叙述的,\pictkeyword应在\*\shppict引用控制keyword之后。

一个图象的样例例如以下:

{\*\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文件基本结构例如以下:

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

分享到:

RTF 格式 说明的更多相关文章

  1. rtf格式的一些说明,转载的

    RTF是Rich TextFormat的缩写,意即多文本格式.这是一种类似DOC格式(Word文档)的文件,有很好的兼容性,使用Windows"附件"中的"写字板&quo ...

  2. RTF格式文件浅析

    ps:这两天在分析从微软的word复制一个绕排环绕的表格到openoffice的writer中去的bug,需要了解RTF... RTF是Rich TextFormat的缩写,意即多文本格式.这是一种类 ...

  3. rtf格式 C#设置字间距 CharacterSpacing

    richtextbox空间中操作行间距段间距都可以用发送消息解决,但是字间距却鲜有人关注,无法通过PARAFORMAT2消息解决,只能直接操作rtf格式 字间距主要就是要控制 expand expan ...

  4. 一次查找Windows Live Writer的VSPaste插件丢失RTF格式信息的经历

    背景 我在博客园上写博客是使用Windows Live Writer,代码高亮插件是使用Paste from Visual Studio(下文简称VSPaste). Windows Live Writ ...

  5. 如何在CRichEditCtrl控件中直接读如RTF格式的文件(这个是通过流的方式来读取文件)

    如何在CRichEditCtrl控件中直接读如RTF格式的文件   Inserting an RTF string using StreamIn   ------------------------- ...

  6. c#如何保存richtextbox的rtf格式

    C# codethis.rtbText.Rtf = @"{\rtf1\ansi\ansicpg936\deff0\deflang1033\deflangfe2052" + @&qu ...

  7. 在RichTextBox控件中显示RTF格式文件

    实现效果: 知识运用:    RichTextBox控件的LoadFile方法 //将文件内容加载到RichTextBox控件中 public void LoadFile(string path,Ri ...

  8. 如何用C#把Doc文档转换成rtf格式

    先在项目引用里添加上对Microsoft Word 9.0 object library的引用 using System; namespace DocConvert { class DoctoRtf ...

  9. delphi从TRichEdit获得RTF格式文本(PC版本)

    function GetRTF(RE: TRichedit): string;varstrStream: TStringStream;beginstrStream := TStringStream.C ...

随机推荐

  1. Tair是一个高性能,分布式,可扩展,高可靠的key/value结构存储系统(转)

    Tair是一个高性能,分布式,可扩展,高可靠的key/value结构存储系统! Tair专为小文件优化,并提供简单易用的接口(类似Map)Tair支持Java和C版本的客户端 Tair is a di ...

  2. perl lwp 获取请求头

    <pre name="code" class="html">[root@dr-mysql01 ~]# cat getx.pl use LWP::Us ...

  3. PowerShell 在线教程 4

    PowerShell 在线教程 4   认识Powershell 介绍和安装 自定义控制台 快速编辑模式和标准模式 快捷键 管道和重定向 Powershell交互式 数学运算 执行外部命令 命令集 别 ...

  4. <摘录>详谈高性能UDP服务器的开发

    上一篇文章我详细介绍了如何开发一款高性能的TCP服务器的网络传输层.本章我将谈谈如何开发一个高性能的UDP服务器的网络层.UDP服务器的网络层开 发相对与TCP服务器来说要容易和简单的多,UDP服务器 ...

  5. [Oracle] 常用工具集之 - SQL*Loader

    SQL*Loader原理 SQL*Loader是Oracle提供的用于数据加载的一种工具,它比较适合业务分析类型数据库(数据仓库),能处理多种格式的平面文件,批量数据装载比传统的数据插入效率更高.其示 ...

  6. Api之Cors跨域以及其他跨域方式

    Web Api之Cors跨域以及其他跨域方式(三)   我们知道ajax不能跨域访问,但是有时我们确实需要跨域访问获取数据,所以JSONP就此诞生了,其本质使用的是Script标签,除JSONP以外还 ...

  7. 不断摸索发现用 andy 模拟器很不错,感觉跟真机差不多

    嗯,今天也遇到了模拟的问题.那个慢啊,好几分钟才能开机,加载程序总共差不多十几分钟.当时想如果真做android开发必须换电脑啊.后来不断摸索发现用 andy 模拟器很不错,感觉跟真机差不多. 还是真 ...

  8. Android 开源项目android-open-project工具库解析之(一) 依赖注入,图片缓存,网络相关,数据库orm工具包,Android公共库

    一.依赖注入DI 通过依赖注入降低View.服务.资源简化初始化.事件绑定等反复繁琐工作 AndroidAnnotations(Code Diet) android高速开发框架 项目地址:https: ...

  9. java泛型 之 入门(interface)

    一:泛型简单介绍: (1)所谓泛型,就是变量类型的參数化. 泛型是JDK1.5中一个最重要的特征.通过引入泛型,我们将获得编译时类型的安全和执行时更小的抛出ClassCastException的可能. ...

  10. POJ 2365 Rope(水题)

    [题意简述]:给出我们钉子个数与半径,让我们求出缠绕在钉子上的绳子有多长. [分析]:从题目中我们能够看出,绳子长度的和等于每两个钉子的距离的和加上接触在钉子上的绳子的长度,不难发现这部分长度事实上就 ...