Definición de la clase cWord
Para combinar correspondencia definimos de una clase llamada cWord con los métodos necesarios para esta tarea. El código de la clase es el siguiente:
*-------------------------------------------------- * Clase cWord *-------------------------------------------------- DEFINE CLASS cWord AS CUSTOM *-- * Propiedades *-- oWord = .NULL. && Objeto Word cDirApp = ADDBS(SYS(5) + SYS(2003)) cDirDat = ADDBS(HOME(2) + 'Northwind') cDataSource = '' *-------------------------------------------------- * Creo el servidor de automatización *-------------------------------------------------- PROCEDURE CrearServidor() *-- Creo el objeto THIS.oWord = CREATEOBJECT('Word.Application') RETURN VARTYPE(THIS.oWord) = 'O' ENDPROC *-------------------------------------------------- * Cierro el servidor de automatización *-------------------------------------------------- PROCEDURE CerrarServidor() *-- Cierro Word THIS.oWord.QUIT() THIS.oWord = .NULL. RETURN ENDPROC *-------------------------------------------------- * Abro la Carta, si no existe la creo *-------------------------------------------------- PROCEDURE AbrirCarta(tcArchivo) LOCAL loDoc AS 'Word.Document' tcArchivo = FORCEEXT(tcArchivo,'DOC') IF NOT FILE(THIS.cDirApp + tcArchivo) *-- Si no existe la carta, la creo loDoc = THIS.CrearCarta(tcArchivo) ELSE *-- Si existe la carta, la abro loDoc = THIS.oWord.Documents.OPEN(THIS.cDirApp + tcArchivo) *-- y me aseguro que no tiene un documento asociado loDoc.MailMerge.MainDocumentType = -1 && wdNotAMergeDocument ENDIF *-- Retorno un objeto Document RETURN loDoc ENDPROC *-------------------------------------------------- * Creo la Carta *-------------------------------------------------- PROCEDURE CrearCarta(tcArchivo) LOCAL loDoc AS 'Word.Document' *-- Creo un nuevo documento loDoc = THIS.oWord.Documents.ADD(,,0) *-- Guardo el documento como ... loDoc.SAVEAS(THIS.cDirApp + tcArchivo) *-- Activo el documento loDoc.ACTIVATE *-- Comienzo a 'escribir' el documento WITH THIS.oWord.SELECTION .FONT.NAME = 'Tahoma' .FONT.SIZE = 10 .ParagraphFormat.ALIGNMENT = 2 && wdAlignParagraphRight .TypeText('San Miguel de Tucumán, ' + DTOC(DATE())) .TypeParagraph .ParagraphFormat.ALIGNMENT = 0 && wdAlignParagraphLeft .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeText('Señores: ') .FONT.Bold = .T. .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD CompanyName ') .FONT.Bold = .F. .TypeParagraph .TypeText('At: ') .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD ContactName ') .TypeParagraph .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD Address ') .TypeParagraph .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD PostalCode') .TypeText(' - ') .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD City ') .TypeParagraph .FONT.Underline = 1 && wdUnderlineSingle .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD Country ') .FONT.Underline = 0 && wdUnderlineSingle .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeText(CHR(9) + 'Estimado/a ') .FIELDS.ADD(.RANGE, -1, 'MERGEFIELD ContactName ') .TypeParagraph .TypeParagraph .TypeText(CHR(9) + 'Nos dirigimos a Ud. con el objeto de comunicarle ' + ; 'la nueva dirección de nuestra empresa') .TypeParagraph .TypeParagraph .FONT.Bold = .T. .TypeText('Informática del Tucumán') .FONT.Bold = .F. .TypeParagraph .TypeText('9 de Julio 123, 1° Piso') .TypeParagraph .TypeText('4000 - San Miguel de Tucumán') .TypeParagraph .TypeText('Tucumán, Argentina') .TypeParagraph .TypeText('Teléfono (+54) (381) 681-4521') .TypeParagraph .TypeParagraph .TypeText(CHR(9) + 'Sin otro particular lo saludamos atte.') .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeParagraph .TypeText('Manuel Belgrano') .TypeParagraph .TypeText('Socio Gerente') .TypeParagraph .TypeText('Informática del Tucumán') .TypeParagraph ENDWITH *-- Retorno un objeto Document RETURN loDoc ENDPROC *-------------------------------------------------- * Creo archivo DataSource *-------------------------------------------------- PROCEDURE GenerarDataSource LOCAL lcArchivo AS CHARACTER IF NOT DBUSED('Northwind') OPEN DATABASE (THIS.cDirDat + 'Northwind') SHARED ENDIF SET DATABASE TO 'Northwind' *-- Consulta a los Clientes de Northwind SELECT CompanyName, ContactName, ; Address, PostalCode, City, Country ; FROM Customers ; INTO CURSOR Clientes *-- Copio el cursor al archivo para combinar lcArchivo = SYS(2015) COPY TO (THIS.cDirApp + lcArchivo) TYPE CSV USE IN Clientes THIS.cDataSource = THIS.cDirApp + FORCEEXT(lcArchivo,'CSV') RETURN ENDPROC *-------------------------------------------------- * Combino la Carta *-------------------------------------------------- PROCEDURE CombinarCarta(toDoc) WITH toDoc.MailMerge .MainDocumentType = 0 && wdFormLetters .OpenDataSource(THIS.cDataSource) .Execute() ENDWITH WITH THIS.oWord *-- Cambio la Carpeta del cuadro de diálogo 'Guardar...' .ChangeFileOpenDirectory(THIS.cDirApp) *-- Maximizo y hago visible .WINDOWSTATE = 1 && wdWindowStateMaximize .VISIBLE = .T. && True ENDWITH RETURN ENDPROC *-------------------------------------------------- * Guardo el Documento, si tlCierra = .T. lo cierra *-------------------------------------------------- PROCEDURE GuardarCarta(toDoc, tlCierra) *-- Guardo el documento toDoc.SAVE() IF tlCierra *-- Cierro el documento toDoc.CLOSE() ENDIF ENDPROC ENDDEFINE *-------------------------------------------------- * Fin Clase cWord *--------------------------------------------------El programa Combinar.prg
El siguiente es el código de nuestro programa "Combinar.prg" donde creamos una instancia de la clase cWord y comenzamos a ejecutar los métodos de esa clase.
*------------------------------------------------- * Combinar.prg *------------------------------------------------- LOCAL lo AS OBJECT, loDoc AS OBJECT lo = NEWOBJECT('cWord','cWord.prg') IF lo.CrearServidor() *-- Ejecuto métodos de la clase loDoc = lo.AbrirCarta('MiCarta') lo.GenerarDataSource() lo.CombinarCarta(loDoc) lo.GuardarCarta(loDoc, .T.) ELSE MESSAGEBOX('No se pudo instanciar el servidor', 16, 'Error!') ENDIF lo = .NULL. RETURN *------------------------------------------------- * Fin Combinar.prg *-------------------------------------------------Ejecutando los métodos en la clase cWord
En primer lugar invocamos el método CrearServidor() que nos retorna el objeto oWord que será nuestro servidor de automatización.
Abrir y/o crear la carta
El método AbrirCarta(), abre la carta de Word si esta existe o crea una nueva carta con el método CrearCarta(). Ambos métodos retornan un objeto Document de Word.
Crear la carta
En el caso de crear o abrir una carta ya existente de Word, estas deben contener los nombres de los campos para su reemplazo en la combinación. Estas cartas serán los documentos principales para la combinación.
La fuente de los datos
También debemos crear o abrir los documentos con los datos a combinar. En este ejemplo creamos un archivo del tipo CSV (Valores Separados por Comas) desde una cláusula SELECT a la tabla "Customers" de la base de datos "Northwind"
Obtener los datos a combinar
Crear la fuente de datos (archivo .CSV)
Para esta tarea tenemos el método GenerarDataSource() que crea el archivo con los datos y establece la propiedad cDataSource de la clase cWord.
Combinar la carta
En el método CombinarCarta() ejecutamos las siguientes sentencias para:
- Hacer la carta del tipo Documento Principal.
- Abrir el archivo con la fuente de datos.
- Ejecutar la combinación
Ejecutar la combinación
Guardar la carta
Para finalizar tenemos el método GuardarCarta() que guarda el documento principal, con la posibilidad mediante un parámetro de cerrar el documento.
En este ejemplo el documento combinado que se genera quedará abierto, entonces hacemos la aplicación visible para que el usuario lo guarde o imprima directamente desde la ventana de Word. También establecemos la carpeta donde están los documentos de este ejemplo, para que Word por defecto la seleccione en la ventana de "Guardar...".
Pueden descargar el código fuente de los programas desde el siguiente vínculo: combinar.zip
Hasta la próxima.
Luis María Guayán
aún no lo pruebo pero creo no tener problema para implementarlo. Recién haré un pequeño software de control de obra pública para contratistas y creo que visual FoxPro 9 es una buena alternativa para ello, ya que será un sistema de escritorio. De antemano muchas gracias por tu aportación. Atentamente Juan Carlos Ojeda
ResponderBorrarTENGO UN ARCHIVO YA DISEÑADO EN WORD, AL CUAL SOLO REQUIERO PASAR ALGUNOS DATOS DE UNA TABLA DE VISUAL FOX, TIPO COMBINAR CORRESPONDENCIA, POR METODO DE REEMPLAZO, ASI EVITO REDISEÑAR DE NUEVO EL DOCUMENTO Y SOLO ACTUALIZO LOS DATOS DESDE VISUAL FOX. HABRÁ UNA MANERA DE AUTOMATIZARLO. ALGUIEN ME PUEDE AYUDAR. MI CORREO ES f3rcho68@icloud.com
ResponderBorrarHice todo el procedimiento, pero en
ResponderBorrarWITH toDoc.MailMerge
.MainDocumentType = 0 && wdFormLetters
.OpenDataSource(THIS.cDataSource)
.Execute()
ENDWITH
no me reconoce el cDataSource, y me saca el formulario sin reemplazar los campos
O sea saca el formulario original con los nombres de las variables.