xlAddInManagerInfo/xlAddInManagerInfo12
在 Excel 会话中,每一次调用 Add-In 管理器时,系统会调用这两个函数。此函数可以在 Add-In 管理器中提供关于 Add-In 的信息。
如果 XLL 同时输出了这两个函数,Excel 2007 会优先调用 xlAddInManagerInfo12 。xlAddInManagerInfo12功能 应该和 xlAddInManagerInfo 保持一至,从而保证 XLL 在不同版本的 Excel 中相互兼容。Excel 总是默认 xlAddInManagerInfo12 返回 XLOPER12 数据类型,xlAddInManagerInfo 返回 XLOPER 数据类型。
xlAddInManagerInfo12 只能由 Excel 2007 版本 调用,同样早期版本的 Excel 也不支持 XLOPER12 数据类型。
XLL 可以不用实现和输出这两个函数,这并不会影响 XLL 的运行。
函数原型
LPXLOPER WINAPI xlAddInManagerInfo(LPXLOPER pxAction);
LPXLOPER WINAPI xlAddInManagerInfo(LPXLOPER pxAction);
参数
pxAction: 一个 XLOPER/XLOPER12 数值类型指针。
Excel 会调用此参数。
属性值/返回值
如果 pxAction 数值是1 ,你的这个函数在实现时就需要返回 一个关于 add-in 的字符串信息,通常返回的 add-in 名称或是版本号。其它情况下,函数需要返回 #VALUE!。
如果你没有返回任意一个字符串,Excel 会尝试将返回值转换为 字符串。
备注
如果返回的字符串是一个动态分析内存空间,你必需确保内存最终是可以释放的。如果字符串由 Excel 分配,你可以设置 xlbitXLFree 选项。如果字符串是由 DLL 分配的,你就需要设置为 xlbitDLLFree 选项,并且实现 xlAutoFree(如果返回的是XLOPER) 或 xlAutoFree12(如果返回的 XLOPER12) 函数。
实例
\SAMPLES\GENERIC\GENERIC.C
LPXLOPER12 WINAPI xlAddInManagerInfo12(LPXLOPER12 xAction)
{
static XLOPER12 xInfo, xIntAction;
/*
** This code coerces the passed-in value to an integer. This is how the
** code determines what is being requested. If it receives a 1, it returns a
** string representing the long name. If it receives anything else, it
** returns a #VALUE! error.
*/
Excel12f(xlCoerce, &xIntAction, 2, xAction, TempInt12(xltypeInt));
if(xIntAction.val.w == 1)
{
xInfo.xltype = xltypeStr;
xInfo.val.str = L"\026Example Standalone DLL";
}
else
{
xInfo.xltype = xltypeErr;
xInfo.val.err = xlerrValue;
}
// Word of caution - returning static XLOPERs/XLOPER12s is not thread safe
// for UDFs declared as thread safe. Use alternate memory allocation mechanisms.
return (LPXLOPER12)&xInfo;
}
xlAutoAdd
在 Excel 会话期间,任意时候使用 Add-In 管理器载入 XLL 都会调用此函数。需要注意的是,此函数不会在 Excel 启动时预载入 add-in 时调用。
此函数可以用于显示自定义对话框告知用户 Add-In 已经激活,或是读写注册表,检查认证信息等等。
对 XLL 来说,此函数不是必需函数。
原型
int WINAPI xlAutoAdd(void);
参数
此函数没有带参数
属性值和返回值
你的函数实现需要返回 1 (int)
备注
当你需要在 使用 Add-In 管理添加 XLL 执行某些操作时,使用此 函数
实例
函数实例参考:
\SAMPLES\EXAMPLE\EXAMPLE.C 和 \SAMPLES\GENERIC\GENERIC.C 下面的代码来自于\SAMPLES\EXAMPLE\EXAMPLE.C.
int WINAPI xlAutoAdd(void)
{
XCHAR szBuf[255];
wsprintfW((LPWSTR)szBuf, L"Thank you for adding Example.XLL\n"
L"build date %hs, time %hs",__DATE__, __TIME__);
/* Display a dialog indicating that the XLL was successfully added */
Excel12f(xlcAlert, 0, 2, TempStr12(szBuf), TempInt12(2));
return 1;
}
xlAutoClose
任何时候去激活 XLL 都会调用这个函数。 Excel 会在正常关闭程序时,去激活 add-in 。也可以在 使用 Excel 的时候,由用户手动去激活。
Excel 不强制要求 XLL 实现和输出些函数。尽管它有时对以下操作十分有用,如:如果 XLL 去激活函数和命令,释放资源、取消定制等等。如果 XLL 没有确定要去激活函数和命令,Excel 会在调用 xlAutoClose 函数后,执行此操作。
函数原型
int WINAPI xlAutoClose ( void );
参数
这个函数没有带任何参数。
属性和返回值
你实现此函数时,必需返回 1 (int)。
备注
Excel 在任何时候去激活 XLL ,去激活就是从内存中卸载 XLL。XLL 会在以下几种情形被去激活:
- 在运行 Excel 时激活了XLL,然后正常关闭 Excel 的情况下。
- 在 Excel 运行期间,用户手动卸载。
- XLL 可以使用几下几种方法制裁:
- 使用 Add-In 管理器。
- 在其它的 XLL 中调用 xlFUnfregister 函数,使用 DLL 名称做为唯一参数。
- 在 XLM 宏表中调用 UNREGISTER ,使用 DLL 名称做为唯一参数。
这个函数可以做以下这些操作:
- 移除由 XLL 添加的菜单和菜单项。
- 执行任何必要的全局清理
- 删除输出函数创建的名称。记住注册 函数 可能会导致创建一些名称。
实例
实例源文件在 SAMPLES\EXAMPLE\EXAMPLE.C 和 SAMPLES\GENERIC\GENERIC.C,下面的实例来自于SAMPLES\GENERIC\GENERIC.C.
int WINAPI xlAutoClose(void)
{
int i;
XLOPER12 xRes;
//
// This block first deletes all names added by xlAutoOpen or
// xlAutoRegister12. Next, it checks if the drop-down menu Generic still
// exists. If it does, it is deleted using xlfDeleteMenu. It then checks
// if the Test toolbar still exists. If it is, xlfDeleteToolbar is
// used to delete it.
//
// The following code to delete the defined names
// does not work in the current version of Excel.
// You cannot delete these names once they are Registered.
// The code is left here in case the functionality becomes
// available in a future version.
//
for (i = 0; i < g_rgWorksheetFuncsRows; i++)
Excel12f(xlfSetName, 0, 1, TempStr12(g_rgWorksheetFuncs[i][2]));
for (i = 0; i < g_rgCommandFuncsRows; i++)
Excel12f(xlfSetName, 0, 1, TempStr12(g_rgCommandFuncs[i][2]));
//
// Everything else works as documented.
//
Excel12f(xlfGetBar, &xRes, 3, TempInt12(10), TempStr12(L"Generic"), TempInt12(0));
if (xRes.xltype != xltypeErr)
{
Excel12f(xlfDeleteMenu, 0, 2, TempNum12(10), TempStr12(L"Generic"));
// Free the XLOPER12 returned by xlfGetBar //
Excel12f(xlFree, 0, 1, (LPXLOPER12) &xRes);
}
Excel12f(xlfGetToolbar, &xRes, 2, TempInt12(7), TempStr12(L"Test"));
if (xRes.xltype != xltypeErr)
{
Excel12f(xlfDeleteToolbar, 0, 1, TempStr12(L"Test"));
// Free the XLOPER12 returned by xlfGetToolbar //
Excel12f(xlFree, 0, 1, (LPXLOPER12) &xRes);
}
return 1;
}
xlAutoFree / xlAutoFree12
当 XLL 工作表函数返回 XLOPER / XLOPER12 数据类型,并且它们设置了一个标识,告诉 Excel这个 XLL 需要释放时才会调用这两个函数。 它能够让 XLL 返回一个动态分配数组、字符串 和 外部引用 时不会造成内存泄漏。更详细的信息,请查看 Excel 2007 内存管理 一节。
只有 Excel 2007 及其以后的版本才支持 xlAutoFree12 函数,和 XLOPER12 数据类型。
Excel 不强制要求 XLL 实现和输出些函数。但当你的 XLL 函数返回了 动态分配 的 XLOPER 和 XLOPER12 数据类型时或是包含了动态分配的内存指针时,你必需实现它们。确保你的 XLL 从头到尾,就使用一至的方法来管理内存,以及统一的 xlAutoFree 和 xlAutoFree12 的函数实现。
在 xlAutoFree / xlAutoFree12 函数内部,Excel 的回调功能是不可用的,但有一个例外,xlFree 函数可用于释放 Excel 分配的内存。
函数原型
void WINAPI xlAutoFree(LPXLOPER pxFree);
void WINAPI xlAutoFree12(LPXLOPER12 pxFree);
参数
pxFree ( 在 xlAutoFree 中使用 LPXLOPER )
pxFee (在 xlAutoFree12 中使用 LPXLOPER12 )
XLOPER 或 XLOPER12 内存指针,表示需要释放的内存。
属性值 / 返回值
这个函数不会返回任何值,因此需要声明为返回 void。
备注
当 Excel 2007 设置了使用 多线程计算时, xlAutoFree / xlAutoFree12 会在同一个线程上被调用 并返回。系统总是在随后的单元格评估线程之前调用 xlAutoFree / xlAutoFree12 。这简化了你的 XLL 中的线程设计。
如果你的 xlAutoFree / xlAutoFree12 支持查看 pxFree 的 xltype 字段,你需要知道, xlbitDLLFree 位必需设置。
实例
实例 1
第一个实例来自于 \SAMPLES\EXAMPLE\EXAMPLE.C 示范了 xlAutoFree 的具体实现,这只有一个函数 fArray 。通常,你的 XLL 中有多个函数返回了 XLOPER 或 XLOPER12 需要释放。在这种情况下,需要一个受较少限制的实现。
实例 2
第二个实例,始终假设 XLOPER12 创建与 1.6.3节的 的 xl12_Str_example、xl12_Ref_example 和 xl12_Multi_example。假设已经设置了 xlbitDLLFree 位。所有的字符串,数组,和外部引用内在都是使用 malloc 动态分配,因此希望在需要释放时可以正常释放。
实例 3
第三个实例实现,始终是用 malloc 为函数返回的 XLOPER12数据类型, 动态分配字符串,外部引用和数组,并且 XLOPER12 自身也是动态分配的。函数返回的动态分配 XLOPER12 类型是确保函数线程安全性的唯一方法。
//
// BEGIN EXAMPLE IMPLEMENTATION 1
//
LPXLOPER12 WINAPI fArray(void)
{
LPXLOPER12 pxArray;
static XLOPER12 xMulti;
int i;
int rwcol;
xMulti.xltype = xltypeMulti | xlbitDLLFree;
xMulti.val.array.columns = 1;
xMulti.val.array.rows = 8;
// For large values of rows and columns, this would overflow
// use __int64 in that case and return an error if rwcol
// contains a number that won't fit in sizeof(int) bytes
rwcol = xMulti.val.array.columns * xMulti.val.array.rows;
pxArray = (LPXLOPER12)GlobalLock(hArray = GlobalAlloc(GMEM_ZEROINIT, rwcol * sizeof(XLOPER12)));
xMulti.val.array.lparray = pxArray;
for(i = 0; i < rwcol; i++)
{
pxArray[i].xltype = xltypeInt;
pxArray[i].val.w = i;
}
// Word of caution - returning static XLOPERs/XLOPER12s is not thread safe
// for UDFs declared as thread safe, use alternate memory allocation mechanisms
return (LPXLOPER12)&xMulti;
}
void WINAPI xlAutoFree12(LPXLOPER12 pxFree)
{
GlobalUnlock(hArray);
GlobalFree(hArray);
return;
}
//
// BEGIN EXAMPLE IMPLEMENTATION 2
//
void WINAPI xlAutoFree12(LPXLOPER12 pxFree)
{
if(pxFree->xltype & xltypeMulti)
{
/* Assume all string elements were allocated using malloc, and
** need to be freed using free. Then free the array itself.
*/
int size = pxFree->val.array.rows *
pxFree->val.array.columns;
LPXLOPER12 p = pxFree->val.array.lparray;
for(; size-- > 0; p++) // check elements for strings
if(p->xltype == xltypeStr)
free(p->val.str);
free(pxFree->val.array.lparray);
}
else if(pxFree->xltype & xltypeStr)
{
free(pxFree->val.str);
}
else if(pxFree->xltype & xltypeRef)
{
free(pxFree->val.mref.lpmref);
}
}
//
// BEGIN EXAMPLE IMPLEMENTATION 3
//
LPXLOPER12 WINAPI example_xll_function(LPXLOPER12 pxArg)
{
// Thread-safe return value. Every invocation of this function
// gets its own piece of memory.
LPXLOPER12 pxRtnValue = (LPXLOPER12)malloc(sizeof(XLOPER12));
// Initialize to a safe default
pxRtnValue->xltype = xltypeNil;
// Set the value of pxRtnValue making sure that strings, external
// references, arrays, and strings within arrays are all dynamically
// allocated using malloc.
// (code omitted)
// ...
// Set xlbitDLLFree regardless of the type of the return value to
// ensure xlAutoFree12 is called and pxRtnValue is freed.
pxRtnValue->xltype |= xlbitDLLFree;
return pxRtnValue;
}
void WINAPI xlAutoFree12(LPXLOPER pxFree)
{
if(pxFree->xltype & xltypeMulti)
{
// Assume all string elements were allocated using malloc, and
// need to be freed using free. Then free the array itself.
int size = pxFree->val.array.rows *
pxFree->val.array.columns;
LPXLOPER12 p = pxFree->val.array.lparray;
for(; size-- > 0; p++) // check elements for strings
if(p->xltype == xltypeStr)
free(p->val.str);
free(pxFree->val.array.lparray);
}
else if(pxFree->xltype & xltypeStr)
{
free(pxFree->val.str);
}
else if(pxFree->xltype & xltypeRef)
{
free(pxFree->val.mref.lpmref);
}
// Assume pxFree was itself dynamically allocated using malloc.
free(pxFree);
}
xlAutoOpen
每个有效的 XLL 必需输出和实现此函数。 xlAutoOpen 函数是注册 XLL 函数和命令的推荐方法,它还常用于 初始化数据结构,自定义用户界面等等。
函数原型
int WINAPI xlAutoOpen ( void );
参数
这个函数没带任何参数。
属性值 / 返回值
实现此函数时,必需返回 1 ( int )。
备注
Excel 会在 XLL 被激活后调用此函数。XLL 会在以下几种情形下被激活。
- 如果在上一次 Excel 正常关闭时,激活了某个 XLL。那么在 Excel 启动时,会再次激活。
- 在 Excel 运行过程中载入 XLL。
- XLL 可以使用下面几种方法载入:
- 使用文件中的打开菜单打开XLL(Excel 2007 支持使用此方法载入 XLL )
- 使用 Add-In 管理器
- 从其它的XLL调用 xlfRegister,使用 DLL 名称作为唯一的参数。
- 从 XLM 宏表,调用 REGISTER,使用 DLL 名称作为唯一的参数。
- 如果 add-in 是去激活的,并在 Excel 运行期间重新激活,此函数会再次被调用。
实例
查看文件 SAMPLES\EXAMPLE\EXAMPLE.C, SAMPLES\GENERIC\GENERIC.C, 和 SAMPLES\STOCK\STOCK.CPP 中的此函数实现实例。
xlAutoRegister/xlAutoRegister12
任何时候调用 XLM 函数 REGISTER 或 C API 等效函数 xlfRegister 函数,都会调用 xlAutoRegister 函数。其函数返回的数据类型和参数被登记为缺失。它允许 XLL 查找它的输出的函数和命令列表,注册指定的函数的参数和返回数据类型。
如果 XLL 同时输出了这两个函数,Excel 会优先调用 xlAutoRegister12
Excel 不强制要求 XLL 实现和输出这些函数。
如果 xlAutoRegister / xlAutoRegister12 尝试在没有提供参数和返回值的情况下注册函数。就会发生 递归循环调用,最终造成调用堆栈溢出 Excel 发生崩溃。
函数原型
LPXLOPER12 WINAPI xlAutoRegister12(LPXLOPER12 pxName);
LPXLOPER WINAPI xlAutoRegister(LPXLOPER pxName);
参数
pxName (xltypeStr)
被注册的 XLL 函数的名称。
属性值 / 返回值
这个函数应该返回 打算使用 xlfRegister函数 注册的 XLL 函数的 pxName 的注册结果,如果指定的函数不在 XLL 的输出函数列表中,它将返回一个 #VLAUE! 错误,或 NULL (由Excel解释 #VALUE 时获取)
备注
你的 xlAutoRegister 将根据传入的名称执行一个区分大小写的查询,查找 XLL 输出的函数和命令列表,如果函数或命令被找到,xlAutoRegister 将试图使用 xlfRegister 函数注册它,确保 函数的参数和返回支持 string 类型,以及其它关于函数的必要信息。在 调用 xlfRegister 返回后,这些信息将返回给 Excel。 如果函数注册成功,xlfRegister 返回 一个xltypeNum 值,其内部包含了 函数的注册ID。
实例
在文件 SAMPLES\EXAMPLE\EXAMPLE.C 查看此函数的实现实例。
xlAutoRemove
任何时候,用户在 Excel 运行期间,使用 Add-In 管理器去激活 XLL,都会调用此函数。这个函数,不会在 Excel 关闭时 add-in 正常或异常安装时被调用。
这个函数可以用于显示用户自定义对话框,告诉用户这个 add-in 已经被 去激活,或是读取和设置注册表信息。
Excel 不强制要求 XLL 实现和输出这个函数。
函数原型
int WINAPI xlAutoRemove(void);
参数
此函数没有带有参数
属性值 / 返回值
实现这个函数时,必需返回 1 ( int )。
备注
当你希望在完成任何任务后,从 Add-In 管理器中删除这个 XLL,就可以使用此函数。
实例
参考文件 \SAMPLES\EXAMPLE\EXAMPLE.C 和 \SAMPLES\GENERIC\GENERIC.C 中的函数实现. 下面的代码来自于 \SAMPLES\EXAMPLE\EXAMPLE.C.
int WINAPI xlAutoRemove(void)
{
/* Display a dialog box indicating that the XLL was successfully removed */
Excel12f(xlcAlert, 0, 2,
TempStr12(L"Thank you for removing Example.XLL!"),
TempInt12(2));
return 1;
}