Automatización de Office con Visual C++


Resumen


Este artículo responde a preguntas comunes sobre la automatización de Microsoft Office desde Visual C++.

Más información


Tabla de contenido

  1. ¿Qué es la automatización?
  2. Soy nuevo en la automatización, ¿Dónde puedo encontrar buenos recursos para obtener más información?
  3. ¿Hay varias formas de usar la automatización?
  4. ¿Qué es COM?
  5. ¿Cómo puedo adjuntar a la instancia en ejecución de una aplicación de Office?
  6. ¿Cómo puedo pasar parámetros opcionales?
  7. ¿Cómo puedo capturar los eventos expuestos por las aplicaciones de Office?
  8. Mi código de automatización es demasiado lento. ¿Cómo puedo acelerar el funcionamiento?
  9. ¿Qué significan estos valores de error enormes, como-2147352573 o 0x80030002?
  10. ¿Qué es una biblioteca de tipos?
  11. Mi código de automatización funciona con Microsoft Excel 95, pero falla con Microsoft Excel 97. ¿Por qué?
  12. ¿Por qué la aplicación que estoy automatizando permanece en la memoria cuando mi programa ha terminado?
  13. Sé qué quiero hacer como usuario de una aplicación de Microsoft Office, pero ¿cómo lo hago mediante programación con automatización?
  14. ¿Puedo automatizar una aplicación de Microsoft Office incrustada?
  15. ¿Cómo puedo obtener acceso a las propiedades de un documento en un documento de Microsoft Office?

Preguntas y respuestas

  1. ¿Qué es la automatización? La automatización (antes automatización OLE) es una tecnología que le permite aprovechar la funcionalidad de un programa existente e incorporarlo en sus propias aplicaciones. Por ejemplo, puede usar las funciones de revisión ortográfica y gramatical de Microsoft Word en su aplicación sin que Microsoft Word esté visible para los usuarios. Puede incluso usar todas las herramientas de análisis de datos, impresión y gráficos de Microsoft Excel. Esta tecnología puede simplificar y acelerar enormemente el desarrollo.
  2. Soy nuevo en la automatización, ¿Dónde puedo encontrar buenos recursos para obtener más información? El capítulo 24 de David Kruglinski "Inside Visual C++" (ISBN: 1-57231-565-2) proporciona una descripción general, así como algunos ejemplos excelentes. Además, Microsoft Knowledge base es una buena fuente de información. Este artículo es un buen comienzo y puede encontrar referencias más específicas en el siguiente artículo de Microsoft Knowledge Base:
    152023 Localizar recursos para estudiar la automatización OLE
    Si prefiere aprender a través del ejemplo, consulte el siguiente artículo en Microsoft Knowledge Base:
    179706 HOWTO usar MFC para automatizar Excel & crear/dar formato a un libro nuevo
  3. ¿Hay varias formas de usar la automatización? Hay tres formas básicas en las que puede usar automatización: MFC, #import y C/C++:
    • Con MFC, use Visual C++ ClassWizard para generar "clases contenedoras" de las bibliotecas de tipos de Microsoft Office. Estas clases, así como la de otras clases MFC, como COleVariant, COleSafeArray, COleException, simplifican las tareas de automatización. Normalmente, se recomienda usar este método en lugar de los demás y la mayoría de los ejemplos de Microsoft Knowledge Base usan MFC.
    • #import, una nueva directiva que estaba disponible en Visual C++ 5,0, crea punteros inteligentes VC + + "de una biblioteca de tipos especificada. Es muy eficaz pero, a menudo, no se recomienda por problemas de recuento de referencias que normalmente se producen cuando se usan con las aplicaciones de Microsoft Office.
    • La automatización de C/C++ es mucho más difícil, pero a veces es necesaria para evitar la sobrecarga con MFC, o problemas con #import. Básicamente, trabajas con API como CoCreateInstance () e interfaces COM, como IDispatch e IUnknown.
    Es importante tener en cuenta que existen pequeñas diferencias entre la automatización de C++ y la función C: se ha diseñado COM en relación con la clase de C++. Para obtener más información, consulte el siguiente artículo en Microsoft Knowledge base para obtener un ejemplo de C:
    181473 HOWTO: usar automatización OLE desde una aplicación C
  4. ¿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 dividir el código en objetos independientes. Piense en ello 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 con un objeto, como la inicialización, las notificaciones y la transferencia de datos, se producen a través de estas interfaces. COM también es un conjunto de servicios proporcionados por bibliotecas de vínculos dinámicos (dll) instaladas con el sistema operativo. La automatización usa muchos de esos servicios. Un ejemplo es el servicio de "cálculo de referencias", que empaqueta las llamadas de la aplicación cliente a las funciones miembro de las interfaces de la aplicación servidor y las pasa a la aplicación servidor, con sus argumentos. Aparentemente, las interfaces del servidor se exponen en el espacio de memoria del cliente, que no es el caso cuando el cliente es un archivo. exe que se está ejecutando en su propio espacio de proceso. El cálculo de referencias también obtiene los valores devueltos de los métodos del servidor en 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 diversas bibliotecas COM. Las fuentes de información sobre estas incluyen "Inside OLE-Second Edition" de Kraig Brockschmidt, ISBN 1-55615-843-2, "Inside COM" por Dale Rogerson-ISBN 1-57231-349-8 y "referencia del programador de automatización", ISBN 1-57231-584-9.
  5. ¿Cómo puedo adjuntar a la instancia en ejecución de una aplicación de Office? Usa la API GetActiveObject (). Los servidores de automatización se registran por sí mismos en la tabla ROT (tabla de objetos de ejecución) a través de la API RegisterActiveObject (). Los clientes de automatización pueden obtener acceso a la instancia de ejecución con 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 ejecutándose de la aplicación de Office que desea adjuntar, solo podrá adjuntar la primera instancia iniciada con la API GetActiveObject (). Teóricamente, puede iterar la tabla ROT para cada instancia individual, pero las aplicaciones de Office no se registran si otra instancia ya está en la tabla ROT porque el moniker para el propio siempre es el mismo (no se puede distinguir de todos modos). Esto significa que no puede adjuntar en ninguna instancia excepto en la primera. Sin embargo, dado que las aplicaciones de Office también registran sus documentos en la tabla ROT, puede adjuntar correctamente a otras instancias iterando la ROT en busca de un documento específico, adjuntarlo y, a continuación, obtener el objeto de la aplicación a partir de él. Hay algo de código en el siguiente artículo de Microsoft Knowledge base para iterar la tabla ROT y buscar un nombre de documento:
    190985 HOWTO: obtener IDispatch de un documento de Excel o Word desde un OCX
    No es necesario que haga esto para PowerPoint porque es una aplicación de instancia única; solo se puede ejecutar una instancia de él.
  6. ¿Cómo puedo pasar parámetros opcionales? Algunos métodos tienen parámetros "opcionales". En Visual Basic, puedes omitirlas al azar al llamar al método. Sin embargo, al llamar con Visual C++, tiene que pasar una variante especial cuyo campo. VT se VT_ERROR y el campo. SCODE está 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 lo que hace Visual Basic en segundo plano.
  7. ¿Cómo puedo capturar los eventos expuestos por las aplicaciones de Office? Básicamente, implementas la interfaz de eventos que deseas detectar (el "receptor") y configura una conexión de asesoría con la aplicación (el "origen"). En el siguiente artículo se proporcionan ejemplos paso a paso para Microsoft Word:
    183599 HOWTO: capturar eventos de la aplicación Microsoft Word97 con VC + +
    En general, para configurar la conexión de consulta, obtiene la IConnectionPointContainer del servidor y llama a FindConnectionPoint () con el IID de la interfaz de eventos. Esto le proporciona una interfaz IConnectionPoint y todo lo que queda es llamar a Advise () con una instancia de la interfaz de eventos. El servidor devolverá una llamada a través de esta interfaz cuando se produzcan estos eventos.
  8. Mi código de automatización es demasiado lento. ¿Cómo puedo acelerar el funcionamiento? Una causa común de la velocidad de los problemas con la automatización es la lectura repetida y la escritura de datos. Esto es típico para los clientes de automatización de Excel. Sin embargo, la mayoría de los usuarios no saben que estos datos se pueden escribir o leer a la vez con SAFEARRAY. Consulte los siguientes artículos de Microsoft Knowledge base para obtener más información e informativos ejemplos:
    186120 HOWTO: usar MFC para automatizar Excel y rellenar un rango con una matriz
    186122 HOWTO: usar MFC para automatizar Excel & obtener una matriz a partir de un rango
    179706 HOWTO: usar MFC para automatizar Excel y crear y dar formato a un libro nuevo
    Además, es importante destacar que el uso del portapapeles puede mejorar en ocasiones el rendimiento. Por ejemplo, puede copiar los datos en el portapapeles y, a continuación, usar la automatización para indicar al servidor que pegue. O viceversa; indique al servidor que se copie en el portapapeles y péguelo en la aplicación.
  9. ¿Qué significan estos valores de error enormes, como-2147352573 o 0x80030002? Estos valores se conocen como HRESULTs y se definen en Winerror. h. Los números son tan grandes porque el primer bit representa si se trata de un resultado de error. Puede usar la utilidad ErrLook. exe que se incluye con Visual C++ para traducir estos números a descripciones significativas. Si desea obtener una descripción de los errores mediante programación, puede usar la API FormatMessage (). Consulte los siguientes artículos de Microsoft Knowledge base para obtener más información y ejemplos sobre el uso de FormatMessage ():
    186063 INFORMACIÓN: traducción de errores de automatización para VB/VBA
    122957 EJEMPLO: herramientas de descodificación de código de error OLE Decode32 y Decode16
    Nota: Si está usando Visual C++ 6,0 y tiene una variable que contiene este valor en la ventana de depuración inspección, anexe ", HR" (sin las comillas) para que Visual c++ la traduzca por usted.
  10. ¿Qué es una biblioteca de tipos? Una biblioteca de tipos es similar a un archivo de encabezado de C/C++. Contiene las interfaces, los métodos y las propiedades que un servidor está publicando. Puede ver la biblioteca de tipos con el visor de objetos OLE/COM (OLEVIEW. exe) que viene con Visual C++. A continuación se muestra una lista de los nombres de archivo de la biblioteca de tipos de Microsoft Office 95, 97 y 2000:
           Office Application      | Type library       ------------------------+----------------       Word 95 and prior       | wb70en32.tlb       Excel 95 and prior      | xl5en32.olb       Powerpoint 95 and prior | Powerpoint.tlb       Access 95 and prior     | msaccess.tlb       Binder 95               | binder.tlb       Schedule+               | sp7en32.olb       Project                 | pj4en32.olb       Team Manager            | mstmgr1.olb       Word 97                 | msword8.olb       Excel 97                | excel8.olb       Powerpoint 97           | msppt8.olb       Access 97               | msacc8.olb       Binder 97               | msbdr8.olb       Graph 97                | graph8.olb       Outlook 97              | msoutl8.olb       Outlook 98              | msoutl85.olb       Word 2000               | msword9.olb       Excel 2000              | excel9.olb       Powerpoint 2000         | msppt9.olb       Access 2000             | msacc9.olb       Outlook 2000            | msoutl9.olb       Word 2002               | msword.olb       Excel 2002              | excel.exe       Powerpoint 2002         | msppt.olb       Access 2002             | msacc.olb       Outlook 2002            | msoutl.olb  
  1. Mi código de automatización funciona con Excel 95, pero falla 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 sola implementación de IDispatch. Esto significaba que a menudo puedes llamar a métodos diseñados 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 propiedad del objeto X desde un objeto Y separado, recibirá el error 0x80020003,-2147352573, "miembro no encontrado". Para evitar este error, debes asegurarte de que la interfaz IDispatch subyacente con la que haces llamadas sea semánticamente correcta. Para obtener más información, consulte los artículos siguientes de Microsoft Knowledge Base:
    172108 HOWTO: solución de problemas "miembro no encontrado", error 0x80020003
  2. La aplicación que estoy automatizando permanece en la memoria cuando mi programa ha terminado. ¿Qué pasa? Es probable que esto se deba a que ha olvidado publicar una interfaz adquirida y tendrá que realizar un seguimiento de la misma. A continuación se muestran algunas sugerencias generales y cosas que hay que buscar:
    • Si está usando #import, es muy probable que se esté ejecutando en uno de los errores de recuento de referencia asociados a la misma. A menudo, los errores se pueden solucionar, pero normalmente es preferible usar uno de los otros métodos de automatización. #import no funciona muy bien con las aplicaciones de Office, porque sus bibliotecas de tipos y su uso son bastante complejas. Además, los problemas de recuento de referencias son difíciles de localizar porque una gran cantidad de llamadas COM en el nivel de interfaz se realizan en segundo plano al usar #import.
    • Compruebe si está llamando a algún método, como Open o New, que devuelvan IDispatch * (LPDISPATCH) y omita el valor devuelto. Si es así, descartará esta interfaz devuelta y necesitará cambiar el código para que la suelte cuando ya no la necesite.
    • Comente gradualmente las secciones de su código hasta que el problema desaparezca y, a continuación, vuelva a agregar el problema con cuidado para rastrear dónde se inicia el problema.
    • Tenga en cuenta que algunas aplicaciones seguirán ejecutándose si el usuario ha "tocado" la aplicación. Si esto sucede mientras está automatizando la aplicación, probablemente la aplicación seguirá ejecutándose. Las aplicaciones de Office tienen una propiedad "UserControl" en el objeto de la aplicación que se puede leer y escribir para cambiar este comportamiento.
    • Además, algunas aplicaciones decidirán seguir funcionando si se ha producido suficiente acción de la interfaz de usuario. Si está intentando cerrar la aplicación, llame a su método Quit () en el objeto de la aplicación. Word se cerrará independientemente de su cuenta de referencia cuando se llama a QUIT. Este es un comportamiento COM esperado. Sin embargo, Excel solo se ocultará correctamente, pero seguirá ejecutándose hasta que se publiquen todas las interfaces pendientes. En general, debe liberar todas las referencias pendientes y llamar a Quit () Si desea que la aplicación se cierre.
  3. Sé qué quiero hacer como usuario de una aplicación de Office, pero ¿cómo lo hago mediante programación a través de automatización? Lo que le interesa son los objetos, los métodos y las propiedades que 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 desee hacer como usuario, es usar la grabadora de macros. Simplemente elija la macro \ ' grabar nueva macro ' en el menú herramientas, ejecute la tarea que le interesa y, a continuación, elija macro \ ' Detener grabación '. Una vez que haya terminado de grabar, elija Macro\Macros en el menú herramientas, seleccione la macro que grabó y, a continuación, haga clic en Editar. Esto le llevará al código de VBA generado que llevará a cabo la tarea que grabó. Tenga en cuenta que la macro grabada no será el mejor código posible en la mayoría de los casos, pero sí muy bien para un ejemplo rápido.
  4. ¿Puedo automatizar una aplicación de Office insertada? Realmente. El truco está recibiendo el puntero IDispatch: esto se indica en la nota técnica de Visual C++ 39 (TN039). Consulte el siguiente artículo de Microsoft Knowledge base para obtener un ejemplo paso a paso:
    184663 HOWTO: incrustar y automatizar una hoja de cálculo de Microsoft Excel con MFC
  5. ¿Cómo puedo obtener acceso a las propiedades de un documento en un documento de Office? Las propiedades del documento son accesibles a través de automatización o directamente a través de IPropertyStorage. Los siguientes artículos de Microsoft Knowledge Base muestran cada método:
    179494 HOWTO: usar la automatización para recuperar propiedades de documento integradas
    186898 HOWTO: leer propiedades de documentos compuestos directamente con VC + +