Cómo generar un complemento (XLL) para Excel con Visual C++

Seleccione idioma Seleccione idioma
Id. de artículo: 178474 - Ver los productos a los que se aplica este artículo
Expandir todo | Contraer todo

En esta página

Resumen

Un XLL es un complemento para Microsoft Excel que se puede generar con cualquier compilador que admite la creación de DLL (bibliotecas de vínculos dinámicos). En este artículo está diseñado para empezar a generar los XLL con Microsoft Visual C++. Siga los pasos descritos en este artículo, debe tener alguna experiencia generar archivos DLL y debe tener el Kit del programador de Microsoft Excel 97, que contiene los archivos de encabezado y biblioteca necesarios para generar un XLL.

Más información

Pasos para crear un XLL

  1. Cree un nuevo proyecto de MFC AppWizard (.dll) denominado Anewxll.
  2. Copie el xlcall.h, Framewrk.h, Framewrk.c y Xlcall32.lib del Kit del programador de Microsoft Excel 97 al su directorio de proyecto.
  3. Cambie el nombre Framewrk.c Framewrk.cpp.
  4. Agregar Framewrk.cpp a los archivos de origen del proyecto.
  5. Agregue el siguiente # include línea hasta la parte superior de Framewrk.cpp para evitar errores del compilador sobre encabezados precompilados:
    
          #include "stdafx.h"
    					
  6. Cambie la línea siguiente en Framewrk.cpp:
          #include "..\..\include\xlcall.h"
    					
    a:
          #include "xlcall.h"
    					
  7. Haga clic en configuración en el menú proyecto. Haga clic en la ficha de vínculo y agregar Xlcall32.lib al objeto o cuadro de edición módulos de biblioteca.
  8. Agregue las siguientes instrucciones a la parte superior de Anewxll.cpp # include:
          #include "xlcall.h"
          #include "framewrk.h"
    					
    Nota: el proyecto es el programa de instalación ahora correctamente y debe compilar, sin embargo, todavía no has agregado compatibilidad XLL. Los pasos restantes proporcionan algún código de ejemplo que puede agregar a los XLL para comenzar.

  9. Anexe el código siguiente a Anewxll.cpp: código de ejemplo-----------
          //================================================================
          // Commonly used global variables
          int err;
          char buf[8192];
          char txt[8192];
    
          // Function registering table
          int nFuncs;
    
          // proc, type_text, function_text, arg, macro_type, category,
          // shortcut_text, help_topic, function_help
          static LPSTR func[][9] = {
          {" MyFunc", " JJJ", " MyFunc", " ", " 1", " MyCat", " ", " ", " "},
          {" MyMotd", " I", " MyMotd", " ", " 1", " MyCat", " ", " ", " "},
          {0,0,0,0, 0, 0, 0}
          };
    
          // Menu table
          int nMenuItems;
    
          static LPSTR menu[][5] = {
          {" &MyMenu", " ", " ", " Joe's Xll menu!!!", " "},
          {" M.O.T.D."," MyMotd", " ", " Message of the Day!", " "},
          {0, 0, 0, 0, 0}
          };
    
          // Initialization routine
          BOOL __stdcall xlAutoOpen(void) {
             AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
    
             // DEBUG output to indicate when called
             AfxMessageBox("xlAutoOpen() called!", MB_SETFOREGROUND);
    
             int i, j;
    
             // Get XLL file name
             static XLOPER xDll;
             Excel(xlGetName, &xDll, 0);
    
             // Prefix strengths with their length & count items
             // Note the framework's TempStr() function prefixes the
             // lengths anyway, but this is for other code that might
             // use the arrays
             for(nFuncs=0;     func[nFuncs][0];     nFuncs++) {
                 for(i=0; i<9; i++) {
                     func[nFuncs][i][0]     = (BYTE) strlen(func[nFuncs][i]+1);
                 }
    
             }
    
             for(nMenuItems=0; menu[nMenuItems][0]; nMenuItems++) {
                 for(i=0; i<5; i++) {
                 menu[nMenuItems][i][0] = (BYTE) strlen(menu[nMenuItems][i]+1);
                 }
             }
    
             // Loop through the function list, and register the functions
             for(i=0; i<nFuncs; i++) {
    
                // Register a function
                err = Excel(xlfRegister, 0, 9, (LPXLOPER)&xDll,
                   (LPXLOPER)TempStr(func[i][0]),
                   (LPXLOPER)TempStr(func[i][1]),
                   (LPXLOPER)TempStr(func[i][2]),
                   (LPXLOPER)TempStr(func[i][3]),
                   (LPXLOPER)TempStr(func[i][4]),
                   (LPXLOPER)TempStr(func[i][5]),
                   (LPXLOPER)TempStr(func[i][6]),
                   (LPXLOPER)TempStr(func[i][7]),
                   (LPXLOPER)TempStr(func[i][8])
                   );
    
                if(err != xlretSuccess) {
                 sprintf(buf, "xlfRegister for function %d, err = %d", i, err);
                 AfxMessageBox(buf, MB_SETFOREGROUND);
                }
             }
    
             // Free XLL file name from the xlGetName call made earlier
             Excel(xlFree, 0, 1, (LPXLOPER)&xDll);
    
             // Menu support section
             static XLOPER xMenu;
             static XLOPER xMenuList[10*5];
             ASSERT(nMenuItems< 10);
    
             // Build menu
             xMenu.xltype            = xltypeMulti;
             xMenu.val.array.lparray = &xMenuList[0];
             xMenu.val.array.rows    = nMenuItems;
             xMenu.val.array.columns = 5;
    
             for(i=0; i<nMenuItems; i++) {
                 for(j=0; j<5; j++) {
                     xMenuList[j+i*5].xltype  = xltypeStr;
                     xMenuList[j+i*5].val.str = menu[i][j];
                 }
             }
    
             // Add menu
            Excel(xlfAddMenu,0,3,TempNum(1),(LPXLOPER)&xMenu,TempStr(" Help"));
    
             // Finished
             return 1;
          }
    
          // Cleanup routine
          BOOL __stdcall xlAutoClose(void) {
             ::MessageBox(NULL, "xlAutoClose()", "Debug", MB_SETFOREGROUND );
    
             // Delete menu
             Excel(xlfDeleteMenu, 0, 2, TempNum(1), TempStr(" MyMenu"));
    
             return 1;
          }
    
          // Support for descriptive information about the add-in(s)
          // You can add a new customized title for the user, but
          // unfortunately, only an add-in written in Microsoft Visual Basic
          // can add a description string.
          LPXLOPER _stdcall xlAddInManagerInfo(LPXLOPER xAction) {
             static XLOPER xInfo, xIntAction;
    
             // Find out what action must be taken
             Excel(xlCoerce, &xIntAction, 2, xAction, TempInt(xltypeInt));
    
             // DEBUG output to indicate when called
             sprintf(buf, "xlAddInManagerInfo(%ld)", (long)xIntAction.val.w);
             ::MessageBox(NULL, "xlAddInManagerInfo()", "Debug",
                 MB_SETFOREGROUND );
    
             // Set title if asked
             if(xIntAction.val.w == 1) {
                 xInfo.xltype = xltypeStr;
                 xInfo.val.str = " My Add-in!!!!";
                 xInfo.val.str[0] = (char)strlen(&xInfo.val.str[1]);
             }
             else {
                 xInfo.xltype = xltypeErr;
                 xInfo.val.err = xlerrValue;
             }
    
             return (LPXLOPER)&xInfo;
          }
    
            short __stdcall MyMotd(void) {
             char *name[] = {
                "Rebekah",
                "Brent",
                "John",
                "Joseph",
                "Robert",
                "Sara",
                0
             };
             char *quote[] = {
                "An apple a day, keeps the doctor away!",
                "Carpe Diem: Seize the Day!",
                "What you dare to dream, dare to do!",
                "I think, therefore I am.",
                "A place for everything, and everything in its place.",
                "Home is where the heart is.",
    
                0
             };
    
             int nNames, nQuotes;
    
             for(nNames=0; name[nNames]; nNames++);
             for(nQuotes=0; quote[nQuotes]; nQuotes++);
    
             sprintf(buf, "%s says '%s'", name[rand()%nNames],
                quote[rand()%nQuotes]);
             ::MessageBox(NULL, buf, "XLL MOTD", MB_SETFOREGROUND );
    
             return 0;
          }
    
          // Example function that returns the product of its two parameters
          long __stdcall MyFunc(long parm1, long parm2) {
           sprintf(buf, "You sent %ld and %ld to MyFunc()!", parm1, parm2);
           ::MessageBox(NULL, buf, "MyFunc() in Anewxll!!!", MB_SETFOREGROUND);
    
           return parm1 * parm2;
          }
          //=================================================================
    					
  10. Agregue las líneas siguientes al final del archivo Anewxll.def:
          xlAutoOpen
          xlAutoClose
          xlAddInManagerInfo
          MyMotd
          MyFunc
    					
  11. Ahora puede compilar el proyecto para generar una DLL denominada Anewxll.dll. Una vez compilada la DLL, cambiarle el nombre a Anewxll.xll.

Con el complemento de Microsoft Excel

  1. Inicie un libro nuevo en Microsoft Excel.
  2. Haga clic en complementos en el menú Herramientas. Vaya a agregar Anewxll.xll y haga clic en Aceptar. Observe que, cuando hace clic en Aceptar en el cuadro de diálogo Complementos, ejecuta la función xlAutoOpen.
  3. Haga clic en M.O.T.D en el menú MyMenu. Cuando se hace clic en el elemento de menú, la función MyMotd se ejecutará para mostrar un cuadro de mensaje con una oferta, como "Rebekah indica 'Un Apple un día, mantiene al doctor fuera'!".
  4. En una celda, agregue la siguiente fórmula:
    =MYFUNC(2,6)
    					
    MYFUNC devuelve 12, el producto de 2 y 6.

  5. Haga clic en complementos en el menú Herramientas. Desactive la casilla de verificación complemento y haga clic en Aceptar. Observe que, al hacer clic en Aceptar en el cuadro de diálogo Complementos, ejecuta la función xlAutoClose.

Notas adicionales

Si está utilizando Microsoft Visual C++ 6.0, el ejemplo anterior produce un error cuando se compila en modo de depuración. El error se produce porque como de Visual C++ 6.0, cadena literales se colocan en leer genera sólo memoria de depuración, y el truco que los desarrolladores de XLL utilicen para la longitud de prefijo sus cadenas produce una infracción de acceso. Como una solución alternativa, puede quitar el modificador de compilador /Zi en su configuración del proyecto o sólo se prueba una generación de lanzamiento. Para obtener más información, vea el artículo siguiente en Microsoft Knowledge Base:
198477PRB: Uso de /Zi puede producir infracción de acceso

Referencias

Para obtener más información acerca de los XLL, vea:
Kit de desarrollo de Microsoft Excel 97 (ISBN: 1-57231-498-2)

Propiedades

Id. de artículo: 178474 - Última revisión: lunes, 12 de febrero de 2007 - Versión: 4.3
La información de este artículo se refiere a:
  • Microsoft Excel 2000 Standard Edition
  • Microsoft Excel 2002 Standard Edition
  • Microsoft Excel 97 Standard Edition
  • Microsoft Visual C++ 4.0 Standard Edition
  • Microsoft Visual C++ 5.0 Enterprise Edition
  • Microsoft Visual C++ 6.0 Enterprise
  • Microsoft Visual C++ 5.0 Professional
  • Microsoft Visual C++ 6.0 Professional
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
Palabras clave: 
kbmt kbhowto KB178474 KbMtes
Traducción automática
IMPORTANTE: Este artículo ha sido traducido por un software de traducción automática de Microsoft (http://support.microsoft.com/gp/mtdetails) en lugar de un traductor humano. Microsoft le ofrece artículos traducidos por un traductor humano y artículos traducidos automáticamente para que tenga acceso en su propio idioma a todos los artículos de nuestra base de conocimientos (Knowledge Base). Sin embargo, los artículos traducidos automáticamente pueden contener errores en el vocabulario, la sintaxis o la gramática, como los que un extranjero podría cometer al hablar el idioma. Microsoft no se hace responsable de cualquier imprecisión, error o daño ocasionado por una mala traducción del contenido o como consecuencia de su utilización por nuestros clientes. Microsoft suele actualizar el software de traducción frecuentemente.
Haga clic aquí para ver el artículo original (en inglés): 178474

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com