Resumen
Este artículo responde preguntas comunes sobre automatización a Microsoft Office desde Visual C++.
Más información
Tabla de contenido
-
¿Qué es la automatización?
-
Soy nuevo en Automatización, ¿dónde puedo encontrar buenos recursos para obtener más información?
-
¿Hay diferentes maneras de usar la automatización?
-
¿Qué es COM?
-
Cómo adjuntar a la instancia en ejecución de una aplicación de Office?
-
Cómo pasar parámetros opcionales?
-
Cómo detectar eventos expuestos por las aplicaciones de Office?
-
Mi código de automatización es demasiado lento. ¿Cómo puedo acelerar las cosas?
-
¿Qué significan estos enormes valores de error, como -2147352573 o 0x80030002?
-
¿Qué es una biblioteca de tipos?
-
Mi código de automatización funcionaba con Microsoft Excel 95, pero fallaba con Microsoft Excel 97. ¿Por qué?
-
¿Por qué la aplicación que estoy automatizando permanece en la memoria después de que mi programa haya terminado?
-
Sé lo que quiero hacer como usuario de la aplicación de Microsoft Office, pero ¿cómo puedo hacerlo mediante programación con la automatización?
-
¿Puedo automatizar una aplicación de Microsoft Office incrustada?
-
Cómo obtener acceso a las propiedades de mi documento en un documento de Microsoft Office?
Preguntas y respuestas
-
¿Qué es la automatización?
La automatización (anteriormente automatización OLE) es una tecnología que le permite aprovechar las ventajas de la funcionalidad de un programa existente e incorporarla a sus propias aplicaciones. Por ejemplo, puede usar las funciones de revisión ortográfica y gramatical de Microsoft Word en la aplicación sin que los usuarios puedan ver Microsoft Word. Incluso puede usar todas las herramientas de gráficos, impresión y análisis de datos de Microsoft Excel. Esta tecnología puede simplificar y acelerar su desarrollo. -
Soy nuevo en Automatización, ¿dónde puedo encontrar buenos recursos para obtener más información? El capítulo 24 de "Inside Visual C++" de David Kruglinski (ISBN:1-57231-565-2) ofrece una visión general, así como algunos ejemplos excelentes. Además, Microsoft Knowledge Base es una buena fuente de información.
Si prefiere aprender por ejemplo, consulte el siguiente artículo en Microsoft Knowledge Base:179706 USAR MFC para automatizar Excel & Crear o dar formato a un libro nuevo
-
¿Hay diferentes maneras de usar la automatización?
Hay tres formas básicas de usar automatización: MFC, #import y C/C++:-
Con MFC, use el ClassWizard de Visual C++ para generar "clases contenedoras" desde las bibliotecas de tipos de Microsoft Office. Estas clases, así como otras clases MFC, como COleVariant, COleSafeArray, COleException, simplifican las tareas de automatización. Este método se recomienda normalmente sobre los demás y la mayoría de los ejemplos de Microsoft Knowledge Base usan MFC.
-
#import, una nueva directiva que pasó a estar disponible con Visual C++ 5.0, crea VC++ "punteros inteligentes" a partir de una biblioteca de tipos especificada. Es muy eficaz, pero a menudo no se recomienda debido a los problemas de recuento de referencias que suelen producirse cuando se usa con las aplicaciones de Microsoft Office.
-
La automatización de C/C++ es mucho más difícil, pero a veces es necesario evitar la sobrecarga con MFC o problemas con #import. Básicamente, trabaja con API como CoCreateInstance() y interfaces COM como IDispatch e IUnknown.
Es importante tener en cuenta que hay algunas ligeras diferencias entre la automatización de C++ en comparación con C sencilla, porque COM fue diseñado alrededor de la clase de C++.
-
-
¿Qué es COM?
La automatización se basa en el modelo de objetos componentes (COM). COM es una arquitectura de software estándar basada en interfaces y diseñada para tener código separado en objetos autocontenidos. Considéralo como una extensión del paradigma de programación orientada a objetos (OOP), pero aplicable a aplicaciones independientes. Cada objeto expone un conjunto de interfaces y todas las comunicaciones a un objeto, como inicialización, notificaciones y transferencia de datos, se realiza a través de estas interfaces. COM es también un conjunto de servicios proporcionados por bibliotecas de vínculo dinámico (DLL) instaladas con el sistema operativo. La automatización usa muchos de estos servicios. Un ejemplo es el servicio "Marshalling", que empaqueta las llamadas de la aplicación cliente a las funciones miembro de las interfaces de la aplicación de servidor y las pasa, con sus argumentos, a la aplicación de servidor. Parece que las interfaces del servidor se exponen en el espacio de memoria del cliente, que no es el caso cuando el cliente es un .exe que se ejecuta en su propio espacio de proceso. Marshalling también devuelve los valores devueltos de los métodos del servidor a través de los límites del proceso y de forma segura en las manos de la llamada del cliente. Hay muchos otros servicios esenciales para la automatización que proporcionan las distintas bibliotecas COM. Las fuentes de información sobre estos incluyen "Inside Ole - Second Edition" de Kraig Brockschmidt, ISBN 1-55615-843-2, "Inside COM" de Dale Rogerson - ISBN 1-57231-349-8, y "Automation Programmer's Reference", ISBN 1-57231-584-9. -
Cómo adjuntar a la instancia en ejecución de una aplicación de Office?
Use la API GetActiveObject(). Los servidores de automatización se registran en el ROT (Tabla de objetos en ejecución), a través de la API RegisterActiveObject(). Los clientes de automatización pueden obtener en la instancia en ejecución código como:// Translate server ProgID into a CLSID. ClsidFromProgID // gets this information from the registry. CLSID clsid; CLSIDFromProgID(L"Excel.Application", &clsid); // Get an interface to the running instance, if any.. IUnknown *pUnk; HRESULT hr = GetActiveObject(clsid, NULL, (IUnknown**)&pUnk); ASSERT(!FAILED(hr)); // Get IDispatch interface for Automation... IDispatch *pDisp; hr = pUnk->QueryInterface(IID_IDispatch, (void **)&pDisp); ASSERT(!FAILED(hr)); // Release the no-longer-needed IUnknown... pUnk->Release();
NOTA: Si hay varias instancias en ejecución de la aplicación de Office que desea adjuntar, solo podrá adjuntar a la primera instancia que se inició mediante la API GetActiveObject().
Teóricamente, puede iterar el ROT para cada instancia individual, pero las aplicaciones de Office no se registran ellos mismos si otra instancia ya está en el ROT porque el nombre propio es siempre el mismo (no se puede distinguir de todos modos). Esto significa que no puede adjuntar a ninguna instancia excepto a la primera. Sin embargo, como las aplicaciones de Office también registran sus documentos en el ROT, puede adjuntarlos correctamente a otras instancias si itera el ROT buscando un documento específico, adjúntelo y, a continuación, obtiene el objeto Application de él. No tendrá que hacer esto para PowerPoint, porque es una aplicación de instancia única; solo puedes tener una instancia de ella ejecutándose. -
Cómo pasar parámetros opcionales?
Algunos métodos tienen parámetros "opcionales". En Visual Basic, puede omitirlos casualmente al llamar al método. Sin embargo, al llamar con Visual C++ tiene que pasar un variant especial cuyo campo .vt es VT_ERROR y el campo .scode es DISP_E_PARAMNOTFOUND. Es decir:// VARIANT used in place of optional-parameters. VARIANT varOpt; varOpt.vt = VT_ERROR; varOpt.scode = DISP_E_PARAMNOTFOUND;
Esto es realmente lo que Visual Basic está haciendo en segundo plano.
-
Cómo detectar eventos expuestos por las aplicaciones de Office?
Básicamente, implementa la interfaz de eventos que desea capturar (el "receptor") y configurar una conexión de aviso con la aplicación (el "origen"). En general, para configurar la conexión de aviso, obtendrá el servidor IConnectionPointContainer y llamará a FindConnectionPoint() con el IID de la interfaz del evento. Esto le proporciona una IConnectionPoint interfaz y todo lo que queda es llamar a Advise() con una instancia de su interfaz de evento. El servidor volverá a llamar a través de esta interfaz cuando se produzcan estos eventos. -
Mi código de automatización es demasiado lento. ¿Cómo puedo acelerar las cosas?
Una causa habitual de los problemas de velocidad con la automatización es la lectura y escritura repetitiva de datos. Esto es típico de los clientes de automatización de Excel. Sin embargo, la mayoría de las personas no son conscientes de que estos datos normalmente se pueden escribir o leer a la vez con SAFEARRAY. Consulte el siguiente artículo de Microsoft Knowledge Base para obtener más información y ejemplos informativos:179706 HOWTO: Usar MFC para automatizar Excel y crear o dar formato a un nuevo libro Además, es importante señalar que el uso del Portapapeles a veces puede mejorar el rendimiento. Por ejemplo, puede copiar los datos en el Portapapeles y, después, usar la automatización para indicar al servidor que lo pegue. O viceversa; indica al servidor que copie al portapapeles y péguelo en la aplicación.
-
¿Qué significan estos enormes valores de error, como -2147352573 o 0x80030002?
Estos valores se conocen como HRESULT y se definen en winerror.h. Los números son tan grandes porque el primer bit representa si es o no un resultado de error. Puede usar la utilidad ErrLook.Exe que viene con Visual C++ para traducir estos números en descripciones significativas. Si desea obtener mediante programación una descripción de los errores, puede usar la API FormatMessage().NOTA: Si usa Visual C++ 6.0 y tiene una variable que contiene este valor en la ventana del reloj de depuración, anexe ", h" (sin las comillas) para que Visual C++ lo traduzca por usted.
-
¿Qué es una biblioteca de tipos?
Una biblioteca de tipos es similar a un archivo de encabezado de C/C++. Contiene las interfaces, métodos y propiedades que un servidor está publicando. Puede ver la biblioteca de tipos con el Visor de objetos OLE/COM (Oleview.exe) que se incluye con Visual C++. Aquí tiene una lista de los nombres de archivo de biblioteca de tipos para Microsoft Office 95, 97 y 2000: | de aplicaciones de Office Biblioteca de tipos ------------------------+---------------- Word 95 y | anteriores wb70en32.tlb Excel 95 y | anteriores xl5en32.olb PowerPoint 95 y | anteriores Powerpoint.tlb Access 95 y | anteriores msaccess.tlb Carpeta 95 | binder.tlb Programación+ | sp7en32.olb | de Project pj4en32.olb | administrador del equipo mstmgr1.olb Word 97 | msword8.olb | de Excel 97 excel8.olb | de PowerPoint 97 msppt8.olb | de Access 97 msacc8.olb Carpeta 97 | msbdr8.olb Gráfico 97 | graph8.olb | de Outlook 97 msoutl8.olb | de Outlook 98 msoutl85.olb Word 2000 | msword9.olb Excel 2000 | excel9.olb | de PowerPoint 2000 msppt9.olb | de Access 2000 msacc9.olb | de Outlook 2000 msoutl9.olb Word 2002 | msword.olb | de Excel 2002 excel.exe PowerPoint 2002 | msppt.olb | de Access 2002 msacc.olb | de Outlook 2002 msoutl.olb
-
Mi código de automatización funcionaba con Excel 95, pero fallaba con Excel 97. ¿Qué pasa?
El modelo de objetos de Excel realizó un cambio significativo de la versión 95 a la 97. Excel 95 implementó todos sus métodos y propiedades en una única implementación de IDispatch. Esto significaba que a menudo se podía llamar a métodos para el objeto X, desde el objeto Y. Esto no era un buen diseño, por lo que en Office 97, cada objeto tiene su propia implementación de Idispatch independiente. Esto significa que, si solicita un método o una propiedad del objeto X desde un objeto independiente Y, obtendrá el 0x80020003 de error -2147352573, "Miembro no encontrado". Para evitar este error, debe asegurarse de que la interfaz IDispatch subyacente desde la que está realizando llamadas sea la semánticamente correcta. -
La aplicación que estoy automatizando permanece en la memoria una vez que mi programa ha terminado. ¿Qué pasa?
Lo más probable es que esto se deba a que has olvidado liberar una interfaz adquirida y tendrás que localizarla. Estas son algunas sugerencias generales y aspectos que debe buscar:-
Si usas #import, es muy probable que te encuentres con uno de los errores de recuento de referencias asociados a él. A menudo se pueden solucionar los errores, pero normalmente se prefiere usar uno de los otros métodos de automatización. #import no funciona muy bien con las aplicaciones de Office, ya que sus bibliotecas de tipos y su uso son bastante complejos. Además, estos problemas de recuento de referencias son difíciles de localizar porque muchas de las llamadas COM de nivel de interfaz están en segundo plano al usar #import.
-
Compruebe si está llamando a métodos, como Open o New, que devuelven un IDispatch * (LPDISPATCH) e ignorando el valor devuelto. Si lo estás haciendo, estás abandonando esta interfaz devuelta y tendrás que cambiar el código para liberarlo cuando ya no sea necesario.
-
Comenta gradualmente las secciones del código hasta que desaparezca el problema y, a continuación, agrégalo de nuevo con juicioso para localizar dónde comienza el problema.
-
Tenga en cuenta que algunas aplicaciones seguirán ejecutándose si el usuario ha "tocado" la aplicación. Si esto ocurre mientras está automatizando, es probable que la aplicación siga ejecutándose posteriormente. Las aplicaciones de Office tienen una propiedad "UserControl" en el objeto Application que puede leer y escribir para cambiar este comportamiento.
-
Además, algunas aplicaciones deciden seguir ejecutándose si se ha producido suficiente "acción" de la interfaz de usuario. Si su intención es que la aplicación salga, llame a su método Quit() en el objeto Application. Word se cerrará independientemente de su número de referencias cuando se llame a Salir. Este comportamiento COM no es el esperado. Excel, sin embargo, se ocultará correctamente, pero seguirá funcionando hasta que se publiquen todas las interfaces pendientes. En general, debería liberar todas las referencias pendientes y llamar solo a Quit() si su intención es que la aplicación se cierre.
-
-
Sé lo que quiero hacer como usuario de una aplicación de Office, pero ¿cómo puedo hacerlo mediante programación a través de la automatización?
Lo que le interesa es qué objetos, métodos y propiedades necesita usar. La mejor manera de aprender a navegar por los modelos de objetos de Word, Excel y PowerPoint, en función de lo que quiera hacer como usuario, es usar la Grabadora de macros. Simplemente elija Macro\'Grabar nueva macro' desde el menú Herramientas, ejecute la tarea que le interesa, luego elija Macro\'Detener grabación.' Cuando termine de grabar, elija Macro\Macros en el menú Herramientas, seleccione la macro que haya grabado y, a continuación, haga clic en Editar. Esto le llevará al código de VBA generado que realizará la tarea que registró. Tenga en cuenta que la macro grabada no será el mejor código posible en la mayoría de los casos, pero es muy útil para un ejemplo rápido. -
¿Puedo automatizar una aplicación de Office incrustada?
Absolutamente. El truco es obtener el puntero IDispatch: esto se da en la nota técnica 39 de Visual C++ (TN039). -
Cómo obtener acceso a las propiedades de mi documento en un documento de Office?
Las propiedades del documento son accesibles a través de Automation o directamente a través de IPropertyStorage.