Cómo automatizar incrustados documentos ActiveX de Office con C++

Nota: Microsoft Visual C++. NET, Microsoft Visual C++ .NET 2003, Microsoft Visual C++ 2005 y Microsoft Visual C++ 2008 admiten el modelo de código administrado que es proporcionado por el Microsoft.NET Framework y el modelo de código nativo Microsoft Windows no administrado. La información de este artículo sólo se aplica a código no administrado de Visual C++.

Resumen

Utilice a esta guía paso a paso para automatizar un documento incrustado de Microsoft Office. El siguiente procedimiento utiliza un contenedor MFC de VC ++ como un contenedor de documentos ActiveX de una hoja de cálculo de Excel activada. El código incluye métodos de ejemplo para adquirir un puntero de interfaz IDispatch al servidor del documento y muestra cómo automatizar una hoja de cálculo de Excel incrustada.

Utilizar aplicaciones de Office como servidores de documentos ActiveX

Un contenedor de documentos ActiveX puede contener un número de documentos de Office, pero puede mostrarse sólo un documento cada vez. Cuando se activa el documento de Office, el menú de la aplicación de servidor del documento de Office se combina en el menú del contenedor. Un contenedor de documentos ActiveX activa automáticamente el documento que se muestra. Esto varía de incrustación de documentos OLE convencional. Convencional de incrustación o vinculación requiere que el usuario final para activar el documento antes de que los menús se combinan.

Cuando se incrusta una hoja de cálculo "nuevo" en el contenedor se trata como un objeto ActiveX. Se requiere ninguna acción de usuario final para combinar el menú de Excel con el menú del contenedor.

Crear una aplicación de contenedor MFC que automatiza un documento ActiveX

Para generar la aplicación de ejemplo que automatiza una hoja de cálculo de Excel incrustada, siga estos pasos:
  1. Inicie Microsoft Visual Studio. NET. En el menú archivo, elija nuevo y, a continuación, haga clic en proyecto. En tipos de proyecto, haga clic en Proyectos de Visual C++y seleccione la plantilla de Aplicación MFC . El proyecto AutomateEmbednombre. Guarde el proyecto en la carpeta C:\...root.
  2. En el Asistente para aplicaciones MFC, siga estos pasos:
    1. Haga clic en El tipo de aplicación y, a continuación, seleccione Documento único.
    2. Haga clic en Compatibilidad con documentos compuestos y, a continuación, seleccione el contenedor.
    3. Comprobar contenedor de documentos activos.
    4. Haga clic en Finalizar para aceptar los valores predeterminados restantes.
  3. Agregar interfaces de la biblioteca de objetos de Excel. Para ello, siga estos pasos:
    1. En el menú proyecto , haga clic en Agregar clase.
    2. En la lista de plantillas, seleccione Clase MFC de TypeLiby, a continuación, haga clic en Abrir. Agregar clase de biblioteca de tipos aparece el Asistente para.
    3. En la lista de bibliotecas de tipos disponibles, busque
      Versión de Microsoft Excel biblioteca de objetos de, donde versión es 9.0 para Excel 2000 o 10.0 para Excel 2002.
    4. Agregue las siguientes interfaces:
      _Application
      _Workbook
      _Worksheet
      Intervalo
      Hojas de cálculo
      Haga clic en Finalizar.
  4. En el área de solución AutomateEmbed en el Explorador de soluciones, verá una vista de árbol que incluye lo siguiente:

    Archivos de código fuente
    Archivos de encabezado
    Archivos de recursos
    Expanda el nodo de Archivos de recursos y haga doble clic en AutomateEmbed.RC para abrirla.
  5. Haga doble clic en el menú para ver dos menús: IDR_CNTR_INPLACE y IDR_MAINFRAME.
  6. Haga doble clic en IDR_CNTR_INPLACE. Abre un ventana del Diseñador de menús gráfico, que muestra el menú archivo . Cerca de la parte inferior del archivo de menú es un objeto CommandBarButton en blanco que contiene la leyenda Escriba aquí. Escriba AutomateExcel como título.
  7. Haga CommandBarButton recién títulos y, a continuación, haga clic en Agregar controlador de eventos para ejecutar al Asistente para controlador de eventos. En el asistente, establezca los siguientes valores:
       Set this:                  To this:
    ---------------------------------------------------------

    Command Name ID_FILE_AUTOMATEEXCEL
    Message Type Command
    Function Handler Name OnFileAutomateExcel
    Class List CAutomateEmbedView


    La Descripción del controlador va a decir "Llama después de que se ha elegido el botón de comando o elemento de menú".
  8. Haga clic en Agregar y editar para insertar el esqueleto del controlador en el código para el archivo CAutomateEmbedView.cpp.
  9. En el Explorador de soluciones, haga doble clic en el AutomateEmbedView.cpp para abrir el archivo en la ventana de código.
  10. Escriba o pegue el código siguiente en la parte superior del archivo:
    // AutomateEmbedView.cpp : implementation of the CAutomateEmbedView class// 

    #include "stdafx.h"
    #include "AutomateEmbed.h"

    #include "AutomateEmbedDoc.h"
    #include "CntrItem.h"
    #include "AutomateEmbedView.h"

    #include "CWorkbook.h"
    #include "CWorksheet.h"
    #include "CWorksheets.h"
    #include "CRange.h"

    #ifdef _DEBUG
    #define new DEBUG_NEW
    #endif

    // CAutomateEmbedView

  11. Agregar una nueva función miembro público a CAutomateEmbedView en el archivo AutomateEmbedView.h:
    HRESULT GetDocIDispatch( LPDISPATCH* ppDisp );
  12. En la parte inferior del archivo AutomateEmbedView.cpp, reemplace el controlador de mensajes esqueleto para CAutomateEmbedView::OnFileAutomateExcel con el código siguiente:
    // CAutomateEmbedView message handlers
    void CAutomateEmbedView::OnFileAutomateExcel()
    {
    // Query for the IDispatch pointer for the embedded object.
    // In this case it is Excel worksheet.
    LPDISPATCH lpDisp;
    HRESULT hr = GetDocIDispatch(&lpDisp); // Your own new function.

    // If you got an IDispatch, then use it to Automate Excel
    if(SUCCEEDED(hr))
    {
    CWorkbook oBook;
    CWorksheets oSheets;
    CWorksheet oSheet;
    CRange oRange;

    // Set_Workbook oBook to use lpDisp, the IDispatch* of the
    // embedded/Embedded workbook.
    oBook.AttachDispatch(lpDisp);

    // Then, get the first worksheet in the workbook.
    oSheets = oBook.get_Worksheets();
    oSheet = oSheets.get_Item(COleVariant((long)1));

    // Get the Range object corresponding to Cell A1.
    oRange = oSheet.get_Range(COleVariant(TEXT("A1")), COleVariant(TEXT("A1")));

    // Fill the range with the string "Hello World".
    oRange.put_Value(COleVariant((long)DISP_E_PARAMNOTFOUND, VT_ERROR), COleVariant(TEXT("Hello World")));

    //NOTE: If you are automating Excel 2000 the Range.SetValue requires only one
    // argument. The first parameter in the Excel 2002 syntax in the line above is for the data type,
    // and is optional. It is not permitted by Excel 2000 or earlier versions of Excel.

    } // End if
    } // End of method

    /*****************************************************************************
    * *
    * GetDocIDispatch - This method determines if the document is embedded *
    * or linked, and acquires an IDispatch pointer to the embedded/linked *
    * document's server application for use in Automation. *
    * The document must be activated for this method to succeed. *
    * *
    * Parameters: ppDisp = The address of an LPDISPATCH to be filled with *
    * the IDispatch pointer of the embedded/linked document's server. *
    * *
    * Returns: S_OK if successful, otherwise an HRESULT reporting the error. *
    * *
    *****************************************************************************/
    HRESULT CAutomateEmbedView::GetDocIDispatch(LPDISPATCH* ppDisp)
    {
    //HRESULT hr = S_OK;
    HRESULT hr = E_UNEXPECTED; // If no document then return no ppDisp.
    IOleLink* lpLink = NULL;
    IMoniker* lpMoniker = NULL;
    IRunningObjectTable* lpROT = NULL;
    IUnknown* lpUnk = NULL;

    if(!m_pSelection)
    {
    return hr;
    }

    // First, try to get an IOleLink interface from the document.
    // If successful, this indicates that the document is linked as
    // opposed to embedded.
    hr = m_pSelection->m_lpObject->QueryInterface(IID_IOleLink, (void**)&lpLink);

    if(SUCCEEDED(hr))
    {
    // Get the moniker of the source document for this link.
    // You need this to find the ActiveX Document Server.
    hr = lpLink->GetSourceMoniker(&lpMoniker);

    if(SUCCEEDED(hr))
    {
    // For linked documents, search the Running Object Table
    // for the relevant server. Do this through the
    // IRunningObjectTable interfce, which you can get through
    // an API call.
    hr = GetRunningObjectTable(0,&lpROT);

    if(SUCCEEDED(hr))
    {
    // Search the Running Object Table for the ActiveX
    // Document Server of this document. You'll get back an
    // IUnknown pointer to the server.
    hr = lpROT->GetObject( lpMoniker, &lpUnk );

    if(SUCCEEDED(hr))
    {
    // Finally, get the IDispatch pointer from the
    // IUnknown pointer.
    hr = lpUnk->QueryInterface(IID_IDispatch, (void**)ppDisp);
    }
    }
    }
    }
    else
    {
    // If that fails, try for a direct IDispatch pointer. This
    // indicates that the document is embedded, not linked.
    hr = m_pSelection->m_lpObject->QueryInterface(IID_IDispatch, (void**)ppDisp);
    }
    // Clean up interface pointers you may have acquired along the way.
    if(lpLink)
    lpLink->Release();
    if(lpMoniker)
    lpMoniker->Release();
    if(lpROT)
    lpROT->Release();
    if(lpUnk)
    lpUnk->Release();
    return hr;
    }

  13. Compile y ejecute la aplicación. Si recibe errores de compilador, consulte la sección "Solucionar problemas".
  14. En el formulario del contenedor, haga clic en Editar y, a continuación, haga clic en Insertar objeto.
  15. En el cuadro de lista Insertar objeto , seleccione una nueva hoja de cálculo de Excel. El vacío la hoja de cálculo de Excel aparece en el contenedor y el menú de Excel se combina con el menú del contenedor.
  16. Desde el menú de archivo del contenedor, haga clic en AutomateExcel. La cadena "Hello World" aparece en la celda A1.
  17. En el menú archivo , haga clic en nuevo para borrar la hoja de cálculo. No guarde la hoja de cálculo.
  18. En el nuevo documento, insertar un libro de Excel existente (crear desde archivo).
  19. En el menú archivo , haga clic en AutomateExcel. "Hello World" aparece en la celda A1 de la hoja de cálculo.

Solución de problemas

  • Si agregar contenedores de clase para la biblioteca de objetos de Excel mediante la opción del fichero de la clase de TypeLib Asistente para agregar y examinar la biblioteca de objetos, puede recibir un mensaje de error. Para evitar este problema, escriba la ruta y el nombre completo de la biblioteca de objetos en lugar de buscar el archivo. Para obtener más información, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

    ERROR 311408 : 'Sólo lectura' advertencia al agregar una clase MFC desde una biblioteca de tipos

  • Si recibe el siguiente mensaje de error al generar la aplicación de ejemplo, cambie "DialogBox Variant" en CRange.h a "Variant _DialogBox":
    Advertencia C4003: No hay suficientes parámetros reales para la macro 'DialogBoxA'.
    Para obtener más información acerca de este mensaje de error, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:

    311407 error: Asistente para clases MFC no resuelve los conflictos de nombres entre las API de Windows y los métodos de interfaz COM

  • Si recibe un error de compilación en Excel.tlh al compilar con Visual C++ 2005 o en Visual C++ 2008:
    1. Ejecute "Buscar en los archivos" (CTRL + MAYÚS + F) y, a continuación, busque "#import." Comentario o eliminar todas las líneas en EXCEL. Biblioteca de importación del archivo EXE se ha importado al utilizar #import. Habrá aproximadamente cinco instancias en los archivos de cinco encabezado creados por el Asistente para la importación de biblioteca de tipos.
    2. Abra el archivo de origen de Stdafx.h. Después de cada # instrucción include, agregue las siguientes instrucciones de importación junto con el modificador auto_rename para importar la biblioteca de tipos de Excel y sus dependencias.
      // mso.dll#import "libid:{2df8d04c-5bfa-101b-bde5-00aa0044de52}"  auto_rename
      // vb6ext.olb
      #import "libid:{0002e157-0000-0000-c000-000000000046}" auto_rename
      // excel.exe
      #import "libid:{00020813-0000-0000-c000-000000000046}" auto_rename

Referencias

Para obtener más información, haga clic en el siguiente número de artículo para verlo en Microsoft Knowledge Base:

311546 cómo incrustar y automatizar una hoja de cálculo de Excel mediante MFC y Visual C++ 2005 o Visual C++ .NET

316207 cómo incrustar y automatizar un documento de Word utilizando .NET de C++ y MFC

Propiedades

Id. de artículo: 316587 - Última revisión: 17 ene. 2017 - Revisión: 1

Comentarios