六、最基本的加载宏函数
在这一节中我们将逐一介绍前面提到的几个最基本的函数,了解了这些函数的用法,就可以编写一个简单的xll加载宏了。每个函数都会有一个例子代码,这些代码是来自“ExcelAddin”工程中,你可以在光盘上找到“ExcelAddin”工程。
1、xlAutoOpen
函数原形:int __stdcall xlAutoOpen(void)
当xll加载宏被加载到Excel中时调用这个函数。在这个函数中加入任何需要初始化的操作,比如,注册函数,添加菜单、按钮等等。如果函数执行成功返回整数1。为了更好的阅读程序可以定义一个宏或常量表示函数是否执行成功。
下面的例子函数在执行时会在Excel中注册一个“MyFunc”函数和一个“MyMethod”方法,并在Excel中添加一个菜单,如果函数执行成功,你就可以在Excel调用“MyFunc”函数和“MyMethod”方法,并可以看到Excel界面上增加一个“MyMenu”的菜单。- int __stdcall xlAutoOpen(void)
- {
- MessageBox(NULL,_T("xlAutoOpen"),_T("xll"),MB_OK);
- if (true == m_Initialize)
- {
- return(XLL_SUCCESS);
- }
- int iNum = 0;
- static int iErr = 0;
- //从新设置字符串
- for (iNum=0;iNum<9;iNum++)
- {
- func[iNum][0] = (BYTE)(strlen(func[iNum])-1);
- }
- for (iNum=0;iNum<10;iNum++)
- {
- menu[iNum][0] = (BYTE)(strlen(menu[iNum])-1);
- }
- for (iNum=0;iNum<9;iNum++)
- {
- method[iNum][0] = (BYTE)(strlen(method[iNum])-1);
- }
- //获得xll的名字
- static XLOPER xllName;
- Excel4(xlGetName,&xllName,0);
- //注册“MyFunc”函数
- iErr = Excel4(xlfRegister,0,10,(LPXLOPER)&xllName,
- (LPXLOPER)TempStr(func[0]),
- (LPXLOPER)TempStr(func[1]),
- (LPXLOPER)TempStr(func[2]),
- (LPXLOPER)TempStr(func[3]),
- (LPXLOPER)TempStr(func[4]),
- (LPXLOPER)TempStr(func[5]),
- (LPXLOPER)TempStr(func[6]),
- (LPXLOPER)TempStr(func[7]),
- (LPXLOPER)TempStr(func[8]),
- (LPXLOPER)TempStr(func[9])
- );
- if (iErr != xlretSuccess)
- {
- MessageBox(NULL,"Can not register fun!","",MB_OK);
- return(XLL_FAIL);
- }
- //注册“MyMethod”方法
- iErr = Excel4(xlfRegister,0,6,(LPXLOPER)&xllName,
- (LPXLOPER)TempStr(method[0]),
- (LPXLOPER)TempStr(method[1]),
- (LPXLOPER)TempStr(method[2]),
- (LPXLOPER)TempStr(method[3]),
- (LPXLOPER)TempStr(method[4]),
- (LPXLOPER)TempStr(method[5])
- );
- if (iErr != xlretSuccess)
- {
- MessageBox(NULL,"Can not register Method!","",MB_OK);
- return(XLL_FAIL);
- }
- //释放xllName所占用的空间
- Excel4(xlFree,0,1,(LPXLOPER)&xllName);
- nMenuItems = 2;
- static XLOPER xMenu;
- static XLOPER xMenuList[10*5];
- //设置菜单参数
- xMenu.xltype = xltypeMulti;
- xMenu.val.array.lparray = &xMenuList[0];
- xMenu.val.array.rows = nMenuItems;
- xMenu.val.array.columns = 5;
- for (iNum=0;iNum<10;iNum++)
- {
- xMenuList[iNum].xltype = xltypeStr;
- xMenuList[iNum].val.str = menu[iNum];
- }
- //注册菜单
- Excel4(xlfAddMenu,0,2,TempNum(1),(LPXLOPER)&xMenu);
- m_Initialize = true;
- return(XLL_SUCCESS);
- }
复制代码
2、xlAutoClose
函数原形是:int __stdcall xlAutoClose(void)
Excel会在关闭或卸载xll加载宏时调用此函数。当执行这个函数时意味着你要关闭xll加载宏并且不再容许Excel调用这个加载宏中的函数或方法,所以你可以在这个函数中实现释放xll加载宏占用的内存以及注销自定义函数。你也可以在这个函数执行时删除菜单,按钮等。
下面的例子函数在执行时会把“MyMenu”菜单项从Excel中移除。- int __stdcall xlAutoClose(void)
- {
- if (false == m_Initialize)
- {
- return(XLL_SUCCESS);
- }
- //删除菜单
- char chMenu[] = " MyMenu";
- Excel4(xlfDeleteMenu,0,2,TempNum(1),TempStr(chMenu));
- m_Initialize = true;
- return(XLL_SUCCESS);
- }
复制代码
3、xlAutoAdd
函数原形是:int __stdcall xlAutoAdd(void)
当通过加载宏管理器来加载xll宏和在加载宏管理器中激活xll宏时会调用此函数,但是,调用此函数的时候也会调用xlAutoOpen函数,所以你可以忽略此函数并把相关操作放在xlAutoOpen函数中执行。
下面的例子函数通过调用xlAutoOpen执行初始化操作。- int __stdcall xlAutoAdd(void)
- {
- if (false == m_Initialize)
- {
- xlAutoOpen();
- }
- return(XLL_SUCCESS);
- }
复制代码
4、xlAutoRemove
当xll加载宏被关闭或被取消激活状态时,Excel会调用此函数,但是这个函数同样也可以被忽略,因为在调用它的时候,也会调用xlAutoClose函数。
下面的例子函数在被调用时除显示一个提示对话框外不执行任何其他操作- int __stdcall xlAutoRemove(void)
- {
- MessageBox(NULL,"xlAutoRemove","XLL",MB_OK);
- return(XLL_SUCCESS);
- }
复制代码
5、xlAddInManagerInfo
函数原形是:LPXLOPER __stdcall xlAddInManagerInfo(LPXLOPER xAction)
Excel会在第一次打开加载宏管理器时调用此函数,从中获得有关xll文件的信息并把注册名显示在加载宏管理器中,如果xll加载宏中并没有显示注册xll加载宏名,则在加载宏管理器中显示它的文件名(不包括扩展名)。函数返回一个字符串xloper的指针,其中字符串是要注册的名字。
下面的函数显示的注册了当前的xll加载宏的名字为“My Add-in!!!!”。- LPXLOPER __stdcall xlAddInManagerInfo(LPXLOPER xAction)
- {
- static XLOPER xInfo,xIntAction;
- //find out what action must be taken
- Excel4(xlCoerce,&xIntAction,2,xAction,TempInt(xltypeInt));
- strcpy(xllName," My Add-in!!!!");
- //Set title if asked
- if (xIntAction.val.w == 1)
- {
- xInfo.xltype = xltypeStr;
- xInfo.val.str = xllName;
- xInfo.val.str[0] = (char)strlen(&xInfo.val.str[1]);
- }
- else
- {
- xInfo.xltype = xltypeErr;
- xInfo.val.err = xlerrValue;
- }
- // Excel4(xlFree,0,1,(LPXLOPER)&xInfo);
- return((LPXLOPER)&xInfo);
- }
复制代码 如果这个函数执行成功则在加载宏管理器中出现一项“My Add-in!!!!”。如图
635344729934208984.jpg
6、xlAutoFree
函数原形是:void __stdcall xlAutoFree(xloper *)
当xll加载宏中的一个函数返回给Excel一个指向xloper的指针时,它被调用并把xloper指针传作为参数传递给它。通过它释放xll动态分配的xloper变量所占用的内存。通常一个函数需要返回xloper指针时,那么指针所占用的内存不能在返回前被是否,否则返回的指针将指向无效地址。但是已经分配的动态内存必须在合适的时候被释放,否则就会造成内存泄露。我们可以给要释放的xloper变量的中设置xlbitDllFree状态位并通过xlAutoFree函数来解决这个问题。
下面的例子函数功能是释放一个xloper指针,这个指针所指向的xloper可能是字符串,数组,或是一个范围的应用。函数分别对不同类型的xloper执行释放内存的操作。- void __stdcall xlAutoFree(XLOPER *pXloper)
- {
- if (pXloper->xltype & xltypeMulti)
- {
- int size = pXloper->val.array.rows * pXloper->val.array.columns;
- XLOPER *p = pXloper->val.array.lparray;
- for (;size-- > 0;p++)
- {
- if (p->xltype & (xlbitDLLFree | xlbitXLFree))
- {
- xlAutoFree(p);
- }
- }
- if (pXloper->xltype & xlbitDLLFree)
- {
- Excel4(xlFree,0,1,pXloper->val.array.lparray);
- }
- }
- else if (pXloper->xltype == (xltypeStr | xlbitDLLFree))
- {
- Excel4(xlFree,0,1,pXloper->val.str);
- }
- else if (pXloper->xltype == (xltypeRef | xlbitDLLFree))
- {
- }
- else if (pXloper->xltype | xlbitXLFree)
- {
- Excel4(xlFree,0,1,pXloper);
- }
- }
复制代码 |