搜索
您的当前位置:首页正文

Delphi控制Word编程手记

来源:小奈知识网
Delphi控制Word编程手记

前几日对软件“文件整理助手”进行了完善。该软件有文本文件合并,文本文件内容的替换、插入、删除、为特定行首/尾添加字符、清理空行等,以及文件批量替换、改名等功能。

一同事见后,希望能对Word文件进行合并。尽管Word的“插入文件”可以实现这个功能,但不能在插入文件时调整插入的顺序,也不能控制插入的新文件是否另起一页。Word虽然功能强大,但还是有一定的局限性。当然,通过VBA录入脚本、编写宏代码也许可以实现这些复杂的功能。但囿于其缺乏通用性和移植性,对于不善于编程的人来说,还是存在诸多不便。

因此,打算做一个“Word文档合并器”。刚做出这个决定时,以为很简单,因为Delphi的Servers组件页有WordApplication、WordDocument等控件,通过它们来控制全不是那么回事!以前做过涉及到Excel的小程序,没觉得有多难。首次跟Word打交道,竟给我来了个大大的下马威。

以前用过函数,用过过程,也用过带参数的函数、带参数的过程。见过参数多的,但没见过打开、保存Word时尽然要用多达15个、16个参数的函数、过程。而且这些参数青一色地被定义为OleVariant类型,哪些应该是字符串,哪些应该是布尔型,或者专门为Word程序和文档定义的变量类型,没有详细的、系统的资料,只好摸着石头过河,慢慢研究了。

经过几翻碰壁、几翻查证、几翻试验,把要实现的功能一步步拆解,逐一进行调试,通过后再重新组合起来试验。经过拆解、调试、组装三步曲之后,总算是完成了“Word文档合并器”这样一个小小的软件。

为避免下次还重复这种繁琐的基础工作,现将有关技术要点总结于下:

(本程序在Word2003中调试通过,其他版本未进行测试。网上找的一些资料在过程调用、函数语句及参数个数上有出入,可能与

Word版本不一样有关。)

说明:

主窗体中放置以下三个与Word有关的控件: Word: TWordApplication; //Word应用程序接口 Document1: TWordDocument; //Word文档 ole_ShowDoc: TOleContainer; //用以显示Word文档

【一】相关Word组件

这里仅整理Delphi通过自身所提供的Server组件连接Office(Word)的有关资料,其他方法暂不研究。Delphi中提供的与操作Word有关的组件有共有5个,常用的有4个:

1、TWordApplication对象。对应于Microsoft Word应用程序,主要用来在Delphi程序中直接启动或关闭Word应用程序,建立或断开与Word程序的连接。

2、TWordDocument对象。对应于Word文档,主要用来实现创建、销毁一个Word文档,文档的连接和断开,文档中的字符匹配查询,拼写和语法检查以及文档打印等功能。

3、TWordFont对象。对应于Word的字体对象,用来设置Word文档中的字体属性。

4、TWordParagraphFormat对象。对应于Word的段落对象,用来设置文档中的段落格式。

【二】启动Word程序

//建立与Word应用程序的连接 try

Word:=TWordApplication.Create(nil); //必加此句,否则WORD.Quit后无法再启用

//提示:“RPC服务器不可用”。 word.Connect; except

Application.MessageBox('无法连接Word。'+#13#10#13#10 +'请确认已正确安装了Word,并关闭了Word中的对话框!','提醒:',Mb_Ok+

MB_ICONSTOP); Exit; end;

说明:不要“Word:=TWordApplication.Create(nil); ”也可建立与Word应用程序的连接,启动Word应用程序,但

如果用Word.Quit或Word.Destroy退出或注销Word后,便无法再次与Word建立连接,提示“RPC 服务器不可用”。添加

此句后,便可随心所欲地启动、退出Word应用程序。

【三】创建Word文件 新建空白文档的函数原型:

{//===========================================================================

Word.Documents.Add(var NewTemplate: OleVariant;

var DocumentType: OleVariant; var Visible: OleVariant): WordDocument;

============================================================================//}

由于在程序中需要多次调用Add函数,而函数中又不能直接使用变量的值,必须通过OleVariant型的变量名进行传递,

为避免繁琐的变量定义和赋值,我将其简化为AddDoc过程: //WordApplication建立空白文档过程 procedure

AddDoc(word:TWordApplication;Dot:String;NewDot,DocVisible:Boolean); //打开文件

var

Template:

OleVariant;

var

Template,NewTemplate,DocumentType,Visible: OleVariant; begin

Template:=Dot; //使用模板的名称,

NewTemplate:=NewDot; //新建文档的类型,True表示为模板,False表示为文档

DocumentType:=EmptyParam; //文档类型,默认为空白文档

Visible:=DocVisible; //打捞的窗口是否可见

Word.Documents.Add(Template,NewTemplate,DocumentType,Visible);

end;

【四】打开Word文件 打开文件的函数原型:

{//===========================================================================

Word.Documents.Open(var ConfirmConversions: OleVariant;

var ReadOnly: OleVariant; var AddToRecentFiles: OleVariant; var PasswordDocument: OleVariant; var PasswordTemplate: OleVariant;

var Revert: OleVariant; var WritePasswordDocument: OleVariant;

var

WritePasswordTemplate:

OleVariant;

var

Format:

OleVariant;

var Encoding: OleVariant; var Visible: OleVariant; var OpenAndRepair: OleVariant;

var DocumentDirection: OleVariant; var NoEncodingDialog: OleVariant): WordDocument;

======================================

FileName:

OleVariant;

var

======================================//}

由于在程序中需要多次调用Open函数,我将其简化只有2个参数的OpenDoc过程:

//WordApplication打开文件过程 procedure

OpenDoc(word:TWordApplication;sFileName:string);

var

//打开文件的参数

FileName,CfCversions,ReadOnly,AddToRctFiles,PswDocument,PswTemplate,Revert,

WPswDocument,WPswTemplate,Format,Encoding,Visible,OpenAndRepair,

DocumentDirection,NoEncodingDialog:OleVariant; begin

// ===== 创建对象 ===== try

Word:=TWordApplication.Create(nil); word.Connect; except

Application.MessageBox('本机可能没有正确安装WORD!','提醒:',Mb_Ok+MB_ICONSTOP);

Exit; end;

// ===== 打开文件 ===== Word.Visible := false; FileName:=sFileName; CfCversions := false; ReadOnly:=False; AddToRctFiles:= false; PswDocument:= '';

PswTemplate:= ''; Revert:=true;

WPswDocument:= '';//文档密码 WPswTemplate:= '';//模板密码 Format:= EmptyParam; Encoding:= ''; Visible:=False;

OpenAndRepair:= EmptyParam; DocumentDirection:= EmptyParam; NoEncodingDialog:= EmptyParam;

Word.Documents.open(FileName,CfCversions,ReadOnly,AddToRctFiles,PswDocument,

PswTemplate,Revert,WPswDocument,WPswTemplate,Format,Encoding,Visible,

OpenAndRepair,DocumentDirection,NoEncodingDialog); end;

【五】连接Word文件

将新建的或打开的word文档通过TWordDocument对象的ConnectTo方法与TWordapplication实例建立关联。

var

DocInx: OleVariant; begin DocInx:=1;

// Document1.ConnectTo(Word.ActiveDocument); Document1.ConnectTo(Word.Documents.Item(DocInx)); end;

【六】保存Word文件 Word保存文件过程的原型:

{//===========================================================================

Word.ActiveDocument.SaveAs(var FileName: OleVariant; var FileFormat: OleVariant;

var LockComments: OleVariant; var Password: OleVariant; var AddToRecentFiles: OleVariant; var WritePassword: OleVariant;

var

ReadOnlyRecommended:

OleVariant;

var

EmbedTrueTypeFonts: OleVariant;

var SaveNativePictureFormat: OleVariant; var SaveFormsData: OleVariant;

var SaveAsAOCELetter: OleVariant; var Encoding: OleVariant; var InsertLineBreaks: OleVariant; var AllowSubstitutions: OleVariant;

var LineEnding: OleVariant; var AddBiDiMarks: OleVariant); safecall;

============================================================================//}

为避免繁琐地使用保存文件过程,精简为: //WordApplication保存文件过程 procedure

SaveDoc(word:TWordApplication;sFileName:string);

var

//保存文件的参数

FileName,FileFormat,LockComments,Password,AddToRecentFiles,

WritePassword,

ReadOnlyRecommended,EmbedTrueTypeFonts,SaveNativePictureFormat,

SaveFormsData,SaveAsAOCELetter,Encoding,InsertLineBreak

s,AllowSubstitutions,

LineEnding,AddBiDiMarks: OleVariant; begin

FileName:=sFileName; FileFormat:= EmptyParam; LockComments:= EmptyParam; Password:= EmptyParam; AddToRecentFiles:= EmptyParam; WritePassword:= EmptyParam;

ReadOnlyRecommended:= EmptyParam; EmbedTrueTypeFonts:= EmptyParam; SaveNativePictureFormat:= EmptyParam; SaveFormsData:= EmptyParam; SaveAsAOCELetter:= EmptyParam; Encoding:= EmptyParam; InsertLineBreaks:= EmptyParam; AllowSubstitutions:= EmptyParam; LineEnding:= EmptyParam; AddBiDiMarks:= EmptyParam;

Word.ActiveDocument.SaveAs(FileName,FileFormat,LockComments,Password,

AddToRecentFiles,WritePassword,ReadOnlyRecommended,EmbedTrueTypeFonts,

SaveNativePictureFormat,

SaveFormsData,SaveAsAOCELetter,Encoding,

InsertLineBreaks,AllowSubstitutions,LineEnding,AddBiDiMarks);

end;

如果通过TWordDocument对象保存文件,则比较简单: Document1.SaveAs(newFileName);

【七】插入Word文件 Word插入文件过程的原型:

{//===========================================================================

InsertFile(const FileName: WideString; var Range: OleVariant; var ConfirmConversions: OleVariant; var Link: OleVariant; var Attachment: OleVariant); safecall;

============================================================================//}

//向打开的Word文件中插入外部文件 var i:Integer;

myRange,CfCversions,Link,Attachment: OleVariant; s:WideString; begin

for i :=0 to List.Items.Count-1 do begin

myRange:=EmptyParam; CfCversions:=EmptyParam; Link:=EmptyParam; Attachment:=EmptyParam; myType:=wdPageBreak; if

(chk_AddNewPage.Checked)

and

(i>0)

then

Word.Selection.InsertBreak(myType);

s:=List.Items[i];

Word.Selection.InsertFile(s,myRange,CfCversions,Link,Attachment);

end; end;

如果在插入文件时,要另起一页,则可在插入文件前执行:

//var myType:OleVariant; myType:=wdPageBreak;

Word.Selection.InsertBreak(myType); 插入“分隔符”的类型定义如下: const

wdSectionBreakNextPage = $00000002; wdSectionBreakContinuous = $00000003; wdSectionBreakEvenPage = $00000004; wdSectionBreakOddPage = $00000005; wdLineBreak = $00000006; wdPageBreak = $00000007; wdColumnBreak = $00000008; wdLineBreakClearLeft = $00000009; wdLineBreakClearRight = $0000000A; wdTextWrappingBreak = $0000000B; 如果要插入字符串,可以使用如下方法:

Document1.Characters.Last.Select;//选择最后字符 Document1.Range.InseflAfter('要输入的文字'+#13);

【八】关闭Word文件 //关闭打开的Word文件

{//===========================================================================

procedure

Close(var

SaveChanges:

OleVariant;

var

OriginalFormat: OleVariant;

var RouteDocument: OleVariant); safecall;

============================================================================//}

var

SaveChanges,OriginalFormat,RouteDocument: OleVariant;

begin

Document1.Disconnect; Document1.Close; SaveChanges:=False;

OriginalFormat:=EmptyParam; RouteDocument:=EmptyParam;

Word.Documents.Close(SaveChanges,OriginalFormat,RouteDocument);

end;

【九】退出Word程序 //退出Word begin

Word.Disconnect; // Word.Destroy; WORD.Quit; end;

【十】其他相关操作 var

WORDAPP:Twordapplication; WORDdocument:TWordDocument; itemindex:OleVariant;

template,newtemplate,documenttype,visible:olevariant; curr_range:Range; row,col:Integer; direction:OleVariant;

defaulttablebehvior,autofitbehvior:OleVariant; curr_table:Table; myrange:OleVariant; savefile:OleVariant;

begin try try

WORDAPP:=TWordApplication.Create(nil); WORDdocument:=TWordDocument.Create(nil); except

ShowMessage('本机可能没有装WORD!'); Exit; end;

itemindex:=1; WORDAPP.Connect; WORDAPP.Visible:=true;

WORDAPP.Documents.AddOld(EmptyParam,EmptyParam) ; WORDdocument.ConnectTo(WORDAPP.Documents.Item(itemindex) as _document);

//关闭拼写检查,因为这会浪费较多时间

WORDAPP.Options.CheckSpellingAsYouType:= False; WORDAPP.Options.CheckGrammarAsYouType:= False; //页面设置

with WORDdocument.PageSetup do begin

PaperSize:=wdPaperA4; //wdPaperA4 = $00000007;; LeftMargin:= WORDAPP.CentimetersToPoints(2.0); RightMargin:= WORDAPP.CentimetersToPoints(2.0); TopMargin:= WORDAPP.CentimetersToPoints(2.0); BottomMargin:=WORDAPP.CentimetersToPoints(2.0); Orientation:= wdOrientLandscape; //横向打印 //centerHorizontally:= True; //水平对齐方式 end;

//写标题

curr_range:= WORDdocument.Range;

curr_range.InsertAfter('插入标题文字'+#13#10); curr_range.Font.Size:=14; curr_range.Bold:=1;

curr_range.ParagraphFormat.Alignment:=wdAlignPageNumberCenter; //居中对齐

//加入表格

direction:=wdCollapseEnd; //定位到标题的下一行加入表格

curr_range.Collapse(direction);

defaulttablebehvior:=wdWord10ListBehavior; //画边框线

autofitbehvior:=wdAutoFitWindow;

col:=DBGridEh1.DataSource.DataSet.FieldCount-1; //列数 row:=DBGridEh1.DataSource.DataSet.RecordCount+1; //行数

//下面两种方式也能通过

//myrange:=WORDdocument.Content.End_-1; //定位到标题的下一行加入表格

//curr_table:=WORDdocument.Tables.AddOld(WORDdocument.Range(myrange),row,col);

curr_table:=WORDdocument.Tables.Add(curr_range,row,col,defaulttablebehvior,autofitbehvior);

//WORDdocument.Tables.AddOld(curr_range,row,col); curr_table.Range.Paragraphs.Alignment:= wdAlignParagraphLeft; //对齐方式左对齐

//写字段名及值

with DBGridEh1.DataSource.DataSet do begin

for col:=1 to FieldCount-1 do //写字段名 begin

curr_table.Cell(1,col).Range.Font.Name:='宋体'; curr_table.Cell(1,col).Range.Font.Size:=12;

curr_table.Cell(1,col).Range.Font.Bold:=Integer(False); if col=1 then curr_table.Cell(1,col).Range.Text:='序号' else 1].FieldName;

//curr_table.Columns.AutoFit; end; row:=2; First;

while not Eof do //写值 begin

for col:=1 to FieldCount-1 do begin if

then curr_table.Cell(row,col).Range.Text:=IntToStr(row-1)

else begin

if ( Fields[COL-1].FieldName='开始时间' ) or ( Fields[COL-1].FieldName='终止时间' ) then

curr_table.Cell(row,col).Range.Text:=FormatDateTime('yyyy-MM-dd',Fields[COL-

1].AsDateTime) else 1].AsString;

end;

curr_table.Cell(row,col).Range.Font.Size:=11; curr_table.Cell(row,col).Range.Font.Name:='宋体';

curr_table.Cell(row,col).Range.Text:=Fields[COL-col=1

curr_table.Cell(1,col).Range.Text:=Fields[col-

curr_table.Cell(row,col).Range.Font.Bold:=Integer(False); end; inc(row); Next; end;

curr_table.Columns.AutoFit; end; finally

if Trim(savefilename)<>'' then begin

savefile:=savefilename+'.doc'; WORDdocument.SaveAs(savefile); end;

WORDdocument.Disconnect; WORDAPP.Disconnect; FreeAndNil(WORDdocument); FreeAndNil(WORDAPP); end; end;

因篇幅问题不能全部显示,请点此查看更多更全内容

Top