我用DB中的BLOB字段保存WORD的文档.
如何取出其数据,对其进行一些操作后保存?(不需要出现WORD的界面,让WORD在后台工作)?
例如有下面的代码:
MyWordApp: OleVariant;
MyStream: TMemoryStream;  MyWordApp := CreateOleBbject('word.application');
  MyStream:= TMemoryStream,Create();
 
  (ADOQuery_File.FieldByName('ProFile_Data') as TBlobField).SaveToStream(MyStream);
MyStream.Position := 0;
取到MyStream后,用OLEContainter打开没有问题.如:OLEContainter.LoadFormStream(MyStream)但是,如何在后台对MyStream的内容进行操作,再保存到数据库中?
MyWordApp.LoadFromStream()----没有这个方法,怎么办?

解决方案 »

  1.   

    调用word有几种办法,我经常使用的是a.使用Delphi提供的Servers控件调用Word,使用Word的属性
    使用Delphi的Servers控件来操纵Word,在编程时Delphi能够实现代码提示,总体上看能够较好的实现Delphi对Word的控制,但是还有一些Word的功能不能在Delphi中调用(比如自己编写的VBA宏代码)。且实现功能时本来在VBA代码中可选则参数在Delphi调用的时候必须添加,否则,连编译都不能通过。b.使用CreateOleObject将启动Word,然后以Ole方式对Word进行控制。本办法是使用以CreateOleObjects方式调用Word,实际上还是Ole,但是这种方式能够真正做到完全控制Word文件,能够使用Word的所有属性,包括自己编写的VBA宏代码。与Servers控件和com技术相比,本方法能够真正地使用Word的各种属性,和在VBA中编写自己的代码基本一样,可以缺省的代码也不需要使用。
    本方式启动的Word与Delphi程序分属两个窗体。缺点是使用本方法没有Delphi代码提示,所有异常处理均需要自己编写,可能编写时探索性知识比较多。如果不希望出现word界面只需要将其中的visible参数设为false
      

  2.   

    给你一个单元,可以控制向word的模板文件的任意位置写入指定的任意数据  
    注意,模板需要写入数据的地方需要用$$$_1之类的标志标明。 
    unit  unAppWord;  
     
    interface  
    uses  
       Windows,  Messages,  SysUtils,  Variants,  Classes,  Graphics,  Controls,  Forms,  
       Dialogs,  udbword,  ADODB,  DB;  
       //ComObj,  Word2000,  
    type  
       TAppword  =  class(TdbWord)  
       private  
           dbWord:  TdbWord;  
    //      Protected  
       public  
           constructor  Create();  
           destructor  Destroy();  override;  
           //依据Word文件名和内容向文件写内容  
           procedure  WriteDoc(sts:  Tstrings;  fn:  string);  
           //提取模板文件并生成word文件  
           function  PickDoc(DocTitle:  string;  Conn:  TADOConnection):  string;  
             {  Public  declarations  }  
       end;  
     
     
    implementation  
    const  
       ReplaceText  =  '$$$_';  
    constructor  TAppWord.Create();  
     
    begin  
       inherited  Create();  
    end;  
     
    destructor  TAppWord.Destroy();  
    begin  
       inherited  Destroy();  
    end;  
     
    procedure  TAppWord.WriteDoc(sts:  Tstrings;  fn:  string);  
    var  
       sCnt:  string;  
       i:  integer;  
    begin  
       if  (fn  =  '')  or  (not  Assigned(sts))  then  exit;  
       try  
       dbword.OpenFile(fn);  
           for    i  :=  0  to  sts.Count  -  1  do  
           begin  
               if  sts.Strings[i]  =  ''  then  
               begin  
                   sCnt  :=  '  ';  
                   dbword.Replace(ReplaceText+IntToStr(i),sCnt);  
               end  
               else  
               begin  
                   sCnt  :=  sts.Strings[i];  
                   dbword.Replace(ReplaceText+IntToStr(i),sCnt);  
               end;  
           end;  
           dbword.Save;  
           dbword.CloseDoc;  
       except  
             raise(Exception.Create('error'));  
       end;  
     
    end;  
     
    function  TAppWord.PickDoc(DocTitle:  string;  Conn:  TADOConnection):  string;  
    var  
       AQuery:  TAdoQuery;  
       sqlDoc:  string;  
       SD:  TSaveDialog;  
     
    begin  
       result  :=  '';  
       if  (Conn  =  nil)  or  (DocTitle  =  '')  or  (not  conn.Connected)  then  exit;  
     try  
           AQuery  :=  TAdoQuery.Create(nil);  
           AQuery.Connection  :=  Conn;  
           if  AQuery.Active  then  AQuery.Close;  
           AQuery.SQL.Clear;  
           sqlDoc  :=  Format('select  MB_DATA  from  tdly.MB_WDWJ  where  MB_NAME=''%s''',  [DocTitle]);  
           AQuery.SQL.Add(sqlDoc);  
           AQuery.Open;  
           if  AQuery.RecordCount    <  >  1  then  
           begin  
               Alert('无法提取'+  DocTitle  +'模板文件');  
               exit;  
           end;  
           SD  :=  TSaveDialog.Create(nil);  
           try  
               SD.Filter  :=  'WORD文件(*.DOC)  |*.DOC';  
               sd.DefaultExt  :=  '*.doc';  
               sd.Options  :=  [ofPathMustExist,  ofOverwritePrompt];  
               if  not  SD.Execute  then  exit;  
               result  :=  Sd.FileName;  
               Tblobfield(AQuery.FieldByName('MB_DATA')).SaveToFile(Result);//  .SaveToStream(memstr);  //模板字段  
           finally  
               AQuery.Close;  
               AQuery.Free;  
               SD.Free;  
           end;  
       except  
       end;  
    end;  
     
     
    end. 
    procedure TFrmMain.BitBtn12Click(Sender: TObject);
    var
    //ItemIndex:OleVariant;
    FileName,ConfirmConversions,ReadOnly,AddToRecentFiles,
    PasswordDocument,PasswordTemplate, Revert,
    WritePasswordDocument,WritePasswordTemplate,Format:OleVariant;
    begin
                 WordApplication1.Connect;
                 FileName:='c:\ZhiD.doc';
                 ConfirmConversions:=False;
                 ReadOnly:=False;
                 AddToRecentFiles:=False;
                 PasswordDocument:='';
                 PasswordTemplate:='';
                 Revert:=True;
                 WritePasswordDocument:='';
                 WritePasswordTemplate:='';
                 Format:=wdOpenFormatDocument;
                 WordApplication1.Documents.Open(FileName,ConfirmConversions,ReadOnly,AddToRecentFiles,PasswordDocument,PasswordTemplate,Revert,WritePasswordDocument,WritePasswordTemplate,Format,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam);
                 WordApplication1.Visible:=true;
      

  3.   

    delphi擅长做数据库类的mis开发,但对于oa就有点力不从心了。不过随着microsoft的com技术逐渐成熟,现在普通windows应用已经可以和office 97无缝结合了,尤其是在delphi 5中提供了一组servers组件,更是简化了程序开发。 最近接触了一个用户的案例,用delphi控制word做一个合同管理程序。办公人员先根据业务需要,写好合同的文字,但在用户名称、产品名称等变化的位置填写指定的标记字符串,然后通过delphi把数据库中的实际数据替换掉word中的文字,最后让word打印出合同。 delphi自带了一个简单的word例题,但功能太简单。通过查找vba的说明,再对照delphi的vcl,编写了如下代码,实现了基本的公文管理功能。 启动word时用如下代码: 
    begin
    try 
    wordapplication.connect; 
    except 
    messagedlg('word may not be installed', mterror, [mbok], 0); 
    abort; 
    end; 
    wordapplication.visible := true; 
    wordapplication.caption := 'delphi automation'; 
    end; 关闭word用如下代码。如果想保存doc文件,请修改savechanges变量的内容: 
    var 
    savechanges, originalformat, routedocument: olevariant; 
    begin 
    savechanges := wddonotsavechanges; 
    originalformat := unassigned; 
    routedocument := unassigned; 
    try 
    wordapplication.quit(savechanges, originalformat, routedocument); 
    wordapplication.disconnect; 
    except 
    on e: exception do 
    begin 
    showmessage(e.message); 
    wordapplication.disconnect; 
    end; 
    end; 
    end; 让word打开一个指定的文件,需要先放置opendialog,然后调用wordapplication.documents.open: 
    var 
    itemindex :olevariant; 
    filename, confirmconversions, readonly, addtorecentfiles, 
    passworddocument, passwordtemplate, revert, 
    writepassworddocument, writepasswordtemplate, format: olevariant; 
    begin 
    if not dlgopen.execute then 
    exit; {open document} 
    filename := dlgopen.filename; 
    confirmconversions := false; 
    readonly := false; 
    addtorecentfiles := false; 
    passworddocument := ''; 
    passwordtemplate := ''; 
    revert := true; 
    writepassworddocument := ''; 
    writepasswordtemplate := ''; 
    format := wdopenformatdocument; wordapplication.documents.open( filename, confirmconversions, 
    readonly, addtorecentfiles, passworddocument, passwordtemplate, 
    revert, writepassworddocument, writepasswordtemplate, format ); {assign worddocument component} 
    itemindex := 1; 
    worddocument.connectto(wordapplication.documents.item(itemindex)); {turn spell checking of because it takes a long time if enabled and slows down winword} 
    wordapplication.options.checkspellingasyoutype := false; 
    wordapplication.options.checkgrammarasyoutype := false; 
    end; 让word替换标记字符串要使用worddocument.range.find.execute,这里用delphi替换了< #name> : 
    var 
    findtext, matchcase, matchwholeword, matchwildcards, matchsoundslike, 
    matchallwordforms, forward, wrap, format, replacewith, replace: olevariant; 
    begin 
    findtext := '< #name> '; 
    matchcase := false; 
    matchwholeword := true; 
    matchwildcards := false; 
    matchsoundslike := false; 
    matchallwordforms := false; 
    forward := true; 
    wrap := wdfindcontinue; 
    format := false; 
    replacewith := 'delphi'; 
    replace := true; worddocument.range.find.execute( findtext, matchcase, matchwholeword, 
    matchwildcards, matchsoundslike, matchallwordforms, forward, 
    wrap, format, replacewith, replace ); end; 上面这4段代码完成了公文管理的基本功能,再把它和数据库结合起来,就可以开发一个与lotus notes类似的产品了。
      

  4.   

    我在数据库中保存的是OLECONTAILER.SAVETOSTREAM(MyStream)的数据.
    在OLECONTAILER中打开没有问题.现在如何在后台对MyStream的内容进行操作?即不要显示界面,只通过WORD对MyStream中的内容进行处理?
      

  5.   

    procedure tfrmlxxt.putout;
    var
        V:variant;
        j,I:Integer;
        s1,s2,s3,s4,s5,pd,sa,sb,sc : String;
    begin
        V:=createoleobject('word.application');    //创建WORD工程
        v.documents.add;                           //加载文档
        DM1.Cn1Query_tm.first;
        v.Selection.TypeText(label22.Caption);     //加入文字
        v.Selection.TypeParagraph;                 //加入回车
        v.Selection.TypeParagraph;
        v.Selection.TypeParagraph;
        sa:='';
        sb:='';
        sc:='';
        while not DM1.Cn1Query_tm.Eof do
        begin
           DBRichEdit3.DataField:='';
           DBRichEdit3.DataSource:=DM1.Cn1DS_tm;
           DBRichEdit3.DataField:='a15';
          sa:=inttostr(DM1.Cn1Query_tm.findfield('a13').asinteger);
          if sa='11' then
          begin
            sc:='单选题:';
          end
          else
          begin
            if sa='18' then
            begin
              sc:='多选题:';
            end
            else
            begin
              if sa='12' then
              begin
                sc:='判断题';
              end
              else
              begin
                if sa='20' then
                begin
                  sc:='简答题';
                end
                else
                begin
                  if sa='21' then
                  sc:='分析题';
                end;
              end;
            end;
          end;
           if sb<>sa then
           begin
             v.Selection.TypeText(sc);
             v.Selection.TypeParagraph;
           end;
           v.Selection.TypeText(inttostr(DM1.Cn1Query_tm.RecNo)+'、');
           DBRichEdit3.SelStart:=0;
           DBRichEdit3.SelLength:=length(DBRichEdit3.Lines.Text);
           DBRichEdit3.CopyToClipboard;                     //复制
           v.selection.paste;                               //粘贴
           v.Selection.TypeParagraph;
           IF DM1.Cn1Query_tm.FieldByName('CSBS').AsString<>'' THEN
           BEGIN
             TRY
               //AdvImage2.loadImage(ExtractFilePath(Application.ExeName)+DM1.Cn1Query_exam.FIELDBYNAME('CSBS').AsString);
               V.SELECTION.InlineShapes.AddPicture(ExtractFilePath(Application.ExeName)+DM1.Cn1Query_tm.FIELDBYNAME('CSBS').AsString);
               v.Selection.TypeParagraph;
             EXCEPT
             END;
           END;
           sb:=sa;
           DM1.Cn1Query_tm.next;
       end;   v.Selection.insertBreak;
       DM1.Cn1Query_tm.first;
       v.Selection.TypeText('答案');
       v.Selection.TypeParagraph;
       v.Selection.TypeParagraph;
       v.Selection.TypeParagraph;
       while not DM1.Cn1Query_tm.Eof do
       begin
          v.Selection.TypeText('第'+inttostr(DM1.Cn1Query_tm.RecNo)+'题');
          v.Selection.TypeParagraph;
          if  DM1.Cn1Query_tm.findfield('a13').asinteger<=19 then
          begin
             pd:=DM1.Cn1Query_tm.fieldbyname('a2').AsString;
             if dm1.Cn1Query_tm.FindField('a13').AsInteger<>12 then
             begin
             v.Selection.TypeText('试题答案:'+pd);
             v.Selection.TypeParagraph;
             end
             else
             begin
               if pd='A' then pd:='正确';
               IF PD='B' then pd:='错误';
               v.Selection.TypeText('试题答案:'+pd);
               v.Selection.TypeParagraph;
             end;
          end;
          DM1.Cn1Query_tm.next;
      end;
      DM1.Cn1Query_tm.first;
      ListBox1Click(Application);
      v.Visible := TRUE;        //文档可视
      keybd_event(17, MapVirtualKey( 17, 0 ), 0 , 0 );  // win 键按下
      keybd_event(36, MapVirtualKey( 36, 0 ), 0 , 0 );  // home 键按下
      keybd_event(36, MapVirtualKey( 36, 0 ), KEYEVENTF_KEYUP , 0 );  // home 键抬起
      keybd_event(17, MapVirtualKey( 17, 0 ), KEYEVENTF_KEYUP , 0 );  // win 键抬起
      //文件回到文件头、标题位置
    end;