You are on page 1of 25

Conferencia Visual FoxPro España 2003

Automatizando Office con Visual FoxPro

Luis María Guayán Vicente Trapani S.A. Tucumán, Argentina luismaria@portalfox.com

Luis María Guayán es programador en lenguajes xBase desde el año 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 versión de Visual FoxPro. Es el Responsable del Área de Desarrollo Informático de Vicente Trapani S.A., un establecimiento citrícola industrial en la provincia de Tucumán, en la República Argentina. Es cofundador en el año 2000, y SysOp de PortalFox, el mayor portal gratuito para todos los desarrolladores en Visual FoxPro de habla hispana. En los años 2002 y 2003 fue nombrado por Microsoft como MVP (Most Valuable Professional) en Visual FoxPro, por su colaboración en las distintas comunidades en línea.

Automatizando Office con Visual FoxPro

Página 2

......15 El programa Grafico..................................................................................................................7 Las constantes de Office.........................................16 Generar una tabla dinámica..............15 Abrir los libros exportados.........................................................9 Definición de la clase cWord......20 ¿Y ahora que? ..................................4 Instanciando un Servidor de Automatización ..........................................................................................................................................................................................................................................................................................................................19 Versiones de Outlook.....................................................................12 ¿Dónde está la ayuda?..................................................20 Problemas de seguridad.....................................................3 Introducción........................................................................................................................................13 Definición de la clase cExcel.................................................................................................5 Aprendamos con IntelliSense..........................................................................15 Guardar y cerrar el libro...................................................................................20 Un breve ejemplo.........................................................................................14 Los métodos de la clase cExcel............................................................................................................................................................................................................................................25 Página 3 ..................................................................................12 Combinar la carta...................11 La fuente de los datos......................................................19 Enviar y leer correo con Outlook......................................................................................................................................................22 Los métodos de la clase cOutlook......................................................................6 El uso de las Macros de Office..............................................................................................................................................................................................................................................................................................................................................................................................................................................................12 Gráficos y tablas dinámicas con Excel.....................9 El programa MailMerge........................................................................................Automatizando Office con Visual FoxPro Automatizando Office con Visual FoxPro Tabla de contenidos Automatizando Office con Visual FoxPro........24 Resumen..........................................................................................23 Leer los correos...........prg.................................................................................................................4 ¿Cómo comenzar?.......................................................10 Abrir y/o crear la carta....................................................................................................................................................................................................21 El formulario de ejemplo....................................................................................15 Generar un gráfico.................................................................................................12 Guardar la carta..............................10 Los métodos en la clase cWord..................................................13 Formas de exportar los datos de Visual FoxPro a Excel...........prg..........................................................................17 Programa TablaDinamica.......................................prg..................................................................................................................................................................................................................................................................3 Tabla de contenidos................................................................4 El Examinador de Objetos de Visual FoxPro...................................................................8 Combinar correspondencia con Word.................................................................................21 Definición de la clase cOutlook.........................................................................................................................................18 Otros métodos auxiliares..........................................22 Enviar un correo........................................................................14 Exportar los datos............................................................................................................................................................................................

los artículos 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.Automatizando Office con Visual FoxPro Introducción Visual FoxPro es una poderosa herramienta. pero hay tareas que no las puede realizar él solo..universalthread.Application') loExcel = CREATEOBJECT('Excel. necesitamos de otras herramientas. vamos a crear una instancia del servidor. En español.microsoft.fpress. elegimos la herramienta Microsoft Office. la información disponible en Internet esta generalmente en inglés. ¿Cómo comenzar? Lo primero que debemos preguntarnos es ¿cómo comenzar la tarea de automatización? Esta pregunta pareciera que tiene una respuesta difícil. aunque exista una instancia de dicho servidor. escribir un documento.portalfox. Esto se logra desde Visual FoxPro con las funciones CREATEOBJECT() o GETOBJECT(). pero veremos. Por ejemplo si tenemos una aplicación en la cual queremos enviar un correo.microsoft. realizar un gráfico.com/spanish/msdn PortalFox: http://www.. Como una desventaja más para los desarrolladores en Visual FoxPro de habla hispana. editado en el mes de Junio de 2000. Todos los ejemplos descriptos fueron realizados con Microsoft Visual FoxPro 8 y Microsoft Office XP. etc. Con CREATEOBJECT() siempre se crea una nueva instancia del servidor.com Revista UTMag (edición en español): http://www.com/spanish/magazine En inglés 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.hentzenwerke.com/latam/msdn Sitio de MSDN España: http://www. Está disponible para su compra en formato impreso y electrónico en el sitio de Hentzenwerke: http://www. La mayoría de la información disponible en: la Ayuda de Office.Application') Página 4 . Para automatizar estas tareas desde Microsoft Visual FoxPro. formatear un texto. existen varios artículos. Para crear una instancia de Word.com Revista FoxPress: http://www..com/spain/msdn Sitio de MSDN en Español: http://www.microsoft. vamos a conocer las distintas herramientas que disponemos y veremos algunos ejemplos de código. Excel y Outlook se ejecutan las siguientes funciones: loWord = CREATEOBJECT('Word. En este documento vamos a ver como podemos Automatizar Office desde Visual FoxPro.com Instanciando un Servidor de Automatización Para comenzar a utilizar la automatización de Office. ideas y trucos disponibles en los siguientes sitios de la Web:       Sitio de MSDN Latinoamérica: http://www.

Página 5 . la instancia del servidor estará oculta. con solo hacer clic en el nodo raíz. podemos disponer del "Examinador de Objetos" que nos permite examinar una gran cantidad de información útil sobre las propiedades y métodos de cualquier servidor de automatización. 'Excel. El Examinador de Objetos de Visual FoxPro también nos permite ver la ubicación del archivo de ayuda.Application') Si no existe una instancia disponible del servidor.T.Application') Con GETOBJECT() se instancia al servidor de la siguiente forma: loExcel = GETOBJECT( .Application') Por defecto. ya que esto hará más lento el proceso de automatización. Para evitar este error sin importar si existe o no una instancia del servidor. loExcel = GETOBJECT('C:\MiPlanilla. Si el archivo de ayuda se encuentra en la misma carpeta de la aplicación. eventos y métodos (PEMs). 'Excel. éste se mostrará como un vínculo y lo podemos abrir desde allí. Si el archivo de ayuda no se encuentra. Podemos hacer visible la instancia con la propiedad Visible = . Esto lo haremos solo para ver los cambios que producimos. pasamos como parámetro el nombre del archivo. El nombre del archivo de ayuda es mostrado en la parte inferior del Examinador de Objetos (Figura 1). con la sintaxis correspondiente a cada caso (Figura 2). en este caso de las aplicaciones de Microsoft Office. el Examinador de Objetos nos indicará "No instalado". el comando fallará y aparecerá el Error OLE 1426. En el caso de Microsoft Office XP en Español 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. generalmente en la etapa de desarrollo.Automatizando Office con Visual FoxPro loOutlook = CREATEOBJECT('Outlook. Se puede copiar el archivo de ayuda a la carpeta de la aplicación. El Examinador de Objetos de Visual FoxPro A partir de la versión 7 de Visual FoxPro.xls'.

Automatizando Office con Visual FoxPro Figura 2: Los métodos y su sintaxis Con el Examinador de Objetos también podemos tener acceso a los valores de las distintas constantes de cada aplicación (Figura 3). sus métodos y propiedades directamente desde la "Ventana de Comandos" o desde el "Editor de programas" de Visual FoxPro. Figura 3: Las constantes y sus valores Aprendamos con IntelliSense Uno de los cambios más llamativos a partir de la versión 7 de Visual FoxPro. es la implementación de IntelliSense. Esta herramienta nos permite conocer acerca de los objetos. Página 6 .

Esto lo logramos con el "Grabador de Macros" que recuerda las tareas que ejecutamos y genera automáticamente un código en VBA (Visual Basic for Application). Figura 4: Las distintas propiedades y métodos mostrados con IntelliSense Figura 5: La sintaxis de un método El uso de las Macros de Office Una manera fácil de comenzar la tarea de automatización. con solo escribir el nombre del objeto nos aparecerán sus propiedades y métodos (Figura 4) y la sintaxis correspondiente (Figura 5).Automatizando Office con Visual FoxPro Una vez instanciado el objeto desde la "Ventana de Comandos" o declarado desde el "Editor". es generar el código de automatización grabando una Macro con la aplicación de Office que deseamos automatizar. Figura 6: Grabar una macro en Word Página 7 .

wdOpenFormatAuto) Los pasos a seguir para esta traducción son los siguientes:  Encerrar con paréntesis la lista de parámetros  Observar una llamada tipo del método y ordenar los parámetros en el orden que estos aparecen. Una alternativa (como en el ejemplo) es definir estos valores con: #DEFINE wdOpenFormatAuto 0 #DEFINE true . existen otras herramientas que nos permitirán tener acceso a las constantes y crear fácilmente un archivo de encabezados ("Archivo. ''.Open FileName:='Automation.F..doc'. ''.h") para definirlas y utilizarlas directamente desde Visual FoxPro. ó 1.. como por ejemplo "True" con . Format:=wdOpenFormatAuto El código en Visual FoxPro quedaría: loWord.F.Documents.  Quitar los nombres de los parámetros y los símbolos ':='  Reemplazar los nombres de constantes por sus valores.T. ConfirmConversions:=False.doc'. 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: Página 8 . . PasswordDocument:=''. Revert:=False. . ..Automatizando Office con Visual FoxPro Figura 7: Código VBA generado automáticamente Podemos fácilmente traducir el código generado en VBA a Visual FoxPro: ChangeFileOpenDirectory 'D:\Espana\Automation\Documentos\' Documents. _ PasswordTemplate:=''. WritePasswordDocument:=''.Open('D:\Espana\Automation\Documentos\Automation. .F. _ ReadOnly:=False. AddToRecentFiles:=False. .T. Las constantes de Office Si bien disponemos de las herramientas como el Examinador de Objetos o IntelliSense para facilitar la tarea de automatización. _ WritePasswordTemplate:=''.. ''.F. ''.

.NULL. llamada cWord con los métodos necesarios para esta tarea. Como expresamos anteriormente.Application' *-* Propiedades *-oWord = . toda esta implementación en nuestra aplicación es solo para saber cuando se ejecuta el evento Quit en el servidor de automatización. crear y completar con datos una carta en Microsoft Word desde Visual FoxPro. Artículo 285396) disponible en: http://support. utilizamos la función EventHandler() presente desde la versión 7 de Visual FoxPro... La instrucción IMPLEMENTS. Miremos las primeras líneas de la definición de esta clase: DEFINE CLASS cWord AS CUSTOM *-. Para esta tarea que pareciera tan compleja.Interfaz de ApplicationEvents2 IMPLEMENTS ApplicationEvents2 IN 'Word. cuando el usuario cierra Word y evitar que un objeto de Visual FoxPro quede referenciado a este. Definición de la clase cWord Para combinar correspondencia disponemos de una clase definida por el usuario. Cuando esto ocurre liberamos el objeto de Visual FoxPro con la siguiente sentencia en el método Página 9 . usamos el Examinador de Objetos de Visual FoxPro para arrastrar y colocar una definición de interfaz en el código y ahorrar tiempo..west-wind. y vamos a utilizar una gran herramienta de Word como lo es "Combinar Correspondencia" (Mail Merge). Con ello podremos controlar.asp Combinar correspondencia con Word En este ejemplo vamos a abrir. Utilizamos el nombre de interfaz como principio del nombre de los métodos (por ejemplo. ¡¡¡se escribirá automáticamente!!! Para vincular los métodos del servidor con los métodos de la interfaz implementados en el objeto de Visual FoxPro.Automatizando Office con Visual FoxPro #INCLUDE 'Archivo. ApplicationEvents2_Quit). Cuando implementamos una interfaz debemos incluir en la definición de clase todos los métodos de dicha interfaz.com/webtools.com/?scid=285396 Programa de utilidades de Rick Strahl (GetConstants) disponible libremente en: http://www.h' Para la creación de estos archivos disponemos al menos de dos herramientas: Código en VFP de Trevor Hancock (Base de Conocimientos de Microsoft. Este tipo de vínculo requiere que el objeto Visual FoxPro y el componente COM estén activos. por ejemplo si hacemos la aplicación visible. Así evitamos conflictos entre dos interfaces que contengan métodos con el mismo nombre. En un caso desde Visual FoxPro y en el otro desde un servidor SQL Server 2000.. junto con los demás métodos implementados con sus parámetros. Esto nos permitirá que los eventos de Word interactúen con el código de Visual FoxPro. En la definición de la clase cWord vemos la cláusula IMPLEMENTS que nos especifica que la definición de la clase hereda la interfaz de otro componente COM (en este caso Word). && Objeto Word .microsoft. Los datos a combinar en este ejemplo los tomaremos de la base de datos "Northwind".

CombinarCarta(loDoc) lo. y cuando el error efectivamente ocurre. 'Error!') ENDIF lo = . Ante– riormente vimos que podíamos instanciar a Word con la función: GETOBJECT('Word.'cWord. se aísla en la cláusula TRY (estas se pueden anidar).NULL. se haya producido o no el error.Application') WAIT WINDOW 'Ya existe una instancia de Word.WINDOWSTATE = 1 && wdWindowStateMaximize lo. en el orden que aparecen dentro del bloque (en forma similar a cómo funciona el DO CASE). lo) MESSAGEBOX('No se pudo vincular a los eventos de Word'.Desvinculo los eventos de Word IF NOT EVENTHANDLER(lo.oWord = GETOBJECT( . 'Word. lo. 16.CrearServidor() *-. surge el Error OLE 1426.. RETURN Los métodos en la clase cWord En primer lugar invocamos el método CrearServidor() que nos crea una instancia de Word. El programa MailMerge.Manejo el error con TRY .GenerarDataSource('ODC') lo..T.Automatizando Office con Visual FoxPro ApplicationEvents2_Quit: THIS. 'Error!' ) ENDIF *-. en donde creamos una instancia de la clase cWord y comenzamos a ejecutar sus métodos.Vinculo los eventos de Word a métodos del objeto 'lo' IF NOT EVENTHANDLER(lo...GenerarDataSource('CSV') *lo.NULL.Maximizo y hago visible lo.oWord.oWord..oWord. LOCAL lo AS OBJECT.. Visual FoxPro crea un objeto de la nueva clase Exception.prg') IF lo.. 16.) MESSAGEBOX('No se pudo desvincular a los eventos de Word'..Application') y si no existía una instancia de Word. CATH . Visual FoxPro 8 trae un nuevo mecanismo para el manejo de errores.. Para evitar esto.T. se ejecuta. loDoc AS OBJECT lo = NEWOBJECT('cWord'. .GuardarCarta(loDoc. 'Error!' ) ENDIF ELSE MESSAGEBOX('No se pudo instanciar el servidor'.Instancio el objeto THIS.. CATCH .) *-. FINALLY.VISIBLE = . FINALLY.prg Este es el código de nuestro programa "MailMerge. CATCH . Lo novedoso de este mecanismo es que siempre que se produce un error dentro de un bloque TRY . .prg".. implementado mediante el bloque de sentencias TRY . loDoc = lo.' TIMEOUT 2 CATCH TRY Página 10 ..T. FINALLY TRY *-.oWord. El código que potencialmente puede producir un error. La cláusula opcional FINALLY.. el control de la ejecución pasa al código en la cláusula CATCH. *-.AbrirCarta('Carta') lo. 16.oWord = ..

ENDWITH RETURN loDoc ENDPROC En el caso de crear o abrir una carta ya existente de Word.Creo el objeto THIS.oWord = CREATEOBJECT('Word.Documents.NAME = 'Tahoma' .Si no existe la carta..oWord.ACTIVATE *-. vamos a hacer visible a la aplicación Word para ver paso a paso como se ejecutan los distintos métodos. loDoc. 'Problemas!!!') FINALLY ENDTRY FINALLY ENDTRY RETURN VARTYPE(THIS.FONT.oWord) = 'O' Para que este ejemplo sea más descriptivo..ADD(. estas deben contener los nombres de los campos para su reemplazo en la combinación.cDirDoc + tcArchivo) *-. Estas cartas serán los documentos principales para la combinación. Abrir y/o crear la carta El método AbrirCarta().oWord.Application') WAIT WINDOW 'Nueva instancia de Word..Guardo el documento como.MailMerge.SIZE = 10 .Creo un nuevo documento loDoc = THIS..cDirDoc + tcArchivo) *-. abre la carta de Word si esta existe o crea una nueva carta con el método CrearCarta().' TIMEOUT 2 CATCH MESSAGEBOX('Microsoft Word no está instalado.oWord.Si existe la carta.Document' tcArchivo = FORCEEXT(tcArchivo.Activo el documento loDoc.Document' *-.OPEN(THIS.cDirDoc + tcArchivo) *-.0) *-.. la creo loDoc = THIS..Retorno un objeto Document RETURN loDoc ENDPROC PROCEDURE CrearCarta(tcArchivo) LOCAL loDoc AS 'Word. Página 11 .SAVEAS(THIS. 16.MainDocumentType = -1 && wdNotAMergeDocument ENDIF *-.oword.'DOC') IF NOT FILE(THIS. PROCEDURE AbrirCarta(tcArchivo) LOCAL loDoc AS 'Word.Comienzo a 'escribir' el documento WITH THIS. la abro loDoc = THIS.'.VISIBLE = ..y me aseguro que no tiene un documento asociado loDoc. Esto lo hacemos en la sentencia: lo.Automatizando Office con Visual FoxPro *-.CrearCarta(tcArchivo) ELSE *-.Documents.FONT. Ambos métodos retornan un objeto Document de Word.T.SELECTION .

En este ejemplo tenemos dos casos:  Crear un archivo tipo CSV (Valores Separados por Comas) desde una cláusula SELECT a la tabla "Customers" de la base de datos "Northwind" (que viene con Visual FoxPro). pero esta vez desde un servidor SQL Server 2000. mostrando los datos en distintos formatos.VISIBLE = . Combinar la carta En el método CombinarCarta() ejecutamos las siguientes sentencias para:  Hacer la carta del tipo Documento Principal.".OpenDataSource(THIS.Automatizando Office con Visual FoxPro La fuente de los datos También debemos crear o abrir los documentos con los datos a combinar. Para esta tarea tenemos el método GenerarDataSource() que crea el archivo con los datos y establece la propiedad cDataSource.MainDocumentType = 0 && wdFormLetters . ENDWITH Gráficos y tablas dinámicas con Excel En nuestras aplicaciones podemos aumentar el impacto de los resultados de las consultas.CLOSE() ENDIF ENDPROC En este ejemplo el documento combinado que se genera quedará abierto. tlCierra) *-.cDataSource) . entonces hacemos la aplicación visible para que el usuario lo guardar directamente de la ventana de Word.SAVE() IF tlCierra *-.cDirDoc) . WITH THIS. con la posibilidad mediante un parámetro de cerrar el documento.  Abrir el archivo con la fuente de datos.Guardo el documento toDoc..MailMerge . Página 12 .  Mediante una Conexión de Datos de Office (ODC) ya existente. También establecemos la carpeta donde están los documentos de este ejemplo.  Ejecutar la combinación WITH toDoc.T. Para ello vamos a recurrir a dos grandes herramientas de Excel como lo son los gráficos y las tablas dinámicas. traer los datos de la tabla "Customers" de la base de datos "Northwind".ChangeFileOpenDirectory(THIS.Execute() ENDWITH Guardar la carta Para finalizar tenemos el método GuardarCarta() que guarda el documento principal.Cierro el documento toDoc.. para que Word por defecto la seleccione en la ventana de "Guardar.oWord . PROCEDURE GuardarCarta(toDoc.

es seleccionar el área de trabajo con datos de Visual FoxPro (estos pueden estar en una tabla. Si elegimos esta manera.chm" en la carpeta de la instalación de Office.. con los parámetros correspondientes. Parte de esta ayuda la podemos encontrar en el tema "Referencia Visual Basic de Microsoft Excel" en el archivo de ayuda "vbaxl10. debemos siempre examinar la ayuda disponible.Automatizando Office con Visual FoxPro Antes de comenzar a analizar el ejemplo en Visual FoxPro vamos a comprender algunos conceptos para poder hacer más fácil la automatización de Excel desde Visual FoxPro. En esta ayuda podemos conocer acerca de los objetos disponibles en Excel. SELECT 'MiCursor' COPY TO 'C:\Planilla1' TYPE XL5 EXPORT TO 'C:\Planilla2' TYPE XL5 Otra forma que disponemos es usando el método DataToClip() del objeto Application de Visual FoxPro ('VisualFoxPro. SELECT 'MiCursor' GO TOP _VFP. La variable del sistema _VFP hace referencia al objeto Application de la instancia actual. ¿Dónde está la ayuda? Para tener una idea mas clara acerca de todos los objetos de Excel.Application'). ó EXPORT TO . solo necesitamos tener activa la aplicación de Visual FoxPro. un cursor o una vista) y ejecutar las ordenes COPY TO .. También vamos a conocer distintas formas que disponemos para pasar los datos de Visual FoxPro a 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. esto siempre lo logramos con los archivos de ayuda.3) Página 13 ....DataToClip(. De esta manera copiamos un conjunto de registros como texto al "Portapapeles". Recordar que el tercer parámetro del método DataToClip() debemos configurarlo en 3 para que los campos se delimiten con tabulaciones.

xls') ENDWITH loExcel. loExcel Otra forma de pasar los datos de Visual FoxPro a Excel. THIS.Activate() .. es tener ambas aplicaciones activas y recorrer los datos de nuestra tabla y escribirlos directamente en una Hoja de Excel celda por celda. STORE . creamos una instancia de Excel desde Visual FoxPro. FINALLY para manejar el error OLE 1426.xls') loExcel. Esta opción es mucho más lenta que las anteriores. Página 14 . loExcel = CREATEOBJECT('Excel.T. DEFINE CLASS cExcel AS CUSTOM *-* Propiedades *-oExcel = .VALUE = FIELD(lnCol) ENDFOR lnFil = lnFil + 1 && Resto de las filas SCAN ALL FOR lnCol = 1 TO FCOUNT() loHoja. Los métodos de la clase cExcel El primer método que vamos a invocar de esta clase es CrearServidor() que establece la propiedad oExcel como una referencia a la instancia de Excel creada.Cells(1.NULL.SaveAs('C:\Planilla3.Application') Al igual que en la clase cWord que vimos anteriormente.Application') loLibro = loExcel.ActiveSheet() lnFil = 1 && Nombres de campos FOR lnCol = 1 TO FCOUNT() loHoja.NULL.VALUE = EVALUATE(FIELD(lnCol)) ENDFOR lnFil = lnFil + 1 ENDSCAN loLibro. TO loHoja.Workbooks.. . SELECT 'MiCursor' loExcel = CREATEOBJECT('Excel.oExcel = CREATEOBJECT('Excel.. loExcel Definición de la clase cExcel En esta clase definida por el usuario tendremos los métodos que nos permitirán crear y manejar los gráficos y las tablas dinámicas de Excel desde Visual FoxPro. creamos un nuevo Libro y pegamos los datos desde el Portapapeles con el método Paste().Visible = .Automatizando Office con Visual FoxPro Una vez que tenemos los datos en el Portapapeles.Application') loLibro = loExcel.. pero es útil cuando la hoja de Excel ya tiene un formato establecido o cuando queremos escribir fórmulas en la hoja de Excel.Cells(lnFil.Workbooks.Add() loHoja = loLibro.ActiveSheet.T. TO loLibro. loLibro.. este método tiene el mismo manejo de errores con el bloque TRY .lnCol).Visible = .Add() WITH loLibro .lnCol).Paste() ..NULL. CATCH . STORE .SaveAs('C:\Planilla4.

.CLOSE() ENDIF RETURN ENDPROC Generar un gráfico A partir de los resultados de una consulta a las tablas de la base de datos "Northwind". los ejes y las barras.NULL..cDirDoc + tcArchivo) loLibro = THIS. ENDIF *-.Cierro el Libro toLibro..Automatizando Office con Visual FoxPro Exportar los datos Para exportar nuestros datos de Visual FoxPro a Excel vamos a elegir la opción de COPY TO . Página 15 . generaremos un gráfico del tipo de columnas en 3 dimensiones (xl3DColumnStacked) como lo vemos en la Figura 9.cDirDoc + tcArchivo) ELSE *-.Retorno un objeto Workbook RETURN loLibro ENDPROC Guardar y cerrar el libro Con el método GuardarLibro() vamos a guardar el libro. Este método tiene un parámetro adicional que indica si se cierra el libro luego de guardarlo.Workbooks. tlCierra) *-.cDirDoc + tcCursor.Guardo el Libro toLibro.Si no existe el libro loLibro = .oExcel. Este método retorna un objeto WorkBook de Excel.. PROCEDURE AbrirLibro(tcArchivo) LOCAL loLibro AS 'Excel.SAVE() IF tlCierra *-. SELECT (tcCursor) COPY TO (lcArchivo) TYPE XL5 RETURN ENDPROC Abrir los libros exportados Con el método AbrirLibro() vamos a abrir el libro para comenzar con la automatización.OPEN(THIS.'XLS') IF FILE(THIS. que la ejecutamos en el método ExportarDatos().Opción COPY TO . 'XLS') *-. y daremos formato a algunos objetos del gráfico. como los títulos. PROCEDURE GuardarLibro(toLibro.Workbook' tcArchivo = FORCEEXT(tcArchivo. PROCEDURE ExportarDatos(tcCursor) LOCAL lcArchivo AS CHARACTER lcArchivo = FORCEEXT(THIS.

ADD WITH loGrafico Página 16 .Automatizando Office con Visual FoxPro Figura 9: Grafico de barras en 3 dimensiones El programa Grafico. loLibro AS OBJECT lo = NEWOBJECT('cExcel'.Genero cursor y exporto datos lo.VtaAnualEmpleado(1997. . RETURN El método GenerarGrafico() de la clase cExcel.T. .prg') *-.prg En este programa vamos a crear un objeto cExcel y ejecutaremos los métodos vistos anteriormente para la creación del gráfico.Grabo planilla y cierro lo.VISIBLE = .'cExcel.Chart'. loHoja AS 'Excel.GenerarGrafico(loLibro.Charts.Genero gráfico lo.Cierro el servidor lo.WorkSheet' loHoja = toLibro.COLUMNS.NULL.UsedRange.WINDOWSTATE = -4137 && xlMaximized lo.GuardarLibro(loLibro.AbrirLibro('VtaAnualEmpleado') *-.CerrarServidor() ELSE MESSAGEBOX('No se pudo instanciar el servidor'. es el que hace la tarea propiamente dicha.oExcel.oExcel. 'VtaAnualEmpleado') lo. 'Ventas Anuales por Empleado (AÑO 1997)') *--.Maximizo y hago visible lo. tcTitulo) LOCAL lcRango AS CHARACTER. *-.oExcel.ExportarDatos('VtaAnualEmpleado') IF lo.CrearServidor() *-. PROCEDURE GenerarGrafico(toLibro. oGrafico AS 'Excel.ActiveSheet lcRango = 'A1:' + CHR(loHoja.) *-. 16.Abro el libro copiado loLibro = lo. 'Error!') ENDIF lo = .ROWS.T.COUNT + 64) + .UsedRange. ALLTRIM(STR(loHoja.COUNT)) loGrafico = THIS. LOCAL lo AS OBJECT.

*-.Ancho separación barras . Figura 10: Diseño de la tabla dinámica Página 17 .1) . 'Ventas Anuales') && xlLocationAsNewSheet = 1 *-.T.RANGE(lcRango).RightAngleAxes = .Automatizando Office con Visual FoxPro *-.1) .T.SIZE = 14 .T.AutoScaling = .TEXT = 'Empleado' ENDWITH WITH . En nuestro ejemplo vamos a generar una tabla dinámica que nos muestra las Ventas Anuales agrupadas por País.NAME = 'Arial' .ChartGroups(1) *-.TEXT = tcTitulo WITH .ChartType = 55 && xl3DColumnStacked .Tipo. rango y localización . .T.HasLegend = . *-.AxisTitle.Bold = .Ejes WITH .GapWidth = 50 ENDWITH ENDWITH RETURN ENDPROC Generar una tabla dinámica Nuestro programa de ejemplo es "TablaDinamica. . ENDWITH *-.Titulo .ChartTitle.AxisTitle.HasTitle = .Location(1.Sin Leyendas . 2) . .Formato 3D .Grupo de gráfico WITH . Empleado y Tipo de Producto.T.F.ChartTitle.Axes(1.FONT .SetSourceData(loHoja.prg" que crea una instancia de la clase cExcel y ejecuta sus métodos para generar la tabla dinámica.T.HasTitle = . .TEXT = '$' ENDWITH *-.HasTitle = .Axes(2.

lcRango *--.Arrays con los datos de la tabla dinámica laPagina(1)='Anio' laFilas(1)='Pais' laFilas(2)='Empleado' laColumnas(1)='TipoProd' lcRango = 'A1:E1275' WITH THIS.##0.Genero cursor y exporto datos lo.WINDOWSTATE = -4137 && xlMaximized lo.COLUMNS. El diseño elegido lo observamos en la Figura 10. RETURN Para generar la tabla dinámica ejecutamos el método GenerarTablaDinamica() de la clase cExcel.prg Este es el código de nuestro programa: LOCAL lo AS OBJECT.NumberFormat = '$ #. loLibro AS OBJECT lo = NEWOBJECT('cExcel'.##0. Programa TablaDinamica.GenerarTablaDinamica(loLibro) *--.NULL. .SELECTION.SELECT *--. @laColumnas.'Suma de ventas') && xlDescending = 2 Página 18 .00' ENDWITH .GuardarLibro(loLibro.AddFields(@laFilas.Genero tabla dinámica lo.oExcel.T. PROCEDURE GenerarTablaDinamica(toLibro) LOCAL laPagina(1).SELECT . 16.ActiveSheet.'cExcel.Automatizando Office con Visual FoxPro Con anterioridad a la programación de los métodos debemos diseñar la forma de la tabla dinámica que deseamos generar. @laPagina) WITH .ActiveSheet.Cierro el servidor lo.00' . *-.VtaAnualPais('VtaAnualPais') lo. laColumnas(1).ORIENTATION = 4 && xlDataField .PivotTables('TablaDinamica') .PivotTableWizard(1.RANGE('A2').Cells. Este método nos genera la tabla dinámica (Figura 11) ordenada descendentemente por las Ventas por País. laFilas(2).AbrirLibro('VtaAnualPais') *-.Armo la Tabla dinámica WITH .PivotFields('Ventas') .Maximizo y hago visible lo.NumberFormat = '$ #.COLUMNS('E:E'). ''.AutoSort(2.SELECTION.Grabo planilla y cierro lo.Abro el libro copiado loLibro = lo.Llamo al generador de Tablas Dinámicas .PivotFields('Pais').VISIBLE = .oExcel *--.T.) *-. lcRango.Formato de los datos hoja principal .prg') *-.oExcel.CrearServidor() *-. 'Error!') ENDIF lo = .ExportarDatos('VtaAnualPais') IF lo.CerrarServidor() ELSE MESSAGEBOX('No se pudo instanciar el servidor'.SELECT . 'TablaDinamica') *--.AUTOFIT .

Cells. Figura 12: La ayuda de Outlook en el archivo "vbaol10.SELECT ENDWITH RETURN ENDPROC Figura 11: Tabla dinámica generada Otros métodos auxiliares En la clase cExcel también existen otros métodos. que todo lo podemos hacer por programa desde Visual FoxPro.SELECTION.SELECT .ActiveSheet. Como en temas anteriores. o sea.COLUMNS. Enviar y leer correo con Outlook El modelo de objetos de Outlook es muy rico y poderoso. siempre recurriremos a la ayuda.Automatizando Office con Visual FoxPro ENDWITH *--.AUTOFIT .NAME = 'Ventas Anuales' . Esta interfaz está disponible como un servidor de automatización. Estos cursores toman los datos de la base de datos "Northwind" que se encuentra en la carpeta "\Samples\Northwind" de la carpeta de la instalación original de Visual FoxPro.chm" Página 19 .RANGE('A2'). Estos métodos son VtaAnualPais() y VtaAnualEmpleado() utilizados para crear los cursores con los datos para exportar a Excel. solo válidos para este ejemplo.Formato de los datos hoja tabla dinámica . Allí podemos ver los distintos objetos de Outlook (Figura 12).

Versiones de Outlook Seguramente conocemos varias versiones de Outlook.GetNameSpace("MAPI") *-.ADD(lcDestinatario) loMailItem. pero solo Corporate Workgroup trabaja con la interfaz MAPI. .NULL.Logon(lcPerfil . solo daremos las principales características de cada uno. lcContrasenia) loMailItem = loOutlook.Creo objetoa Outlook y NameSpace loOutlook = CREATEOBJECT("Outlook." + LF_CR *-.  Outlook Express: No es Outlook. es crear un objeto Outlook. El objeto NameSpace proporciona entre otros.  Outlook 97 y 2000: Existen dos versiones.Subject = lcTema loMailItem.Datos del correo lcPerfil = "Prueba" lcContrasenia = "prueba" lcDestinatario = "luismaria@portalfox. Un breve ejemplo Una de las tareas más fácil de automatizar en Outlook es el envío de un correo. lcCuerpo AS CHARACTER LOCAL loOutlook AS "Outlook. Internet Mail Only (IMO) y Corporate Workgroup (C/W).NULL. lcDestinatario AS CHARACTER. .Body = lcCuerpo loMailItem.Automatizando Office con Visual FoxPro Lo primero que debemos hacer para automatizar Outlook. debemos crear un objeto "NameSpace" apropiado que actuará como entrada (en este ejemplo MAPI). loMailItem AS OBJECT #DEFINE LF_CR CHR(10)+CHR(13) *-.Recipients.Application". LOCAL lcPerfil AS CHARACTER.Ejecuto los métodos loNameSpace. incluyen los parches de seguridad de Microsoft.Logoff loNameSpace = . Página 20 ." + LF_CR lcCuerpo = lcCuerpo + "Saludos desde A Coruña. loNameSpace AS OBJECT. con el fin de evitar códigos maliciosos que toman los datos de nuestra libreta de direcciones y envían correo sin nuestro consentimiento. similar a como vimos anteriormente con las otras herramientas de Office. . es un programa completamente diferente y no es servidor de automatización. pero esto no lo logramos en forma directa.com" lcTema = "Prueba" lcCuerpo = "Prueba desde la Conferencia Visual FoxPro España 2003. Veremos un ejemplo de solamente unas pocas líneas.  Outlook XP: Combina las versiones Internet Mail y Corporate Workgroup. lcTema AS CHARACTER . lcContrasenia AS CHARACTER . loOutlook = .SEND loNameSpace. Ambas trabajan con Internet Mail. Problemas de seguridad Outlook XP y Outlook 2000 SP2. entre otras cosas. los métodos Logon y Logoff.Application") loNameSpace = loOutlook. debemos acceder al origen de los datos. Estos parches restringen. el acceso a la libreta de direcciones y el envío de correo mediante automatización. Una vez creado el objeto.CreateItem(0) loMailItem.

." ¿Y ahora que? Estas son algunas de las opciones disponemos nosotros para trabajar con estos parches de seguridad:  Mantener la versión de Office 2000 SR-1 y no actualizarla ni instalarle parches de seguridad..." Cuando intentamos acceder a la libreta de direcciones aparece el cuadro de dialogo el cual nos permitirá un acceso inmediato. ó 10 minutos que debemos seleccionar (Figuras 14). el administrador de Exchange. Existe para descarga una versión libre con fines de desarrollo.Application' Página 21 .com/redemption.Automatizando Office con Visual FoxPro Cuando intentamos enviar un correo desde Visual FoxPro.html. Figura 14: ". 2. puede disminuir las alertas o registrar algunas aplicaciones como seguras. llamada cOutlook con los distintos métodos para realizar el envío y la lectura de los correos.intentando enviar correo. Definición de la clase cOutlook En este ejemplo disponemos de una clase definida por el usuario.. Este "presionará" el botón "Si" antes de que el dialogo aparezca.. La definición de esta clase es la siguiente: DEFINE CLASS cOutlook AS CUSTOM *-. o de 1.  Si se tienen Outlook y Exchange instalados..dimastr.intentando tener acceso a direcciones. Este es un producto comercial con un valor de U$S 200 aproximadamente. que luego de 5 segundos habilita el botón "Si" (Figura 13).. con los peligros que esto significa.. se nos presenta el siguiente cuadro de dialogo.  Outlook Redemption: Es un objeto COM que se adapta fácilmente a la automatización y utiliza la MAPI extendida. En el mismo sitio existe un ejemplo para Visual FoxPro.com/mailmate/clickyes.express-soft.  Express ClickYes: Es un pequeño programa residente que se maneja mediante la API de Windows. 5. Esta DLL fue escrita por Dmitry Streblechenko (MS Outlook MVP) y esta disponible en http://www.Heredo la interfaz de _Application Events_10 IMPLEMENTS ApplicationEvents_10 IN 'Outlook. Este programa es gratis y esta disponible en http://www. Figura 13: ".

THIS. Solo pondremos código para interactuar ApplicationEvents_10_Quit(): WITH THIS . 48.oNameSpace = THIS. 'Error!' ) ENDIF ENDIF También en el método Init() llamamos a un formulario para el inicio de sesión: DO FORM Inicio WITH THISFORM.NULL.oOutlook.Propiedades oOutlook = .oOutlook = CREATEOBJECT('Outlook.oCorreo) MESSAGEBOX('No se pudo vincular a los eventos de Outllok'. En este método también creamos un objeto NameSpace que nos permitirá acceder a las carpetas especiales de Outlook. ENDWITH con el evento Quit de Outlook en el método El formulario de ejemplo En este ejemplo utilizaremos un formulario con un objeto PageFrame con dos Páginas.IniciarSesion()) MESSAGEBOX('Falló el inicio sesión'.Vinculo los eventos de Outlook a métodos del objeto oCorreo IF NOT EVENTHANDLER(THISFORM.oOutlook = . ENDIF Los métodos de la clase cOutlook En el inicio del formulario invocábamos al método CrearServidor() que establece una referencia a la instancia de Outlook en la propiedad oOutlook. 'Inicio de sesión') RETURN .. la sentencia IMPLEMENTS nos permitirá interactuar con los eventos de Outlook desde Visual FoxPro.NULL.F. oNameSpace = .Application') Igualmente como en las clases anteriores.oOutlook..NULL.oCorreo. 16. ..'cOutlook.Automatizando Office con Visual FoxPro *-. En el método Init() creamos una instancia de la clase cOutlook y vinculamos los eventos de Outlook: THISFORM.oCorreo.prg') IF THISFORM.oCorreo... . THISFORM. una para enviar correo y la otra para leer los correos desde la Bandeja de Entrada. este método tiene el manejo de errores con el bloque TRY .oCorreo = NEWOBJECT('cOutlook'.oCorreo TO llAceptar IF NOT (llAceptar AND THISFORM.GetNameSpace('MAPI') Página 22 .. Como vimos anteriormente en la definición de la clase cWord. CATCH . FINALLY..oNameSpace = .CrearServidor() *-.NULL. THIS.. .

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

Inbox loInbox = THIS. 64.UnRead) ENDWITH ENDFOR Página 24 .grdMensajes.SenderName. Cuerpo.SETFOCUS ELSE MESSAGEBOX('No existen mensajes para traer'.ADD(. Tema.Adjuntos lnLen = ALEN(.VALUE = 1.COUNT loMsg = . ENDIF ENDWITH RETURN llRet ENDPROC Leer los correos Para leer los correos de la bandeja de entrada invocamos el método LeerMensajes() de la clase cOutlook desde el método Click() del botón "Leer". . Recibido. .MAPIFolder'. . VALUES (.Items. NoLeido) .edtCuerpo. .ReceivedTime. tcAlias) LOCAL loInbox AS 'Outlook.oCorreo.aAdjuntos) FOR lnI = 1 TO lnLen IF NOT EMPTY(.REFRESH En el método LeerMensajes() creamos un objeto loInbox y traemos todos los mensajes.Automatizando Office con Visual FoxPro ENDFOR *-.F.aAdjuntos(lnI)) AND FILE(.PARENT. lnI AS INTEGER.GetDefaultFolder(6) *-.Recorro los mensajes FOR lnI = 1 TO . o solo los mensajes "No leídos" y recorremos uno a uno para cargarlos en un cursor que luego mostraremos en una Grilla y un Cuadro de Edición.Attachments.RESTRICT("[Unread] = True") ELSE loMensajes = loInbox.opgTipo.oNameSpace.ITEM(lnI) WITH loMsg INSERT INTO (tcAlias) .Body.Items' LOCAL loMsg AS OBJECT.SEND ELSE llRet = . (EnviadoPor.Items ENDIF IF VARTYPE(loMensajes) = 'O' WITH loMensajes IF . llRet AS Logical IF EMPTY(tcAlias) tcAlias = 'curMsg' ENDIF *-. ZAP IN curMsg IF THISFORM. PROCEDURE LeerMensajes(tlNoLeidos. loMensajes AS 'Outlook.LeerMensajes(THIS.aAdjuntos(lnI)) loMensaje. 'Aviso') ENDIF THIS.Mensajes del Inbox IF tlNoLeidos loMensajes = loInbox.Count > 0 *-.PARENT.aAdjuntos(lnI)) ENDIF ENDFOR llRet = loMensaje.PARENT. 'curMsg') GO TOP IN curMsg THIS.Subject.

Automatizando Office con Visual FoxPro llRet = . ENDIF ENDWITH ELSE llRet = . Las posibilidades son muchas y cada una depende de la solución que debemos implementar en nuestras aplicaciones..F.F.. Página 25 . ENDIF RETURN llRet ENDPROC Resumen En este documento vimos solo algunos ejemplos de automatización de Office. Solo es cuestión de adoptar alguna de las técnicas vistas y ponerse a trabajar. pueden ser manejadas desde Visual FoxPro. Recuerden que todo el poder que nos brindan las distintas herramientas de Office.T. ELSE llRet = .