我正在尝试使用C API编写Excel的数组构造函数作为工作表函数。
目标:=array_cons(1, 2, 3) => {1, 2, 3}
但是,我没有正确初始化XLOPER12。在Excel中,我的函数当前返回#NUM
。我正在获取参数列表并通过宏将其打包到vargs
数组中,然后尝试返回所提供的数组部分。
#include <windows.h>
#include <xlcall.h>
#include <framewrk.h>
#include <boost/preprocessor.hpp>
#define VARG_COUNT 250
#define VARG_FORMAT(Z, A, B) B##A,
#define VARG_DEF_LIST(N) BOOST_PP_REPEAT(N, VARG_FORMAT, LPXLOPER12 varg) \
LPXLOPER12 varg##N
#define VARG_ARRAY(N) { BOOST_PP_REPEAT(N, VARG_FORMAT, varg) varg##N }
#define GET_VARGS VARG_ARRAY(VARG_COUNT)
__declspec(dllexport) LPXLOPER12 WINAPI array_cons(VARG_DEF_LIST(VARG_COUNT))
{
LPXLOPER12 vargs[] = GET_VARGS;
int args_passed = 0;
for(int i = 0; i < VARG_COUNT; ++i, ++args_passed)
{
if (vargs[i]->xltype == xltypeMissing)
{
break;
}
}
if (args_passed == 0)
{
XLOPER12 err;
err.xltype = xltypeErr;
err.val.err = xlerrValue;
return (LPXLOPER12)&err;
}
XLOPER12 list;
list.xltype = xltypeMulti;
list.val.array.lparray = (XLOPER12*)vargs;
list.val.array.rows = args_passed;
list.val.array.columns = 1;
return (LPXLOPER12)&list;
}
答案 0 :(得分:2)
我明白了。这里有几点需要注意 -
您需要确保您的UDF注册使用正确的签名。在我的情况下,我希望Excel引用给我各自的值,所以我在注册函数时使用了Q
类型。如果您不明白这一点,请查看http://msdn.microsoft.com/en-us/library/office/bb687869.aspx
为了返回一个数组,你必须动态地为list.val.array.lparray
成员分配新内存并迭代填充它。
__declspec(dllexport) LPXLOPER12 WINAPI array_cons(VARG_DEF_LIST(VARG_MAX)) {
LPXLOPER12 vargs[] = GET_VARGS;
int args_passed = 0;
for(int i = 0; i < VARG_MAX; ++i, ++args_passed) {
if (vargs[i]->xltype == xltypeMissing) {
break;
}
}
XLOPER12 list;
list.xltype = xltypeMulti | xlbitDLLFree;
list.val.array.lparray = new XLOPER12[args_passed];
list.val.array.rows = args_passed;
list.val.array.columns = 1;
for(int i = 0; i < args_passed; ++i) {
list.val.array.lparray[i] = *vargs[i];
}
return &list;
}
由于我们是动态分配内存,我们需要定义回调以释放它。
__declspec(dllexport) void WINAPI xlAutoFree12(LPXLOPER12 p) {
if (p->xltype == (xltypeMulti | xlbitDLLFree)) {
delete [] p->val.array.lparray;
}
}
答案 1 :(得分:1)
您的解决方案不完整。
你写
XLOPER12 list;
在函数体中。这使得“list”成为在堆栈上创建的局部变量。当函数返回时,“list”超出范围。您将返回指向不再在范围内的变量的指针,并且当Excel尝试访问此指针时,行为未定义。如果Excel在处理返回值之前碰巧调用另一个函数,则列表变量将被破坏。
解决方案是您必须为列表动态分配内存(然后确保稍后释放它)或使列表成为静态或全局变量。
答案 2 :(得分:0)
不确定为什么您认为xll库不允许您开发开源加载项。 IANAL,但Ms-PL似乎允许这样做。你看过http://xllfunctional.codeplex.com/了吗?它使用类似的非便携技巧,不会将增强功能拖入解决方案中。 WINAPI / __ stdcall就是这样。如果您知道事情如何发生在硅片上,您就可以利用它。