visor texto recuperar portapapeles pegado opciones definicion copiado anteriormente delphi automation clipboard ole delphi-xe

delphi - portapapeles - recuperar texto copiado anteriormente



Automatización OLE: cómo copio texto entre documentos de Word sin usar el portapapeles (4)

Al hacer som la automatización de Word desde Delphi XE, tengo dos documentos abiertos simultáneamente. Quiero copiar el contenido de un rango determinado de un documento a otro rango en el otro documento. ¿Cómo puedo hacer esto?

Considera el siguiente código:

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;

¿Hay algo que pueda sustituir por CONTENIDO? No puedo usar el texto porque quiero copiar el formato, los marcadores, los códigos de campo, etc. ¿Tengo que hacerlo de otra forma? ¿Alguna sugerencia?


¿Por qué no usar el portapapeles? Si todo el texto está seleccionado en vDoc1, copiarlo en el portapapeles implica una simple llamada: vDoc1.copy. Del mismo modo, copiar el contenido del portapapeles al segundo documento requiere una simple llamada: vDoc2.paste. El búfer del portapapeles guardará toda la información de formato.


Si puede usar el formato Office Open XML (es decir, el formato de archivo docx que se introdujo en Word 2007), puede hacerlo sin automatización.

Las versiones de Word anteriores a 2007 deben instalar un paquete de compatibilidad que habilitará los archivos docx para Word 2003, 2002 y 2000.

El archivo docx es en realidad un archivo zip que contiene varios archivos xml. Intente cambiar la extensión de un archivo docx de .docx a .zip y abra este archivo, por ejemplo. WinZip.

Entonces ... Descomprime el archivo docx y toma la parte xml que necesites. Como cadena pura o como un documento xml. Luego puede inyectar esta parte xml en el otro archivo docx. Sin embargo, necesita saber en qué parte de la estructura xml se debe tomar / insertar el xml. Esto dependerá de qué tan bien conozca la estructura del documento y la cantidad de edición que el usuario puede hacer en el documento.

No sé cómo Word manejará los nombres de marcadores duplicados, etc. con este enfoque.


No conozco una forma de usar versiones anteriores de Word, pero para versiones más recientes (2007 y posteriores) puede exportar un rango de un documento a un archivo de fragmento y luego importarlo desde otro documento. Si desea un enlace anticipado, es posible que deba importar la biblioteca de tipos (msword.olb), no sé si Delphi XE lo tiene. De lo contrario, el código podría verse así:

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;

Con mi prueba, el formato ''documento'' arrojó un error (algo así como no poder insertar el formato XML), por lo tanto, uso del formato RTF.

editar:

Con versiones anteriores, parece ser posible insertar una selección nombrada de un documento a una selección en otro documento. El resultado parece no ser perfecto con respecto al formateo si una de las selecciones está en el medio de algún texto. Pero de lo contrario, parece estar funcionando bien.

... 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  


Parece que encontré la solución canónica a esta pregunta mientras cavaba en un problema similar. La propiedad FormattedText del objeto Range es exactamente lo que necesita. Solo usa:

vRange2.FormattedText := vRange1;

y el contenido de vRange1 se copiará en vRange2. Además, esto también funciona:

vRange2 := vRange1;

Sin embargo, la segunda declaración no copia el formato.