OLE Automation: how to copy text between Word documents without using a clipboard

During som Word automation from Delphi XE, I have two documents open at the same time. I want to copy the contents of a given range of one document to another range in another document. How can i do this?

Consider the following code:

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; 

Is there anything I could replace with CONTENT? I cannot use text because I want to copy formatting, bookmarks, field codes, etc. Should I do it differently? Any suggestions?

+4
source share
4 answers

I don’t know the way for earlier versions of Word, but for newer versions (2007 and higher) you can export a range from a document to a fragment file and then import it from another document. If you need early binding, you may need to import the type library (msword.olb), I don't know if it has Delphi XE. Otherwise, the code may look like this:

 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; 

In my test, the "document" format triggered an error (something like the inability to insert XML formatting), therefore, using the RTF format.

change

In earlier versions, it seems possible to insert a named selection from one document into another in another document. The result does not seem to be ideal for formatting if one of the selected events is in the middle of some text. But otherwise it works well.

  ... 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 
+3
source

If you can use Office Open XML- format (that is, the docx file format that was introduced in Word 2007), then you can do this without automation.

In versions of Word prior to 2007, you must install a compatibility package that allows you to use docx files for Word 2003, 2002, and 2000.

The docx file is actually a zip file that contains several xml files. Try changing the docx file extension from .docx to .zip and open this file, for example. WinZip

So ... Unzip the docx file and grab the xml part you need. As a blank line or as an XML document. Then you can paste this xml part into another docx file. However, you need to know where in the xml structure to grab / embed xml. This will depend on how well you know the structure of the document and how much editing the user is allowed to do in the document.

I do not know how Word will handle duplicate bookmark names, etc. using this approach.

+1
source

I seem to have found a canonical solution to this issue, while I dug up a similar problem. The FormattedText property of the Range object is what you need. Just use:

 vRange2.FormattedText := vRange1; 

and the contents of vRange1 will be copied to vRange2. In addition, this also works:

 vRange2 := vRange1; 

Although the second statement does not copy formatting.

0
source

Why not use the clipboard? If all text is selected in vDoc1, then one simple call is used to copy it to the clipboard: vDoc1.copy. Similarly, copying the contents of the clipboard to a second document requires one simple call: vDoc2.paste. The buffer buffer will contain all formatting information.

-3
source

Source: https://habr.com/ru/post/1344786/


All Articles