如何使用 Visual c + + 的 excel 生成外接程序 (XLL)

文章翻译 文章翻译
文章编号: 178474 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

概要

外接程序可以用任何支持生成 dll (动态链接库) 的编译器生成的 Microsoft excel 是一个 XLL。本文旨在帮助您开始构建 XLLs Microsoft Visual c + +。若要进行这篇文章中概述的步骤中,您应该有一些经验生成 dll,并且您应该具有其中包含所需的标头和库文件,以生成一个 XLL Microsoft Excel 97 开发人员工具包。

更多信息

创建一个 XLL 的步骤

  1. 创建一个新的 MFC 应用程序向导 (.dll) 项目 (称为 Anewxll。
  2. Xlcall.h、 Framewrk.h、 Framewrk.c 和 Xlcall32.lib 从 Microsoft Excel 97 开发工具包复制到项目目录。
  3. 重命名 Framewrk.cpp Framewrk.c。
  4. 将 Framewrk.cpp 添加到您项目的源代码文件中。
  5. 将以下代码添加 # include Framewrk.cpp 以避免编译器错误关于预编译头的顶部的行:
    
          #include "stdafx.h"
    					
  6. 更改以下行中 Framewrk.cpp:
          #include "..\..\include\xlcall.h"
    					
    到:
          #include "xlcall.h"
    					
  7. 在项目菜单上,单击设置。单击链接选项卡,并将 Xlcall32.lib 添加到对象/库模块编辑框。
  8. 将以下代码添加 # include 语句 Anewxll.cpp 的顶部:
          #include "xlcall.h"
          #include "framewrk.h"
    					
    注: 项目现在安装程序也将相应地得到,并且应编译,但是,尚未添加 XLL 支持还。其余的步骤使您可以将添加到可以帮助您开始 XLL 一些示例代码。

  9. 将下面的代码添加到 Anewxll.cpp: 示例代码-----------
          //================================================================
          // 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. 将下列代码行添加到您 Anewxll.def 文件的末尾:
          xlAutoOpen
          xlAutoClose
          xlAddInManagerInfo
          MyMotd
          MyFunc
    					
  11. 您现在可以编译以产生称为 Anewxll.dll DLL 项目。 一旦编译 DLL,其重命名为 Anewxll.xll。

使用 Microsoft Excel 使用外接程序

  1. 启动一个新的工作簿在 Excel 中。
  2. 在工具菜单上,单击加载宏。浏览到添加 Anewxll.xll,然后单击确定。 请注意当您在加载项对话框中单击确定,xlAutoOpen 函数运行。
  3. 在 MyMenu 菜单上,单击 M.O.T.D。 在单击菜单项时 MyMotd 函数运行以显示与一个报价单的 MessageBox,如利百加指出一天,一个 Apple 保持医生消失 !"。
  4. 一个单元格中添加以下公式:
    =MYFUNC(2,6)
    					
    MYFUNC 返回 12,2 和 6 的乘积。

  5. 在工具菜单上,单击加载宏。清除加载宏复选框,然后单击确定。 请注意当您单击加载项对话框中的确定,xlAutoClose 函数运行。

其他说明

如果使用的 Microsoft Visual c + + 6.0 前面的示例中无法正常工作时在调试模式下编译它。由于为 Visual c + + 6.0 的字符串文本放在读取仅内存中调试生成,以及这一轮 XLL 开发人员使用长度前缀的字符串会导致访问冲突,将出现故障。作为工作周围,您可以删除您的项目设置中的 / ZI 编译器开关,或只是测试发布版本。有关详细的信息,请参阅下面 Microsoft 知识库中相应的文章:
198477PRB:/ZI 的使用会导致访问冲突

参考

有关 XLLs 的详细信息请参阅:
Microsoft Excel 97 开发工具包 (ISBN: 1-57231-498-2)

属性

文章编号: 178474 - 最后修改: 2007年2月12日 - 修订: 4.3
这篇文章中的信息适用于:
  • Microsoft Excel 2000 标准版
  • Microsoft Excel 2002 标准版
  • Microsoft Excel 97 标准版
  • Microsoft Visual C++ 4.0 标准版
  • Microsoft Visual C++ 5.0 企业版
  • Microsoft Visual C++ 6.0 企业版
  • Microsoft Visual C++ 5.0 专业版
  • Microsoft Visual C++ 6.0 专业版
  • Microsoft Visual C++, 32-bit Learning Edition 6.0
关键字:?
kbmt kbhowto KB178474 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 178474
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

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