Está en la página 1de 24

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 co menz 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 estableci miento 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

Automatizando Office con Visual FoxPro


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

Pgina 2

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 pre gunta 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 fun ciones:
loWord = CREATEOBJECT('Word.Application')
loExcel = CREATEOBJECT('Excel.Application')

Pgina 3

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 par metro 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 propie dad 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 4

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 5

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 au tomticamente un cdigo en VBA (Visual Basic for Application).

Figura 6: Grabar una macro en Word

Pgina 6

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 cons tantes 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 7

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.

Pgina 8

Automatizando Office con Visual FoxPro

Cuando esto ocurre liberamos el objeto de Visual FoxPro con la siguiente sentencia en el mtodo
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 clu sula 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

Pgina 9

Automatizando Office con Visual FoxPro

CATCH
TRY
*-- 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 10

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 estable cemos 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 11

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 12

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 reco rrer 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 for mato 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 13

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 14

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 15

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 16

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 17

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 18

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 res tringen, entre otras cosas, el acceso a la libreta de direcciones y el envo de correo mediante auto matizacin, con el fin de evitar cdigos maliciosos que toman los datos de nuestra libreta de direcciones y envan correo sin nuestro consentimiento.

Pgina 19

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 dispo nible 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 20

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():

con el evento

Quit de Outlook en el mtodo

WITH THIS
.oNameSpace = .NULL.
.oOutlook = .NULL.
ENDWITH

El formulario de ejemplo
En este ejemplo utilizaremos un formulario con un objeto PageFrame con dos Pginas, una para en viar 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 21

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 22

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 23

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 maneja das desde Visual FoxPro. Solo es cuestin de adoptar alguna de las tcnicas vistas y ponerse a tra bajar...

Pgina 24

También podría gustarte