VB 版 (精华区)
发信人: zxfsnow (别怕我伤心), 信区: VB
标 题: 用MS Word作ActiveX自动服务器
发信站: 哈工大紫丁香 (2000年06月01日19:06:41 星期四), 转信
发信人: lijialie (day), 信区: VB
标 题: 用MS Word作ActiveX自动服务器
发信站: 饮水思源站 (Mon Sep 6 10:46:42 1999) , 站内信件
作为通用的字处理工具,MS Word是非常优秀的,它功能强大,使用方便,并且微软提
供的VBA语言又极大地扩展了其功能。MS Word所见即所得的特性的确令人爱不释手。然
而,
它的局限性也是非常明显的,比如说,想用它的VBA语言来获取数据库中的数据就相当麻
烦,
并且不像独立的Visual Basic那样支持标准的文件、目录和驱动器的列表。
我们的任务很简单,就是把全系300多名毕业生四年的学习成绩按照规定的格式打印
出
来,以便存入档案后递交用人单位。每个学生的课程总共约有三、四十门,并且每个人
的课
程都不完全相同,其中选修课大约占30%。仅就输出报表而言,Word是毫无问题的,但是
Word
难以从数据库中读取学生成绩并加以处理。如果不用Word,那么自己编写报表输出程序
会
怎样呢?先看看现有的开发工具VB、Delphi、BC++、VC++等,用它们读取数据库的数据
自
然是毫无问题的,但是输出的报表又难以与Word报表相媲美。想赶上Word报表,就不得
不
深入到令人头痛的打印机编程中去,而且还需要反复调试,非常麻烦。
1.Delphi和Word联手打天下
好在Microsoft果然不负众望,Word既是一个优秀的字处理软件,也是一个出色的
ActiveX自动服务器,其自动服务功能非常强大,而且应有尽有。
为了完成上述任务,我们用Delphi开发主控程序scoreout.exe来操纵Word自动输出
定制的报表。事先将要输出的表格做一份模板,而且给要填写的数据项如班级、姓名、
学号、
课程等留出空位,由scoreout.exe操纵Word填入这些数据项。因为模板是事先用Word做
好的,想怎么排就怎么排,而且不用反复地运行、测试,更不用理会打印机的差异,这
一切
Word都可以处理好。关于数据库的浏览、编辑问题,对于用Delphi开发的scoreout.exe
程序来说也是小菜一碟,友好的用户界面则更不用提了。
2.让Word俯首听命
在scoreout.exe中创建一个隐含的Word.application实例,让该实例在后台工作,
若
Word启动失败,则显示一条提示消息并终止程序的运行。
首先在uses语句中加入comobj单元,此单元中定义了CreateOLEObject函数,然后在
var表中加入wdApp说明,再定义FormCreate函数,Word启动后再设置其visible属性为
可见或不可见(相应的代码参见程序1)。在分发给最终用户时,建议把visible设置为
False,
因为,若Word可见,则用户可能会干扰其工作,这可能会导致不可预见的后果。
uses
...comobj,... //加入comobj单元
var
...
wdApp:Variant; //加入wdApp说明
procedure TForm1.FormCreate(Sender:TObject);
begin //定义FormCreate函数
try
wdApp:=CreateOLEObject('Word.application'); //创建Word实例
except
messageDlg('Word起动失败',mtError,[mbOk],0); //提示错误
application.terminate; //终止程序运行
end;
end;
//设置visible属性
wdApp.Visible:=True; //令Word可见
wdApp.Visible:=False; //令Word不可见
(程序1)
Word启动后就可以让它进行如程序2操作了。
wdApp.quit;//退出
wdApp.run(...);//运行宏
wdApp.language;//返回所用语言
wdApp.fontname;//返回字体名
wdApp.caption;//返回标题
wdApp.Documents.open('c:\mydocument\biao.doc');//打开文档
wdApp.Documents.add;//新建文档
wdApp.Documents('mydoc.doc').close;//关闭文档mydoc.doc
wdApp.Documents('mydoc.doc').save;//保存文档mydoc.doc
wdApp.ActiveDocument.close(0);//关闭当前文档,参数0指出不保存
wdApp.ActiveDocument.SaveAs('filename.doc');
wdApp.Selection.MoveUp;//插入点上移
wdApp.Selection.MoveLeft;//插入点左移
wdApp.Selection.insertafter('string here');//插入文本
(程序2)
3.使用剪贴板交换数据
应用程序和Word交换数据的方法有很多,使用数据交换文件或者DLL都可以,但都比
较麻烦。相比之下,使用剪贴板是一个较好的方法,其缺点是,在应用程序运行时,最
好关
闭其他程序,以避免其他程序使用剪贴板而冲毁数据。剪贴板功能强大,它几乎可以和
Word
交换任何类型的数据。程序3就是一个使用剪贴板的实例。
//向剪贴板中粘贴数据
procedure TForm1.Button1Click(Sender:TObject);
begin
edit1.SelectAll;
edit1.CutToClipboard;//或edit1.CopyToClipboard;
end;
//将剪贴板中的数据粘贴到Word文档中
procedure TForm1.Button2Click(Sender: TObject);
begin
wdApp.Selection.Paste
end;
//将Word中的数据粘贴到剪贴板中:
procedure TForm1.Button3Click(Sender: TObject);
begin
wdApp.Selection.cut;//或wdApp.Selection.copy
end;
//将剪贴板中的数据插入edit控件:
procedure TForm1.Button4Click(Sender:TObject);
begin
edit1.PasteFromClipboard;
end;
(程序3)
4.失去控制的危险
自动操作客户程序(如scoreout.exe)既可以像上面那样以过程方式调用open方法
,
又可以以函数方式调用open方法,例如
result:=wdApp.Documents.open('c:\mydocument\biao.doc');。以过程方式调用的问题
在
于它并不等待Word完成操作就立即将控制权返回给客户程序。如果Word执行的是一项很
费
时间的操作,则有可能在客户发送下一条命令之前,Word还没有完成前一项操作。与此
相
反,如果以函数方式调用一个方法,则只有在操作完成之后,才能将返回值传给客户程
序,
这样就可以确定Word已做好准备并可以执行下一步操作了。
5.深入Word对象模型
与Office 97的其他组件一样,Word被设计成可以用作ActiveX自动操作服务器,因
此好的ActiveX客户程序应该能充分利用其功能。客户程序可以是独立的程序,比如用D
elphi
编写的scoreout.exe或者是Visual Basic编写的其他应用程序,也可以是其他Office组
件中启动的VBA代码。其中,用Delphi编写的应用程序启动Word只需要一条代码
"wdApp:=CreateOleObject('Word.application');",用VB或VBA也很类似。程序4便是使
用CreateObject函数来设置对Microsoft Word的引用(变量名为wdApp),本例使用了该
引用来访问Microsoft Word的Visible属性,然后使用Microsoft Word的Quit方法将它
关闭,最后释放该引用自身。
Dim wdApp As Object '声明变量来保持引用。
Set wdApp = CreateObject("Word.application")
'如果想看见被调用的应用程序,则必须将Visible属性设置为True。
wdApp.Visible = True
'用wdApp来访问Microsoft Word的其他对象,比如document。
wdApp.Quit '结束后用Quit方法来关闭该应用程序,
Set wdApp = Nothing '释放该引用。
(程序4)
要充分利用Word的自动服务功能,则必须对Word的对象模型有较为深入的了解,Wo
rd
对象模型中有一系列属于Application的对象和集合。以下示例程序均是用VB或VBA语言
编写的。
(1)Application对象代表Word应用程序,包括可以返回最高一级对象的属性和方法
。
例如ActiveDocument属性可以返回Document对象。在使用可返回最普通的用户界面对象
的
许多属性和方法(比如活动文档,即ActiveDocument属性)时,可不必用Application对
象进行区分。例如,可写成ActiveDocument.PrintOut,而不必写成
Application.ActiveDocument.PrintOut。使用时不受Application对象限制的属性和方
法
被看作是“共用”的。Application对象的方法有Move、OnTime、Quit、Run等,属性有
ActiveDocument、ActivePrinter、caption、Documents、FontName、Path、visible、
WindowState、WordBasic等。
(2)Documents对象是由Word当前打开的所有Document对象所组成的集合,下列示例
显示各打开文档的名称:
For Each aDoc In Documents
aName = aName & aDoc.Name & vbCr
Next aDoc
MsgBox aName
用Add方法可以创建新的空文档,并将其添加到Documents集合中。用Open方法可以
打开文档。用Documents(index)可以返回单个的Document对象,其中的index是文档的名
称或索引序号。下面的语句用来关闭Report.doc文档,并且不保存所作的修改:
Documents("Report.doc").CloseSaveChanges:=wdAppDoNotSaveChanges
索引序号代表文档在Documents集合中的位置,例如Documents(1).Activate是代表
激
活Documents集合中的第一个文档,但建议使用Documents("Report.doc")这样的显式引
用,
这样可以使可读性强,而且不易出错。
(3)Document对象代表一篇文档,Document对象是Documents集合中的一个元素。
Documents集合包含Word当前打开的所有Document对象。
可用ActiveDocument属性引用处于活动状态的文档。下列示例是用Activate方法激
活
名为Document1的文档,然后将页面方向设置为横向并打印该文档:
Documents("Document1").Activate
ActiveDocument.PageSetup.Orientation = wdAppOrientLandscape
ActiveDocument.PrintOut
它的方法和属性各有数十个,不过常用的并不多,如Range、Save、SaveAs、Prote
ct、
Close、Goto、Unprotect等方法和ActiveWindow、FullName、HasPassWord、Name、Pag
eSetup、
Password、Path、ReadOnly、Saved、SaveFormat等属性。
(4)Selection对象代表一个窗格中的选定内容,该选定内容可以包括文档中的一个
区
域,也可以仅包括插入点。可用Information属性返回有关选定内容的信息:
If Selection.Information(wdAppWithInTable) = True Then...
也可用Select方法选定文档中的一个项目,下例是选定活动文档中的第一个书签并
将
其显示为红色:
If ActiveDocument.Bookmarks.Count >= 1 Then
ActiveDocument.Bookmarks(1).Select
Selection.Font.ColorIndex = wdAppRed
End If
Selection对象还包括几种用于扩展或移动当前选定内容的方法,例如,可以将Mov
eDown
方法的Extend参数设为wdAppExtend。下例在活动窗口中选定接下的三段:
.StartOf Unit:=wdAppParagraph, Extend:=wdAppMove
.MoveDown Unit:=wdAppParagraph, Count:=3, Extend:=wdAppExtend
End With
记录宏时,宏记录器经常将变化记录到Selection对象中。下例中宏将文档的起始两
个
词设为加粗格式并新添加一段:
Selection.HomeKey Unit:=wdAppStory
Selection.MoveRight Unit:=wdAppWord, Count:=2, Extend:=wdAppExtend
Selection.Font.Bold = wdAppToggle
Selection.MoveRight Unit:=wdAppCharacter, Count:=1
Selection.TypeParagraph
下例完成与上例相同的操作,但不使用Selection对象:
Set myRange = ActiveDocument.Range(Start:=0,_
End:=ActiveDocument.Words(2).End)
myRange.Bold = True
myRange.InsertParagraphAfter
每个窗格中只能有一个Selection对象,但在一个文档中可以有多个Range对象。一
个
Range对象代表文档中一个已选定或未选定的范围,用Range对象可以很方便地对文档进
行
操作。
(5)Range对象代表文档中的一个范围,每一个Range对象由一个起始位置字符和一个
终止位置字符定义,下例返回代表活动文档前10个字符的Range对象:
Set myRange = ActiveDocument.Range(Start:=0, End:=10)
(6)Table对象代表一张表格,它是Tables集合的一个成员。该集合包含指定的选定
内
容、范围或文档中的所有表格。可以使用Tables(index)返回一个Table对象,其中inde
x
为索引序号,代表表格在选定内容、范围或文档中的位置,下例是将活动文档中的第一
张表
格转换为文本:
ActiveDocument.Tables(1).ConvertToText Separator:=wdAppSeparateByTabs
使用Add方法可以在指定范围内添加表格。下例在活动文档的起始处添加一张3行x4
列的表格:
Set myRange = ActiveDocument.Range(Start:=0, End:=0)
ActiveDocument.Tables.Add Range:=myRange, NumRows:=3, NumColumns:=4
(7)Goto方法是一个很有用的方法,对于Document或Range对象而言,此方法返回一
个Range对象,该对象代表指定项(例如页、书签或域)的开始位置。对于Selection对
象,
将插入点移动到指定项前面的字符位置。下面的示例将所选内容移动到文档中的第四行
:
Selection.GoTo What:=wdAppGoToLine, Which:=wdAppGoToAbsolute, Count:=4
下面的示例将所选内容向上移动两行:
Selection.GoTo What:=wdAppGoToLine, Which:=wdAppGoToPrevious, Count:=2
下面的示例将所选内容移动到下一个表格的第一个单元格:
Selection.GoTo What:=wdAppGoToTable, Which:=wdAppGoToNext
程序5是综合处理的例子,它显示如何对既有文本又有图表的文档进行定位;
Sub ShowCellName()
'打印出每个单元格的名字
Set newdAppoc = ActiveDocument
Set myTable = newdAppoc.Tables(1)
i = 1
For Each c In myTable.Range.Cells
c.Range.InsertAfter "Cell " & i
i = i + 1
Next c
'单元格定位及合并,注意单元格的引用
Set myTable = ActiveDocument.Tables(1)
Set myRange = ActiveDocument.Range(myTable.cell(1, 2).Range.Start,
myTable.cell(1, 3).Range.End)
myRange.Cells.Merge
'插入点的定位,绝对定位至Tables(1).cells(1,1)
Selection.GoTo What:=wdAppGoToTable, Which:=wdAppGoToAbsolute, Count:=1
End Sub
(程序5)
下面的例子是查看插入点的位置:
if Selection.Information(wdAppWithInTable)
Then Selection.Tables(1).Select
如果所选的内容位于一个表格中,则本示例选定该表格。
6.建议
(1)在使用别的开发语言操纵word进行自动服务之前,请先多多使用Word VBA,以便
熟悉Word的对象模型。因为它的在线提示功能非常有用,并且查阅Visual Basic参考资
料
也很方便。
(2)Word对象模型的文档包含在Microsoft Word Visual Basic Reference(VBAWRD8
.HLP)
帮助文件中,在典型的Office安装过程中,该文件不被安装,但可以在定制安装过程中
选
择安装它。该文档是很有用的参考,但不能指望仅仅依靠该文档来掌握Word的对象模型
,
特别是对于初学者而言,更多的应该是进行思考和验证。
--
以科计为本,以产业报国!
超越自我,飞跃无限!
※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 202.118.235.249]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.271毫秒