Delphi控制Word编程手记
  • 首页
  • 产品中心
  • 工程案例
  • 栏目分类
    工程案例你的位置:北京北恒建筑装饰工程有限公司 > 工程案例 > Delphi控制Word编程手记

    Delphi控制Word编程手记

    发布日期:2022-08-17 20:06    点击次数:177

      前几日对软件“文件整理助手”进行了完善。该软件有文本文件合并,文本文件内容的替换、插入、删除、为特定行首/尾添加字符、清理空行等,以及文件批量替换、改名等功能。  一同事见后,希望能对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 Template: OleVariant; 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,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 FileName: OleVariant; 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;============================================================================//}由于在程序中需要多次调用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,InsertLineBreaks,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程序//退出Wordbegin  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 curr_table.Cell(1,col).Range.Text:=Fields[col-1].FieldName;        //curr_table.Columns.AutoFit;      end;      row:=2;      First;      while not Eof do                     //写值       begin        for col:=1 to FieldCount-1 do        begin          if  col=1 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 curr_table.Cell(row,col).Range.Text:=Fields[COL-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.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;



    Powered by 北京北恒建筑装饰工程有限公司 @2013-2022 RSS地图 HTML地图

    Copyright 365建站 © 2013-2022 365建站器 版权所有