Está en la página 1de 25

Conferencia Visual FoxPro Espaa 2003

Automatizando Office con Visual FoxPro

Luis Mara Guayn Vicente Trapani S.A. Tucumn, Argentina luismaria@portalfox.com

Luis Mara Guayn es programador en lenguajes xBase desde el ao 1990. En 1994 comenz a desarrollar en Microsoft FoxPro 2.6 para Windows. Desde all transit por todas las versiones de FoxPro, hasta la actualidad con la ltima versin de Visual FoxPro. Es el Responsable del rea de Desarrollo Informtico de Vicente Trapani S.A., un establecimiento citrcola industrial en la provincia de Tucumn, en la Repblica Argentina. Es cofundador en el ao 2000, y SysOp de PortalFox, el mayor portal gratuito para todos los desarrolladores en Visual FoxPro de habla hispana. En los aos 2002 y 2003 fue nombrado por Microsoft como MVP (Most Valuable Professional) en Visual FoxPro, por su colaboracin en las distintas comunidades en lnea.

Automatizando Office con Visual FoxPro

Pgina 2

Automatizando Office con Visual FoxPro

Automatizando Office con Visual FoxPro


Tabla de contenidos
Automatizando Office con Visual FoxPro......................................................................................3 Tabla de contenidos................................................................................................................3 Introduccin.............................................................................................................................4 Cmo comenzar?.....................................................................................................................4 Instanciando un Servidor de Automatizacin ...............................................................................4 El Examinador de Objetos de Visual FoxPro..................................................................................5 Aprendamos con IntelliSense......................................................................................................6 El uso de las Macros de Office.....................................................................................................7 Las constantes de Office............................................................................................................8 Combinar correspondencia con Word...........................................................................................9 Definicin de la clase cWord....................................................................................................9 El programa MailMerge.prg....................................................................................................10 Los mtodos en la clase cWord..............................................................................................10 Abrir y/o crear la carta.......................................................................................................11 La fuente de los datos........................................................................................................12 Combinar la carta..............................................................................................................12 Guardar la carta................................................................................................................12 Grficos y tablas dinmicas con Excel........................................................................................12 Dnde est la ayuda?..........................................................................................................13 Formas de exportar los datos de Visual FoxPro a Excel.............................................................13 Definicin de la clase cExcel...................................................................................................14 Los mtodos de la clase cExcel..............................................................................................14 Exportar los datos..............................................................................................................15 Abrir los libros exportados..................................................................................................15 Guardar y cerrar el libro.....................................................................................................15 Generar un grfico................................................................................................................15 El programa Grafico.prg.....................................................................................................16 Generar una tabla dinmica...................................................................................................17 Programa TablaDinamica.prg..............................................................................................18 Otros mtodos auxiliares....................................................................................................19 Enviar y leer correo con Outlook...............................................................................................19 Versiones de Outlook............................................................................................................20 Un breve ejemplo.................................................................................................................20 Problemas de seguridad........................................................................................................20 Y ahora que? ...................................................................................................................21 Definicin de la clase cOutlook...............................................................................................21 El formulario de ejemplo.......................................................................................................22 Los mtodos de la clase cOutlook...........................................................................................22 Enviar un correo................................................................................................................23 Leer los correos.................................................................................................................24 Resumen................................................................................................................................25

Pgina 3

Automatizando Office con Visual FoxPro

Introduccin
Visual FoxPro es una poderosa herramienta, pero hay tareas que no las puede realizar l solo. Por ejemplo si tenemos una aplicacin en la cual queremos enviar un correo, realizar un grfico, escribir un documento, formatear un texto, etc., necesitamos de otras herramientas. Para automatizar estas tareas desde Microsoft Visual FoxPro, elegimos la herramienta Microsoft Office. En este documento vamos a ver como podemos Automatizar Office desde Visual FoxPro, vamos a conocer las distintas herramientas que disponemos y veremos algunos ejemplos de cdigo. Todos los ejemplos descriptos fueron realizados con Microsoft Visual FoxPro 8 y Microsoft Office XP.

Cmo comenzar?
Lo primero que debemos preguntarnos es cmo comenzar la tarea de automatizacin? Esta pregunta pareciera que tiene una respuesta difcil, pero veremos... La mayora de la informacin disponible en: la Ayuda de Office, los artculos de la Base de Conocimientos de Microsoft (MSKB) o en la Red de Desarrolladores de Microsoft (MSDN) esta escrita en Visual Basic y Visual Basic for Application. Como una desventaja ms para los desarrolladores en Visual FoxPro de habla hispana, la informacin disponible en Internet esta generalmente en ingls. En espaol, existen varios artculos, ideas y trucos disponibles en los siguientes sitios de la Web: Sitio de MSDN Latinoamrica: http://www.microsoft.com/latam/msdn Sitio de MSDN Espaa: http://www.microsoft.com/spain/msdn Sitio de MSDN en Espaol: http://www.microsoft.com/spanish/msdn PortalFox: http://www.portalfox.com Revista FoxPress: http://www.fpress.com Revista UTMag (edicin en espaol): http://www.universalthread.com/spanish/magazine

En ingls existe un excelente libro para tener en cuenta a la hora de automatizar Office: "Microsoft Office Automation with Visual FoxPro" escrito por Tamar E. Granor y Della Martin, editado en el mes de Junio de 2000. Est disponible para su compra en formato impreso y electrnico en el sitio de Hentzenwerke: http://www.hentzenwerke.com

Instanciando un Servidor de Automatizacin


Para comenzar a utilizar la automatizacin de Office, vamos a crear una instancia del servidor. Esto se logra desde Visual FoxPro con las funciones CREATEOBJECT() o GETOBJECT(). Con CREATEOBJECT() siempre se crea una nueva instancia del servidor, aunque exista una instancia de dicho servidor. Para crear una instancia de Word, Excel y Outlook se ejecutan las siguientes funciones: loWord = CREATEOBJECT('Word.Application') loExcel = CREATEOBJECT('Excel.Application')

Pgina 4

Automatizando Office con Visual FoxPro

loOutlook = CREATEOBJECT('Outlook.Application') Con GETOBJECT() se instancia al servidor de la siguiente forma: loExcel = GETOBJECT( , 'Excel.Application') Si no existe una instancia disponible del servidor, el comando fallar y aparecer el Error OLE 1426. Para evitar este error sin importar si existe o no una instancia del servidor, pasamos como parmetro el nombre del archivo. loExcel = GETOBJECT('C:\MiPlanilla.xls', 'Excel.Application') Por defecto, la instancia del servidor estar oculta. Podemos hacer visible la instancia con la propiedad Visible = .T. Esto lo haremos solo para ver los cambios que producimos, generalmente en la etapa de desarrollo, ya que esto har ms lento el proceso de automatizacin.

El Examinador de Objetos de Visual FoxPro


A partir de la versin 7 de Visual FoxPro, podemos disponer del "Examinador de Objetos" que nos permite examinar una gran cantidad de informacin til sobre las propiedades y mtodos de cualquier servidor de automatizacin, en este caso de las aplicaciones de Microsoft Office. El Examinador de Objetos de Visual FoxPro tambin nos permite ver la ubicacin del archivo de ayuda, con solo hacer clic en el nodo raz. El nombre del archivo de ayuda es mostrado en la parte inferior del Examinador de Objetos (Figura 1). Si el archivo de ayuda se encuentra en la misma carpeta de la aplicacin, ste se mostrar como un vnculo y lo podemos abrir desde all. Si el archivo de ayuda no se encuentra, el Examinador de Objetos nos indicar "No instalado". Se puede copiar el archivo de ayuda a la carpeta de la aplicacin. En el caso de Microsoft Office XP en Espaol este se encuentra en "C:\Archivos de programa\Microsoft Office\Office10\3082\"

Figura 1: El Explorador de Objetos de Visual FoxPro Con el Explorador de Objetos, podemos recorrer las distintas propiedades, eventos y mtodos (PEMs), con la sintaxis correspondiente a cada caso (Figura 2).

Pgina 5

Automatizando Office con Visual FoxPro

Figura 2: Los mtodos y su sintaxis Con el Examinador de Objetos tambin podemos tener acceso a los valores de las distintas constantes de cada aplicacin (Figura 3).

Figura 3: Las constantes y sus valores

Aprendamos con IntelliSense


Uno de los cambios ms llamativos a partir de la versin 7 de Visual FoxPro, es la implementacin de IntelliSense. Esta herramienta nos permite conocer acerca de los objetos, sus mtodos y propiedades directamente desde la "Ventana de Comandos" o desde el "Editor de programas" de Visual FoxPro.

Pgina 6

Automatizando Office con Visual FoxPro

Una vez instanciado el objeto desde la "Ventana de Comandos" o declarado desde el "Editor", con solo escribir el nombre del objeto nos aparecern sus propiedades y mtodos (Figura 4) y la sintaxis correspondiente (Figura 5).

Figura 4: Las distintas propiedades y mtodos mostrados con IntelliSense

Figura 5: La sintaxis de un mtodo

El uso de las Macros de Office


Una manera fcil de comenzar la tarea de automatizacin, es generar el cdigo de automatizacin grabando una Macro con la aplicacin de Office que deseamos automatizar. Esto lo logramos con el "Grabador de Macros" que recuerda las tareas que ejecutamos y genera automticamente un cdigo en VBA (Visual Basic for Application).

Figura 6: Grabar una macro en Word

Pgina 7

Automatizando Office con Visual FoxPro

Figura 7: Cdigo VBA generado automticamente Podemos fcilmente traducir el cdigo generado en VBA a Visual FoxPro: ChangeFileOpenDirectory 'D:\Espana\Automation\Documentos\' Documents.Open FileName:='Automation.doc', ConfirmConversions:=False, _ ReadOnly:=False, AddToRecentFiles:=False, PasswordDocument:='', _ PasswordTemplate:='', Revert:=False, WritePasswordDocument:='', _ WritePasswordTemplate:='', Format:=wdOpenFormatAuto El cdigo en Visual FoxPro quedara: loWord.Documents.Open('D:\Espana\Automation\Documentos\Automation.doc', ; .F., .F., .F., '', '', .F., '', '',wdOpenFormatAuto) Los pasos a seguir para esta traduccin son los siguientes: Encerrar con parntesis la lista de parmetros Observar una llamada tipo del mtodo y ordenar los parmetros en el orden que estos aparecen. Quitar los nombres de los parmetros y los smbolos ':=' Reemplazar los nombres de constantes por sus valores, como por ejemplo "True" con .T. 1. Una alternativa (como en el ejemplo) es definir estos valores con: #DEFINE wdOpenFormatAuto 0 #DEFINE true .T.

Las constantes de Office


Si bien disponemos de las herramientas como el Examinador de Objetos o IntelliSense para facilitar la tarea de automatizacin, existen otras herramientas que nos permitirn tener acceso a las constantes y crear fcilmente un archivo de encabezados ("Archivo.h") para definirlas y utilizarlas directamente desde Visual FoxPro. Un ejemplo de un archivo de encabezados es: #DEFINE olTo #DEFINE olCC #DEFINE olBCC 1 2 3

En Visual FoxPro incluimos un archivo de cabecera con la siguiente orden:

Pgina 8

Automatizando Office con Visual FoxPro

#INCLUDE 'Archivo.h' Para la creacin de estos archivos disponemos al menos de dos herramientas: Cdigo en VFP de Trevor Hancock (Base de Conocimientos de Microsoft, Artculo 285396) disponible en: http://support.microsoft.com/?scid=285396 Programa de utilidades de Rick Strahl (GetConstants) disponible libremente en: http://www.west-wind.com/webtools.asp

Combinar correspondencia con Word


En este ejemplo vamos a abrir, crear y completar con datos una carta en Microsoft Word desde Visual FoxPro, y vamos a utilizar una gran herramienta de Word como lo es "Combinar Correspondencia" (Mail Merge). Los datos a combinar en este ejemplo los tomaremos de la base de datos "Northwind". En un caso desde Visual FoxPro y en el otro desde un servidor SQL Server 2000.

Definicin de la clase cWord


Para combinar correspondencia disponemos de una clase definida por el usuario, llamada cWord con los mtodos necesarios para esta tarea. Miremos las primeras lneas de la definicin de esta clase: DEFINE CLASS cWord AS CUSTOM *-- Interfaz de ApplicationEvents2 IMPLEMENTS ApplicationEvents2 IN 'Word.Application' *-* Propiedades *-oWord = .NULL. && Objeto Word ... ... En la definicin de la clase cWord vemos la clusula IMPLEMENTS que nos especifica que la definicin de la clase hereda la interfaz de otro componente COM (en este caso Word). Esto nos permitir que los eventos de Word interacten con el cdigo de Visual FoxPro. Con ello podremos controlar, por ejemplo si hacemos la aplicacin visible, cuando el usuario cierra Word y evitar que un objeto de Visual FoxPro quede referenciado a este. Cuando implementamos una interfaz debemos incluir en la definicin de clase todos los mtodos de dicha interfaz. Utilizamos el nombre de interfaz como principio del nombre de los mtodos (por ejemplo, ApplicationEvents2_Quit). As evitamos conflictos entre dos interfaces que contengan mtodos con el mismo nombre. Para esta tarea que pareciera tan compleja, usamos el Examinador de Objetos de Visual FoxPro para arrastrar y colocar una definicin de interfaz en el cdigo y ahorrar tiempo. La instruccin IMPLEMENTS, junto con los dems mtodos implementados con sus parmetros, se escribir automticamente!!! Para vincular los mtodos del servidor con los mtodos de la interfaz implementados en el objeto de Visual FoxPro, utilizamos la funcin EventHandler() presente desde la versin 7 de Visual FoxPro. Este tipo de vnculo requiere que el objeto Visual FoxPro y el componente COM estn activos. Como expresamos anteriormente, toda esta implementacin en nuestra aplicacin es solo para saber cuando se ejecuta el evento Quit en el servidor de automatizacin. Cuando esto ocurre liberamos el objeto de Visual FoxPro con la siguiente sentencia en el mtodo

Pgina 9

Automatizando Office con Visual FoxPro

ApplicationEvents2_Quit: THIS.oWord = .NULL.

El programa MailMerge.prg
Este es el cdigo de nuestro programa "MailMerge.prg", en donde creamos una instancia de la clase cWord y comenzamos a ejecutar sus mtodos. LOCAL lo AS OBJECT, loDoc AS OBJECT lo = NEWOBJECT('cWord','cWord.prg') IF lo.CrearServidor() *-- Vinculo los eventos de Word a mtodos del objeto 'lo' IF NOT EVENTHANDLER(lo.oWord, lo) MESSAGEBOX('No se pudo vincular a los eventos de Word', 16, 'Error!' ) ENDIF *-- Maximizo y hago visible lo.oWord.WINDOWSTATE = 1 && wdWindowStateMaximize lo.oWord.VISIBLE = .T. loDoc = lo.AbrirCarta('Carta') lo.GenerarDataSource('CSV') *lo.GenerarDataSource('ODC') lo.CombinarCarta(loDoc) lo.GuardarCarta(loDoc, .T.) *-- Desvinculo los eventos de Word IF NOT EVENTHANDLER(lo.oWord, lo, .T.) MESSAGEBOX('No se pudo desvincular a los eventos de Word', 16, 'Error!' ) ENDIF ELSE MESSAGEBOX('No se pudo instanciar el servidor', 16, 'Error!') ENDIF lo = .NULL. RETURN

Los mtodos en la clase cWord


En primer lugar invocamos el mtodo CrearServidor() que nos crea una instancia de Word. Ante riormente vimos que podamos instanciar a Word con la funcin: GETOBJECT('Word.Application') y si no exista una instancia de Word, surge el Error OLE 1426. Para evitar esto, Visual FoxPro 8 trae un nuevo mecanismo para el manejo de errores, implementado mediante el bloque de sentencias TRY ... CATCH ... FINALLY. El cdigo que potencialmente puede producir un error, se asla en la clusula TRY (estas se pueden anidar), y cuando el error efectivamente ocurre, el control de la ejecucin pasa al cdigo en la clusula CATCH, en el orden que aparecen dentro del bloque (en forma similar a cmo funciona el DO CASE). La clusula opcional FINALLY, se ejecuta, se haya producido o no el error. Lo novedoso de este mecanismo es que siempre que se produce un error dentro de un bloque TRY ... CATCH ... FINALLY, Visual FoxPro crea un objeto de la nueva clase Exception. *-- Manejo el error con TRY ... CATH ... FINALLY TRY *-- Instancio el objeto THIS.oWord = GETOBJECT( , 'Word.Application') WAIT WINDOW 'Ya existe una instancia de Word...' TIMEOUT 2 CATCH TRY

Pgina 10

Automatizando Office con Visual FoxPro

*-- Creo el objeto THIS.oWord = CREATEOBJECT('Word.Application') WAIT WINDOW 'Nueva instancia de Word...' TIMEOUT 2 CATCH MESSAGEBOX('Microsoft Word no est instalado.', 16, 'Problemas!!!') FINALLY ENDTRY FINALLY ENDTRY RETURN VARTYPE(THIS.oWord) = 'O' Para que este ejemplo sea ms descriptivo, vamos a hacer visible a la aplicacin Word para ver paso a paso como se ejecutan los distintos mtodos. Esto lo hacemos en la sentencia: lo.oword.VISIBLE = .T.

Abrir y/o crear la carta


El mtodo AbrirCarta(), abre la carta de Word si esta existe o crea una nueva carta con el mtodo CrearCarta(). Ambos mtodos retornan un objeto Document de Word. PROCEDURE AbrirCarta(tcArchivo) LOCAL loDoc AS 'Word.Document' tcArchivo = FORCEEXT(tcArchivo,'DOC') IF NOT FILE(THIS.cDirDoc + 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.cDirDoc + tcArchivo) *-- y me aseguro que no tiene un documento asociado loDoc.MailMerge.MainDocumentType = -1 && wdNotAMergeDocument ENDIF *-- Retorno un objeto Document RETURN loDoc ENDPROC 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.cDirDoc + tcArchivo) *-- Activo el documento loDoc.ACTIVATE *-- Comienzo a 'escribir' el documento WITH THIS.oWord.SELECTION .FONT.NAME = 'Tahoma' .FONT.SIZE = 10 ... ENDWITH RETURN loDoc ENDPROC 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 combinacin. Estas cartas sern los documentos principales para la combinacin.

Pgina 11

Automatizando Office con Visual FoxPro

La fuente de los datos


Tambin debemos crear o abrir los documentos con los datos a combinar. En este ejemplo tenemos dos casos: Crear un archivo tipo CSV (Valores Separados por Comas) desde una clusula SELECT a la tabla "Customers" de la base de datos "Northwind" (que viene con Visual FoxPro). Mediante una Conexin de Datos de Office (ODC) ya existente, traer los datos de la tabla "Customers" de la base de datos "Northwind", pero esta vez desde un servidor SQL Server 2000. Para esta tarea tenemos el mtodo GenerarDataSource() que crea el archivo con los datos y establece la propiedad cDataSource.

Combinar la carta
En el mtodo CombinarCarta() ejecutamos las siguientes sentencias para: Hacer la carta del tipo Documento Principal. Abrir el archivo con la fuente de datos. Ejecutar la combinacin WITH toDoc.MailMerge .MainDocumentType = 0 && wdFormLetters .OpenDataSource(THIS.cDataSource) .Execute() ENDWITH

Guardar la carta
Para finalizar tenemos el mtodo GuardarCarta() que guarda el documento principal, con la posibilidad mediante un parmetro de cerrar el documento. PROCEDURE GuardarCarta(toDoc, tlCierra) *-- Guardo el documento toDoc.SAVE() IF tlCierra *-- Cierro el documento toDoc.CLOSE() ENDIF ENDPROC En este ejemplo el documento combinado que se genera quedar abierto, entonces hacemos la aplicacin visible para que el usuario lo guardar directamente de la ventana de Word. Tambin establecemos la carpeta donde estn los documentos de este ejemplo, para que Word por defecto la seleccione en la ventana de "Guardar...". WITH THIS.oWord .ChangeFileOpenDirectory(THIS.cDirDoc) .VISIBLE = .T. ENDWITH

Grficos y tablas dinmicas con Excel


En nuestras aplicaciones podemos aumentar el impacto de los resultados de las consultas, mostrando los datos en distintos formatos. Para ello vamos a recurrir a dos grandes herramientas de Excel como lo son los grficos y las tablas dinmicas.

Pgina 12

Automatizando Office con Visual FoxPro

Antes de comenzar a analizar el ejemplo en Visual FoxPro vamos a comprender algunos conceptos para poder hacer ms fcil la automatizacin de Excel desde Visual FoxPro, esto siempre lo logramos con los archivos de ayuda. Tambin vamos a conocer distintas formas que disponemos para pasar los datos de Visual FoxPro a Excel.

Dnde est la ayuda?


Para tener una idea mas clara acerca de todos los objetos de Excel, debemos siempre examinar la ayuda disponible. Parte de esta ayuda la podemos encontrar en el tema "Referencia Visual Basic de Microsoft Excel" en el archivo de ayuda "vbaxl10.chm" en la carpeta de la instalacin de Office. En esta ayuda podemos conocer acerca de los objetos disponibles en Excel, como por ejemplo el objeto Chart (Figura 8)

Figura 8: El Objeto Chart de Excel

Formas de exportar los datos de Visual FoxPro a Excel


La forma mas simple, es seleccionar el rea de trabajo con datos de Visual FoxPro (estos pueden estar en una tabla, un cursor o una vista) y ejecutar las ordenes COPY TO ... EXPORT TO ... con los parmetros correspondientes. Si elegimos esta manera, solo necesitamos tener activa la aplicacin de Visual FoxPro. SELECT 'MiCursor' COPY TO 'C:\Planilla1' TYPE XL5 EXPORT TO 'C:\Planilla2' TYPE XL5 Otra forma que disponemos es usando el mtodo DataToClip() del objeto Application de Visual FoxPro ('VisualFoxPro.Application'). La variable del sistema _VFP hace referencia al objeto Application de la instancia actual. De esta manera copiamos un conjunto de registros como texto al "Portapapeles". Recordar que el tercer parmetro del mtodo DataToClip() debemos configurarlo en 3 para que los campos se delimiten con tabulaciones. SELECT 'MiCursor' GO TOP _VFP.DataToClip(,,3)

Pgina 13

Automatizando Office con Visual FoxPro

Una vez que tenemos los datos en el Portapapeles, creamos una instancia de Excel desde Visual FoxPro, creamos un nuevo Libro y pegamos los datos desde el Portapapeles con el mtodo Paste(). loExcel = CREATEOBJECT('Excel.Application') loLibro = loExcel.Workbooks.Add() WITH loLibro .Activate() .ActiveSheet.Paste() .SaveAs('C:\Planilla3.xls') ENDWITH loExcel.Visible = .T. STORE .NULL. TO loLibro, loExcel Otra forma de pasar los datos de Visual FoxPro a Excel, es tener ambas aplicaciones activas y recorrer los datos de nuestra tabla y escribirlos directamente en una Hoja de Excel celda por celda. Esta opcin es mucho ms lenta que las anteriores, pero es til cuando la hoja de Excel ya tiene un formato establecido o cuando queremos escribir frmulas en la hoja de Excel. SELECT 'MiCursor' loExcel = CREATEOBJECT('Excel.Application') loLibro = loExcel.Workbooks.Add() loHoja = loLibro.ActiveSheet() lnFil = 1 && Nombres de campos FOR lnCol = 1 TO FCOUNT() loHoja.Cells(1,lnCol).VALUE = FIELD(lnCol) ENDFOR lnFil = lnFil + 1 && Resto de las filas SCAN ALL FOR lnCol = 1 TO FCOUNT() loHoja.Cells(lnFil,lnCol).VALUE = EVALUATE(FIELD(lnCol)) ENDFOR lnFil = lnFil + 1 ENDSCAN loLibro.SaveAs('C:\Planilla4.xls') loExcel.Visible = .T. STORE .NULL. TO loHoja, loLibro, loExcel

Definicin de la clase cExcel


En esta clase definida por el usuario tendremos los mtodos que nos permitirn crear y manejar los grficos y las tablas dinmicas de Excel desde Visual FoxPro. DEFINE CLASS cExcel AS CUSTOM *-* Propiedades *-oExcel = .NULL. ...

Los mtodos de la clase cExcel


El primer mtodo que vamos a invocar de esta clase es CrearServidor() que establece la propiedad oExcel como una referencia a la instancia de Excel creada. THIS.oExcel = CREATEOBJECT('Excel.Application') Al igual que en la clase cWord que vimos anteriormente, este mtodo tiene el mismo manejo de errores con el bloque TRY ... CATCH ... FINALLY para manejar el error OLE 1426.

Pgina 14

Automatizando Office con Visual FoxPro

Exportar los datos


Para exportar nuestros datos de Visual FoxPro a Excel vamos a elegir la opcin de COPY TO ... que la ejecutamos en el mtodo ExportarDatos(). PROCEDURE ExportarDatos(tcCursor) LOCAL lcArchivo AS CHARACTER lcArchivo = FORCEEXT(THIS.cDirDoc + tcCursor, 'XLS') *-- Opcin COPY TO ... SELECT (tcCursor) COPY TO (lcArchivo) TYPE XL5 RETURN ENDPROC

Abrir los libros exportados


Con el mtodo AbrirLibro() vamos a abrir el libro para comenzar con la automatizacin. Este mtodo retorna un objeto WorkBook de Excel. PROCEDURE AbrirLibro(tcArchivo) LOCAL loLibro AS 'Excel.Workbook' tcArchivo = FORCEEXT(tcArchivo,'XLS') IF FILE(THIS.cDirDoc + tcArchivo) loLibro = THIS.oExcel.Workbooks.OPEN(THIS.cDirDoc + tcArchivo) ELSE *-- Si no existe el libro loLibro = .NULL. ENDIF *-- Retorno un objeto Workbook RETURN loLibro ENDPROC

Guardar y cerrar el libro


Con el mtodo GuardarLibro() vamos a guardar el libro. Este mtodo tiene un parmetro adicional que indica si se cierra el libro luego de guardarlo. PROCEDURE GuardarLibro(toLibro, tlCierra) *-- Guardo el Libro toLibro.SAVE() IF tlCierra *-- Cierro el Libro toLibro.CLOSE() ENDIF RETURN ENDPROC

Generar un grfico
A partir de los resultados de una consulta a las tablas de la base de datos "Northwind", generaremos un grfico del tipo de columnas en 3 dimensiones (xl3DColumnStacked) como lo vemos en la Figura 9, y daremos formato a algunos objetos del grfico, como los ttulos, los ejes y las barras.

Pgina 15

Automatizando Office con Visual FoxPro

Figura 9: Grafico de barras en 3 dimensiones

El programa Grafico.prg
En este programa vamos a crear un objeto cExcel y ejecutaremos los mtodos vistos anteriormente para la creacin del grfico. LOCAL lo AS OBJECT, loLibro AS OBJECT lo = NEWOBJECT('cExcel','cExcel.prg') *-- Genero cursor y exporto datos lo.VtaAnualEmpleado(1997, 'VtaAnualEmpleado') lo.ExportarDatos('VtaAnualEmpleado') IF lo.CrearServidor() *-- Maximizo y hago visible lo.oExcel.WINDOWSTATE = -4137 && xlMaximized lo.oExcel.VISIBLE = .T. *-- Abro el libro copiado loLibro = lo.AbrirLibro('VtaAnualEmpleado') *-- Genero grfico lo.GenerarGrafico(loLibro, 'Ventas Anuales por Empleado (AO 1997)') *--- Grabo planilla y cierro lo.GuardarLibro(loLibro, .T.) *-- Cierro el servidor lo.CerrarServidor() ELSE MESSAGEBOX('No se pudo instanciar el servidor', 16, 'Error!') ENDIF lo = .NULL. RETURN El mtodo GenerarGrafico() de la clase cExcel, es el que hace la tarea propiamente dicha. PROCEDURE GenerarGrafico(toLibro, tcTitulo) LOCAL lcRango AS CHARACTER, oGrafico AS 'Excel.Chart', ; loHoja AS 'Excel.WorkSheet' loHoja = toLibro.ActiveSheet lcRango = 'A1:' + CHR(loHoja.UsedRange.COLUMNS.COUNT + 64) + ; ALLTRIM(STR(loHoja.UsedRange.ROWS.COUNT)) loGrafico = THIS.oExcel.Charts.ADD WITH loGrafico

Pgina 16

Automatizando Office con Visual FoxPro

*-- Tipo, rango y localizacin .ChartType = 55 && xl3DColumnStacked .SetSourceData(loHoja.RANGE(lcRango), 2) .Location(1, 'Ventas Anuales') && xlLocationAsNewSheet = 1 *-- Titulo .HasTitle = .T. .ChartTitle.TEXT = tcTitulo WITH .ChartTitle.FONT .NAME = 'Arial' .SIZE = 14 .Bold = .T. ENDWITH *-- Ejes WITH .Axes(1,1) .HasTitle = .T. .AxisTitle.TEXT = 'Empleado' ENDWITH WITH .Axes(2,1) .HasTitle = .T. .AxisTitle.TEXT = '$' ENDWITH *-- Sin Leyendas .HasLegend = .F. *-- Formato 3D .RightAngleAxes = .T. .AutoScaling = .T. *-- Grupo de grfico WITH .ChartGroups(1) *-- Ancho separacin barras .GapWidth = 50 ENDWITH ENDWITH RETURN ENDPROC

Generar una tabla dinmica


Nuestro programa de ejemplo es "TablaDinamica.prg" que crea una instancia de la clase cExcel y ejecuta sus mtodos para generar la tabla dinmica. En nuestro ejemplo vamos a generar una tabla dinmica que nos muestra las Ventas Anuales agrupadas por Pas, Empleado y Tipo de Producto.

Figura 10: Diseo de la tabla dinmica

Pgina 17

Automatizando Office con Visual FoxPro

Con anterioridad a la programacin de los mtodos debemos disear la forma de la tabla dinmica que deseamos generar. El diseo elegido lo observamos en la Figura 10.

Programa TablaDinamica.prg
Este es el cdigo de nuestro programa: LOCAL lo AS OBJECT, loLibro AS OBJECT lo = NEWOBJECT('cExcel','cExcel.prg') *-- Genero cursor y exporto datos lo.VtaAnualPais('VtaAnualPais') lo.ExportarDatos('VtaAnualPais') IF lo.CrearServidor() *-- Maximizo y hago visible lo.oExcel.WINDOWSTATE = -4137 && xlMaximized lo.oExcel.VISIBLE = .T. *-- Abro el libro copiado loLibro = lo.AbrirLibro('VtaAnualPais') *-- Genero tabla dinmica lo.GenerarTablaDinamica(loLibro) *--- Grabo planilla y cierro lo.GuardarLibro(loLibro, .T.) *-- Cierro el servidor lo.CerrarServidor() ELSE MESSAGEBOX('No se pudo instanciar el servidor', 16, 'Error!') ENDIF lo = .NULL. RETURN Para generar la tabla dinmica ejecutamos el mtodo GenerarTablaDinamica() de la clase cExcel. Este mtodo nos genera la tabla dinmica (Figura 11) ordenada descendentemente por las Ventas por Pas. PROCEDURE GenerarTablaDinamica(toLibro) LOCAL laPagina(1), laFilas(2), laColumnas(1), lcRango *--- Arrays con los datos de la tabla dinmica laPagina(1)='Anio' laFilas(1)='Pais' laFilas(2)='Empleado' laColumnas(1)='TipoProd' lcRango = 'A1:E1275' WITH THIS.oExcel *--- Formato de los datos hoja principal .Cells.SELECT .SELECTION.COLUMNS.AUTOFIT .COLUMNS('E:E').SELECT .SELECTION.NumberFormat = '$ #,##0.00' .RANGE('A2').SELECT *--- Llamo al generador de Tablas Dinmicas .ActiveSheet.PivotTableWizard(1, lcRango, '', 'TablaDinamica') *--- Armo la Tabla dinmica WITH .ActiveSheet.PivotTables('TablaDinamica') .AddFields(@laFilas, @laColumnas, @laPagina) WITH .PivotFields('Ventas') .ORIENTATION = 4 && xlDataField .NumberFormat = '$ #,##0.00' ENDWITH .PivotFields('Pais').AutoSort(2,'Suma de ventas') && xlDescending = 2

Pgina 18

Automatizando Office con Visual FoxPro

ENDWITH *--- Formato de los datos hoja tabla dinmica .Cells.SELECT .SELECTION.COLUMNS.AUTOFIT .ActiveSheet.NAME = 'Ventas Anuales' .RANGE('A2').SELECT ENDWITH RETURN ENDPROC

Figura 11: Tabla dinmica generada

Otros mtodos auxiliares


En la clase cExcel tambin existen otros mtodos, solo vlidos para este ejemplo. Estos mtodos son VtaAnualPais() y VtaAnualEmpleado() utilizados para crear los cursores con los datos para exportar a Excel. Estos cursores toman los datos de la base de datos "Northwind" que se encuentra en la carpeta "\Samples\Northwind" de la carpeta de la instalacin original de Visual FoxPro.

Enviar y leer correo con Outlook


El modelo de objetos de Outlook es muy rico y poderoso. Esta interfaz est disponible como un servidor de automatizacin, o sea, que todo lo podemos hacer por programa desde Visual FoxPro. Como en temas anteriores, siempre recurriremos a la ayuda. All podemos ver los distintos objetos de Outlook (Figura 12).

Figura 12: La ayuda de Outlook en el archivo "vbaol10.chm"

Pgina 19

Automatizando Office con Visual FoxPro

Lo primero que debemos hacer para automatizar Outlook, es crear un objeto Outlook, similar a como vimos anteriormente con las otras herramientas de Office. Una vez creado el objeto, debemos acceder al origen de los datos, pero esto no lo logramos en forma directa, debemos crear un objeto "NameSpace" apropiado que actuar como entrada (en este ejemplo MAPI). El objeto NameSpace proporciona entre otros, los mtodos Logon y Logoff.

Versiones de Outlook
Seguramente conocemos varias versiones de Outlook, solo daremos las principales caractersticas de cada uno. Outlook Express: No es Outlook, es un programa completamente diferente y no es servidor de automatizacin. Outlook 97 y 2000: Existen dos versiones, Internet Mail Only (IMO) y Corporate Workgroup (C/W). Ambas trabajan con Internet Mail, pero solo Corporate Workgroup trabaja con la interfaz MAPI. Outlook XP: Combina las versiones Internet Mail y Corporate Workgroup.

Un breve ejemplo
Una de las tareas ms fcil de automatizar en Outlook es el envo de un correo. Veremos un ejemplo de solamente unas pocas lneas. LOCAL lcPerfil AS CHARACTER, lcContrasenia AS CHARACTER , ; lcDestinatario AS CHARACTER, lcTema AS CHARACTER , ; lcCuerpo AS CHARACTER LOCAL loOutlook AS "Outlook.Application", ; loNameSpace AS OBJECT, loMailItem AS OBJECT #DEFINE LF_CR CHR(10)+CHR(13) *-- Datos del correo lcPerfil = "Prueba" lcContrasenia = "prueba" lcDestinatario = "luismaria@portalfox.com" lcTema = "Prueba" lcCuerpo = "Prueba desde la Conferencia Visual FoxPro Espaa 2003." + LF_CR lcCuerpo = lcCuerpo + "Saludos desde A Corua." + LF_CR *-- Creo objetoa Outlook y NameSpace loOutlook = CREATEOBJECT("Outlook.Application") loNameSpace = loOutlook.GetNameSpace("MAPI") *-- Ejecuto los mtodos loNameSpace.Logon(lcPerfil , lcContrasenia) loMailItem = loOutlook.CreateItem(0) loMailItem.Recipients.ADD(lcDestinatario) loMailItem.Subject = lcTema loMailItem.Body = lcCuerpo loMailItem.SEND loNameSpace.Logoff loNameSpace = .NULL. loOutlook = .NULL.

Problemas de seguridad
Outlook XP y Outlook 2000 SP2, incluyen los parches de seguridad de Microsoft. Estos parches restringen, entre otras cosas, el acceso a la libreta de direcciones y el envo de correo mediante automatizacin, con el fin de evitar cdigos maliciosos que toman los datos de nuestra libreta de direcciones y envan correo sin nuestro consentimiento.

Pgina 20

Automatizando Office con Visual FoxPro

Cuando intentamos enviar un correo desde Visual FoxPro, se nos presenta el siguiente cuadro de dialogo, que luego de 5 segundos habilita el botn "Si" (Figura 13).

Figura 13: "...intentando enviar correo..." Cuando intentamos acceder a la libreta de direcciones aparece el cuadro de dialogo el cual nos permitir un acceso inmediato, o de 1, 2, 5, 10 minutos que debemos seleccionar (Figuras 14).

Figura 14: "...intentando tener acceso a direcciones..."

Y ahora que?
Estas son algunas de las opciones disponemos nosotros para trabajar con estos parches de seguridad: Mantener la versin de Office 2000 SR-1 y no actualizarla ni instalarle parches de seguridad, con los peligros que esto significa. Si se tienen Outlook y Exchange instalados, el administrador de Exchange, puede disminuir las alertas o registrar algunas aplicaciones como seguras. Outlook Redemption: Es un objeto COM que se adapta fcilmente a la automatizacin y utiliza la MAPI extendida. Esta DLL fue escrita por Dmitry Streblechenko (MS Outlook MVP) y esta disponible en http://www.dimastr.com/redemption. Este es un producto comercial con un valor de U$S 200 aproximadamente. Existe para descarga una versin libre con fines de desarrollo. Express ClickYes: Es un pequeo programa residente que se maneja mediante la API de Windows. Este "presionar" el botn "Si" antes de que el dialogo aparezca. Este programa es gratis y esta disponible en http://www.express-soft.com/mailmate/clickyes.html. En el mismo sitio existe un ejemplo para Visual FoxPro.

Definicin de la clase cOutlook


En este ejemplo disponemos de una clase definida por el usuario, llamada cOutlook con los distintos mtodos para realizar el envo y la lectura de los correos. La definicin de esta clase es la siguiente: DEFINE CLASS cOutlook AS CUSTOM *-- Heredo la interfaz de _Application Events_10 IMPLEMENTS ApplicationEvents_10 IN 'Outlook.Application'

Pgina 21

Automatizando Office con Visual FoxPro

*-- Propiedades oOutlook = .NULL. oNameSpace = .NULL. ... ... Como vimos anteriormente en la definicin de la clase cWord, la sentencia IMPLEMENTS nos permitir interactuar con los eventos de Outlook desde Visual FoxPro. Solo pondremos cdigo para interactuar ApplicationEvents_10_Quit(): WITH THIS .oNameSpace = .NULL. .oOutlook = .NULL. ENDWITH con el evento Quit de Outlook en el mtodo

El formulario de ejemplo
En este ejemplo utilizaremos un formulario con un objeto PageFrame con dos Pginas, una para enviar correo y la otra para leer los correos desde la Bandeja de Entrada. En el mtodo Init() creamos una instancia de la clase cOutlook y vinculamos los eventos de Outlook: THISFORM.oCorreo = NEWOBJECT('cOutlook','cOutlook.prg') IF THISFORM.oCorreo.CrearServidor() *-- Vinculo los eventos de Outlook a mtodos del objeto oCorreo IF NOT EVENTHANDLER(THISFORM.oCorreo.oOutlook, THISFORM.oCorreo) MESSAGEBOX('No se pudo vincular a los eventos de Outllok', 16, 'Error!' ) ENDIF ENDIF Tambin en el mtodo Init() llamamos a un formulario para el inicio de sesin: DO FORM Inicio WITH THISFORM.oCorreo TO llAceptar IF NOT (llAceptar AND THISFORM.oCorreo.IniciarSesion()) MESSAGEBOX('Fall el inicio sesin', 48, 'Inicio de sesin') RETURN .F. ENDIF

Los mtodos de la clase cOutlook


En el inicio del formulario invocbamos al mtodo CrearServidor() que establece una referencia a la instancia de Outlook en la propiedad oOutlook. THIS.oOutlook = CREATEOBJECT('Outlook.Application') Igualmente como en las clases anteriores, este mtodo tiene el manejo de errores con el bloque TRY ... CATCH ... FINALLY. En este mtodo tambin creamos un objeto NameSpace que nos permitir acceder a las carpetas especiales de Outlook. THIS.oNameSpace = THIS.oOutlook.GetNameSpace('MAPI')

Pgina 22

Automatizando Office con Visual FoxPro

Enviar un correo
Antes de invocar el mtodo EnviarCorreo(), configuramos todas las propiedades necesarias para el envo de correo. Esto lo hacemos en el mtodo Click() del botn "Enviar". WITH THISFORM.oCorreo .CargarVector(THIS.PARENT.txtTo.VALUE, 'aTO') .CargarVector(THIS.PARENT.txtCC.VALUE, 'aCC') .CargarVector(THIS.PARENT.txtAdjunto.VALUE, 'aAdjuntos') .cTema = ALLTRIM(THIS.PARENT.txtTema.VALUE) .cCuerpo = ALLTRIM(THIS.PARENT.edtCuerpo.VALUE) IF .EnviarCorreo() MESSAGEBOX('Mensaje enviado con xito.', 64, 'Aviso') THISFORM.LimpiarPagina() ELSE MESSAGEBOX('No se pudo enviar el mensaje.', 48, 'Problemas') ENDIF ENDWITH RETURN En el mtodo EnviarCorreo() de la clase cOutlook creo un nuevo mensaje y lo armo segn las propiedades anteriormente configuradas. PROCEDURE EnviarCorreo() LOCAL loMensaje AS OBJECT, llRet AS Logical LOCAL lnI AS INTEGER, lnIndex AS INTEGER *-- Creo un nuevo mensaje WITH THIS loMensaje = .oOutlook.CreateItem(0) IF VARTYPE(loMensaje) = 'O' loMensaje.Subject = .cTema loMensaje.Body = .cCuerpo *-- Recipientes lnIndex = 0 *-- TO lnLen = ALEN(.aTO) FOR lnI = 1 TO lnLen IF NOT EMPTY(.aTO(lnI)) lnIndex = lnIndex + 1 loMensaje.Recipients.ADD(.aTO(lnI)) loMensaje.Recipients(lnIndex).TYPE = 1 ENDIF ENDFOR *-- CC lnLen = ALEN(.aCC) FOR lnI = 1 TO lnLen IF NOT EMPTY(.aCC(lnI)) lnIndex = lnIndex + 1 loMensaje.Recipients.ADD(.aCC(lnI)) loMensaje.Recipients(lnIndex).TYPE = 2 ENDIF ENDFOR *-- BCC lnLen = ALEN(.aBCC) FOR lnI = 1 TO lnLen IF NOT EMPTY(.aBCC(lnI)) lnIndex = lnIndex + 1 loMensaje.Recipients.ADD(.aBCC(lnI)) loMensaje.Recipients(lnIndex).TYPE = 3 ENDIF

Pgina 23

Automatizando Office con Visual FoxPro

ENDFOR *-- Adjuntos lnLen = ALEN(.aAdjuntos) FOR lnI = 1 TO lnLen IF NOT EMPTY(.aAdjuntos(lnI)) AND FILE(.aAdjuntos(lnI)) loMensaje.Attachments.ADD(.aAdjuntos(lnI)) ENDIF ENDFOR llRet = loMensaje.SEND ELSE llRet = .F. ENDIF ENDWITH RETURN llRet ENDPROC

Leer los correos


Para leer los correos de la bandeja de entrada invocamos el mtodo LeerMensajes() de la clase cOutlook desde el mtodo Click() del botn "Leer". ZAP IN curMsg IF THISFORM.oCorreo.LeerMensajes(THIS.PARENT.opgTipo.VALUE = 1, 'curMsg') GO TOP IN curMsg THIS.PARENT.grdMensajes.SETFOCUS ELSE MESSAGEBOX('No existen mensajes para traer', 64, 'Aviso') ENDIF THIS.PARENT.edtCuerpo.REFRESH En el mtodo LeerMensajes() creamos un objeto loInbox y traemos todos los mensajes, o solo los mensajes "No ledos" y recorremos uno a uno para cargarlos en un cursor que luego mostraremos en una Grilla y un Cuadro de Edicin. PROCEDURE LeerMensajes(tlNoLeidos, tcAlias) LOCAL loInbox AS 'Outlook.MAPIFolder', loMensajes AS 'Outlook.Items' LOCAL loMsg AS OBJECT, lnI AS INTEGER, llRet AS Logical IF EMPTY(tcAlias) tcAlias = 'curMsg' ENDIF *-- Inbox loInbox = THIS.oNameSpace.GetDefaultFolder(6) *-- Mensajes del Inbox IF tlNoLeidos loMensajes = loInbox.Items.RESTRICT("[Unread] = True") ELSE loMensajes = loInbox.Items ENDIF IF VARTYPE(loMensajes) = 'O' WITH loMensajes IF .Count > 0 *-- Recorro los mensajes FOR lnI = 1 TO .COUNT loMsg = .ITEM(lnI) WITH loMsg INSERT INTO (tcAlias) ; (EnviadoPor, Tema, Recibido, Cuerpo, NoLeido) ; VALUES (.SenderName, .Subject, .ReceivedTime, .Body, .UnRead) ENDWITH ENDFOR

Pgina 24

Automatizando Office con Visual FoxPro

llRet = .T. ELSE llRet = .F. ENDIF ENDWITH ELSE llRet = .F. ENDIF RETURN llRet ENDPROC

Resumen
En este documento vimos solo algunos ejemplos de automatizacin de Office. Las posibilidades son muchas y cada una depende de la solucin que debemos implementar en nuestras aplicaciones. Recuerden que todo el poder que nos brindan las distintas herramientas de Office, pueden ser manejadas desde Visual FoxPro. Solo es cuestin de adoptar alguna de las tcnicas vistas y ponerse a trabajar...

Pgina 25