Por Pedro Pascua
© Copyrights 1998 by FoxPress, All rights reserved
FoxPress, Abril 1998
En las siguientes líneas vamos a hacer una leve incursión en la programación del Word utilizando, como no, nuestra herramienta favorita, el Fox. El Word, desde hace ya unas cuantas versiones, viene siendo una herramienta bastante flexible en cuanto a la personalización a través de macros o de lenguajes como lo que se llamó WordBasic y que ha evolucionado para acabar integrándose en el Visual Basic for Applications (VBA). Lenguaje común de programación para todas las herramientas de Microsoft Office. Aunque este lenguaje está pensado para aumentar la funcionalidad de los macros en Word utilizando la sintaxis y metodología del Visual Basic, la mayoría de las propiedades y métodos de los objetos que emplea para controlar los documentos, pueden ser utilizados desde otros lenguajes, instanciándolos como clase OLE. Para ilustrar esta técnica, vamos a construir un sencillo formulario Fox para lanzar mailings a partir de los datos de una tabla. En el ejemplo, elegiremos primero entre la tabla de clientes o la de empleados. A continuación, seleccionaremos de la lista de nombres, aquellos que queremos incluir en el mailing. Y finalmente, escribiremos el texto común a las cartas. Al pulsar el botón Generar Documento Word, el programa abrirá una sesión de Word y nos creará un nuevo documento con una página para cada carta, incluyendo en la cabecera los datos del cliente o empleado extraídos de la tabla correspondiente y a continuación el texto que hemos escrito en el EditBox. Una vez creado el documento, podremos previsualizarlo, imprimirlo o guardarlo desde nuestro formulario pulsando los botones correspondientes. Para este ejemplo hemos utilizado el VFP5.0 y el Word97, que soporta VBA. No obstante, algunos de los métodos empleados funcionarían con versiones anteriores del Word.
Echemos un vistazo al código. En el Init del formulario creamos los cursores de clientes y empleados que contienen los datos de ejemplo para el mailing. En el destroy limpiaremos los cursores y variables empleados.
** Método Init() del Form ** Public oWord select cust_id,company ; from customer ; order by 2 ; into cursor cCustomer select emp_id,; ALLT(employee.first_name)+; ' '+ALLT(employee.last_name); from employee ; order by 2 ; into cursor cEmployee Thisform.List1.RowSource = 'cCustomer' _Screen.windowstate = 1 ** Método Destroy() del form ** Release oWord Use in cCustomer Use in cEmployee _Screen.windowstate = 2
Para visualizar mejor como nuestro código Fox interactúa con el Word, hemos creado el formulario de tipo Top Level y en el inicio de este, minimizamos la pantalla principal del VFP de modo que en el escritorio solo tengamos el formulario y podamos ver a la vez la ventana del Word cuando pulsemos el botón de previsualizar. En el InteractiveChange() del combo, reasignamos el origen de datos del ListBox:
******************************** ** Combo1.InteractiveChange() * ******************************** If This.DisplayValue = 1 Thisform.List1.RowSource='cCustomer' Else Thisform.List1.RowSource='cEmployee' EndIf Thisform.List1.Refresh()
El listbox tiene la propiedad multiselect a true para que podamos seleccionar varios registros simultáneamente. Lo realmente importante de este ejemplo viene aquí, en el evento click del botón etiquetado Generar documento Word:
************************* ** CmdGenerar.Click() * ************************* PUBLIC oWord #define cr chr(13) oLista = ThisForm.list1 * Contamos el número de páginas (una por * cada registro seleccionado) lnNumPag = 0 For lnLine = 1 To oLista.ListCount lnNumPag = lnNumPag+; +IIF(oLista.Selected(lnLine),1,0) EndFor * Comprobamos que hemos seleccionado * al menos un registro If lnNumPag = 0 MessageBox("No hay registros ; seleccionados",64,"Aviso") Return EndIf * instanciamos el Word Wait Wind "Abriendo sesión Word" NoWait oWord = CreateObject('word.application') * si no se ha podido crear el objeto * salimos del método If Type('oWord') # 'O' Return EndIf * creamos documento nuevo oWord.Documents.Add() oWord.caption='Prueba OLE con Word97' lnPagina = 1 For lnLine = 1 To oLista.ListCount If oLista.Selected(lnLine) Wait Wind "Generando documento:; Página "+allt(str(lnPagina))+; " de "+allt(str(lnNumPag)) NoWait If ThisForm.Combo1.DisplayValue = 1 ** creamos la cabecera de carta a ** clientes con los datos de las tablas Select customer Locate for ; cust_id=oLista.List(lnLine,1) lcCabecera = company + cr +; contact +cr +; address + cr+; postalcode + " " +; city+ cr+; country lcSaludo = "Estimado/a " +; contact Else * Cabecera de la carta a empleados Select employee Locate for ; emp_id = oLista.List(lnLine,1) lcCabecera = ALLT(First_name)+" "+; ALLT(last_name)+ cr+; Address + cr +; postalcode + " " +; city + cr+; country lcSaludo = "Estimado/a"+first_name EndIf * Insertar cabecera oWord.Selection.InsertAfter(lcCabecera) * Insertamos líneas en blanco y fecha lcEspacio = REPLICATE(cr,12) oWord.Selection.InsertAfter(lcEspacio) oWord.Selection.InsertAfter('Fecha: ') oWord.ActiveDocument.Bookmarks.add("fecha") lcEspacio = REPLICATE(cr,3) oWord.Selection.InsertAfter(lcEspacio) oWord.ActiveDocument.Bookmarks.add("saludo") oWord.Selection.InsertAfter(lcEspacio) oWord.ActiveDocument.Bookmarks.add("cuerpo") oWord.selection.Bookmarks('fecha').Select oWord.selection.InsertAfter(date()) oWord.selection.Bookmarks('saludo').select oWord.selection.InsertAfter(lcSaludo+lcEspacio) ** Insertamos el texto de la carta que ; especificamos en el Editbox lcCuerpo = ThisForm.Edit1.Value oWord.selection.Bookmarks('cuerpo').select oWord.selection.InsertAfter(lcCuerpo+cr) oWord.Selection.InsertAfter(lcEspacio+lcEspacio) oWord.selection.InsertAfter('Un cordial ; saludo,'+cr) oWord.Selection.InsertAfter(lcEspacio) oWord.selection.InsertAfter(repl('_',25)) oWord.Selection.InsertAfter(cr) oWord.selection.InsertAfter('Fdo.: Pepe; Pérez') ** Insertamos un salto de página si no ; estamos en la última página If lnPagina < lnNumPag oWord.Selection.InsertAfter(CHR(12)) EndIf Start=oWord.selection.Bookmarks('fecha').select End = oWord.ActiveDocument.; Bookmarks("\ENDOFDOC").select lnPagina = lnPagina +1 EndIf EndFor * especificamos las dimensiones de la ; ventana word oWord.top = 1 oWord.left = 1 oWord.width = 300 oWord.height = 400 MessageBox("Proceso concluido",64,"Aviso") ThisForm.Refresh()
Si no tuviéramos el Word instalado, se produciría un error del tipo, no se ha encontrado la definición de la clase word.application” al intentar crear el objeto oWord. Este error lo procesamos en el evento Error del Botón cmdGenerar:
LPARAMETERS nError, cMethod, nLine AERROR(laERROR) cTextoError = "Error "+ALLT(STR(nError))+CHR(10)+laError[2] MessageBox(cTextoError,16,"Atención")
Una vez concluido este proceso, habilitamos los botones de visualizar, imprimir, etc. Para ello basta hacer un refresh del formulario, ya que en el refresh de cada uno de estos botones hemos incluido la instrucción
This.Enabled = (Type('oWord') = 'O')
para que sólo estén activos si existe el objeto oWord. Mediante estos botones podemos visualizar el documento generado, imprimirlo, revisar su ortografía o salvarlo con estas sencillas órdenes:
** Abrir ventana Preview oword.visible= .t. oWord.ActiveDocument.PrintPreview ** Imprimir oWord.ActiveDocument.PrintOut ** Salvar oWord.ActiveDocument.Save (Salvar como sería oWord.ActiveDocument.SaveAs(nombre.doc) ) ** Ortografía oWord.ActiveDocument.CheckSpelling ** Cerrar documento y salir de Word oWord.ActiveDocument.Close(0) * cerramos documento sin guardar cambios oWord.Quit Release oWord ThisForm.Refresh()
Este ejemplo es bastante sencillo con respecto a las posibilidades de programación que ofrece el Word, ya que el modelo de objetos del Word 97 incorpora aproximadamente 180 objetos. Para encontrar más información sobre este modelo, se puede consultar el tema Microsoft Word Visual Basic Reference en la ayuda del Word, siempre y cuando, eso sí, al instalar el Word, hallamos marcado la opción Online Help for Visual Basic en el checkbox correspondiente del setup. También hay bastante documentación en la web de Microsoft buscando la referencia Microsoft Word Objects en la sección Microsoft Office 97/Visual Basic Programmer’s Guide. Viendo la documentación que hay sobre este tema se aprecia claramente como todo esto está orientado principalmente a su uso desde el omnipresente Visual Basic (como no...), pero bueno, no hay que desanimarse, y con un poco de maña y algún retoque que otro, también los foxeros podemos aprovecharnos de ello.