2011-03-22 72 views
4

从Delphi XE开始使用som自动执行Word时,我同时打开两个文档。我想将一个文档的给定范围的内容复制到另一个文档中的另一个范围。我怎样才能做到这一点?OLE自动化:如何在不使用剪贴板的情况下在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; 

有什么我可以代替内容是什么?我不能使用文本,因为我想复制格式,书签,字段代码等。我必须以另一种方式完成这些任务吗?有什么建议么?

回答

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; 

用我的测试中,“文件”格式抛出一个错误(有点像不能够插入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 
  
+0

我已经注意到这些函数(exportfragment/importfragment),它们对我的需要来说是完美的。不幸的是,Word 2007不适合我。我们的解决方案需要运行Word 2003的用户,可能甚至更早,这些功能不可用。不过谢谢。到目前为止最好的建议:-) – 2011-03-24 07:13:58

+0

更新:由于没有其他答案,我会接受这个最好的。不过,它让我感到害怕,没有涉及剪贴板或使用外部文件的方法,没有好的办法。这似乎很基本: -/ – 2011-04-04 07:38:12

+0

@Svein - 我已经用另一种方法更新了答案。如果它仍然不能令人满意,我会建议在标签中加入'msword'并且暂时保持这个问题不被回答。 – 2011-04-05 22:41:30

-3

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

+3

首先,如果我使用剪贴板,我会删除用户放在那里的任何东西。这不是一件好事。此外,此应用程序通常在剪贴板与本地剪贴板同步的终端服务器上运行,从而导致性能问题。 – 2011-03-23 10:26:01

+2

-1剪贴板属于用户,而不是你。除非用户启动剪贴板(例如复制或剪切或粘贴),否则您绝对不应做任何影响剪贴板内容的操作。 – 2011-03-23 11:28:52

1

如果你可以使用Office Open XML -format(即在Word 2007年推出的docx文件格式),那么你就可以做到这一点没有自动化。

的Word 2007年之前的版本必须安装compatibility pack这将使DOCX,文件的Word 2003,2002年和2000年

的的docx文件实际上是一个zip文件,其中包含一些XML的文件。尝试将docx文件的扩展名从.docx更改为.zip,然后在例如.doc中打开该文件。 WinZip的。

因此...解压缩docx文件并获取您需要的xml部分。作为纯字符串或xml文档。然后你可以将这个XML部分注入到其他docx文件中。不过,您需要知道,其中在xml结构中可以抓取/插入xml。这将取决于您如何了解文档结构以及允许用户在文档中进行多少编辑。

我不知道Word如何处理重复的书签名称等与此方法。

0

看来我发现了这个问题的标准解决方案,同时挖掘到类似的问题。 FormattedText Range对象的属性确切地说是你需要的。只需使用:

vRange2.FormattedText := vRange1; 

和vRange1的内容将被复制到vRange2。此外,这也适用:

vRange2 := vRange1; 

虽然,第二条语句不复制格式。

相关问题