OLE自动化:如何在不使用剪贴板的情况下在Word文档之间复制文本

时间:2011-03-22 15:11:52

标签: delphi automation clipboard ole delphi-xe

在从Delphi XE执行Word自动化时,我同时打开了两个文档。我想将给定范围的一个文档的内容复制到另一个文档中的另一个范围。我怎么能这样做?

请考虑以下代码:

procedure TForm1.ManipulateDocuments;
var
  vDoc1,vDoc2 : TWordDocument;
  vFilename : olevariant;
  vRange1,vRange2 : Range;
begin
  vDoc1 := TWordDocument.Create(nil);
  vDoc2 := TWordDocument.Create(nil);
  try
    vFilename := 'c:\temp\test1.doc';
    vDoc1.ConnectTo(FWordApp.Documents.Open(vFilename,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam));

    vFilename := 'c:\temp\test2.doc';
    vDoc2.ConnectTo(FWordApp.Documents.Open(vFilename,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam,EmptyParam));

    vRange1 := GetSourceRange(vDoc1);
    vRange2 := GetDestinationRange(vDoc2);

    vRange2.CONTENTS := vRange1.CONTENTS; //What should I substitute for CONTENTS?
  finally
    vDoc1.Free;
    vDoc2.Free;
  end;
end;

有什么东西我可以替代内容吗?我无法使用文字,因为我想要复制格式,书签,字段代码等。我是否必须以另一种方式完成这项工作?有什么建议吗?

4 个答案:

答案 0 :(得分:3)

我不知道早期版本的Word的方法,但对于较新版本(2007及更高版本),您可以export a range从文档到片段文件,然后import来自另一个文献。如果你想要早期绑定,你可能需要导入类型库(msword.olb),我不知道Delphi XE是否有它。否则代码可能如下所示:

function GetTempFileName(Prefix: string): string;
begin
  SetLength(Result, MAX_PATH);
  GetTempPath(MAX_PATH, PChar(Result));
  windows.GetTempFileName(PChar(Result), PChar(Prefix), 0, PChar(Result));
end;

procedure TForm2.Button1Click(Sender: TObject);
const
//  wdFormatDocument = 0;
  wdFormatRTF = $00000006;
var
  WordApp : OleVariant;
  fragment: string;
  vDoc1, vDoc2: OleVariant;
  vRange1, vRange2: OleVariant;
begin
  try
    WordApp := GetActiveOleObject('Word.Application');
  except
    WordApp := CreateOleObject('Word.Application');
  end;
  WordApp.Visible := True;

  vDoc1 := WordApp.Documents.Open(ExtractFilePath(Application.ExeName) + 'test1.doc');
  vRange1 := vDoc1.Range(20, 120);     // the export range
  fragment := GetTempFileName('frg');
  vRange1.ExportFragment(fragment, wdFormatRTF);
  try
    vDoc2 := WordApp.Documents.Open(ExtractFilePath(Application.ExeName) + 'test2.doc');
    vRange2 := vDoc2.Range(15, 15);    // where to import
    vRange2.ImportFragment(fragment);
  finally
    DeleteFile(fragment);
  end;
end;

通过我的测试,'document'格式引发了一个错误(类似于无法插入XML格式),因此使用了RTF格式。

修改

对于早期版本,似乎可以将一个文档中的命名选择插入另一个文档中的选择。如果其中一个选择恰好位于某些文本的中间,那么结果似乎并不完美。但除此之外它似乎运作良好。

  ...
  WordApp.Visible := True;

  vDoc1 := WordApp.Documents.Open(ExtractFilePath(Application.ExeName) + 'test1.doc');
  vRange1 := vDoc1.Range(20, 188);                 // the transfer range
  vDoc1.Bookmarks.Add('TransferSection', vRange1); // arbitrary bookmark name

  vDoc2 := WordApp.Documents.Open(ExtractFilePath(Application.ExeName) + 'test2.doc');
  vRange2 := vDoc2.Range(103, 104);           // where to import the bookmark
  vRange2.Select;
  vDoc2.ActiveWindow.Selection.InsertFile(vDoc1.FullName, 'TransferSection');

  vDoc1.Bookmarks.Item('TransferSection').Delete; // no need for the bookmark anymore
 

答案 1 :(得分:1)

如果您可以使用Office Open XML格式(即Word 2007中引入的docx文件格式),那么您可以在不自动化的情况下执行此操作。

2007之前的Word版本必须安装compatibility pack,这将为Word 2003,2002和2000启用docx文件。

docx文件实际上是一个包含多个xml文件的zip文件。尝试将docx文件的扩展名从.docx更改为.zip并在例如中打开此文件。 WinZip的。

所以...解压缩docx文件并获取你需要的xml部分。作为纯字符串或作为xml文档。然后你可以将这个xml-part注入另一个docx文件。但是,你需要知道xml-structure中的 where 来获取/插入xml。这取决于您对文档结构的了解程度以及允许用户在文档中进行多少编辑。

我不知道Word如何使用这种方法处理重复的书签名称等。

答案 2 :(得分:0)

在挖掘类似问题时,我似乎找到了这个问题的规范解决方案。 Range对象的 FormattedText 属性就是您所需要的。只需使用:

vRange2.FormattedText := vRange1;

并将vRange1的内容复制到vRange2中。此外,这也有效:

vRange2 := vRange1;

尽管如此,第二个声明并没有复制格式。

答案 3 :(得分:-3)

为什么不使用剪贴板?如果在vDoc1中选择了所有文本,则将其复制到剪贴板需要一个简单的调用:vDoc1.copy。同样,将剪贴板的内容复制到第二个文档需要一个简单的调用:vDoc2.paste。剪贴板缓冲区将保存所有格式信息。