问题描述
我创建了一个自定义函数“ SumCells”,用于计算单元格的总和。当我在1,000,000个单元格(在一列中)上运行它时,它很快计数,但是当我尝试删除它时,Excel冻结了很长时间。我认为这与释放内存有关。谁可以提意见,请帮忙。也许您有一个指向此类功能的真实示例的链接。
我的代码:
#define g_rgNumUDFs 1
#define g_rgUDFdata 11
#include <windows.h>
#include "XLCALL.H"
#include "FRAMEWRK.H"
static LPWSTR g_rgUDFs
[g_rgNumUDFs][g_rgUDFdata] =
{
{
L"SumCells",// Function name/ordinal
L"BQ",// Func signature type
L"SumCells",// Func name in Func wizard
L"Arg1",// Arg name in Func wizard
L"1",// Function type
L"SimpleXll2020",// Category in Func wizard
L"",// Shortcut (commands only)
L"",// Help topic
L"Sum data",// Func help in Func wizard
L"Help for Arg1",// Arg help in Func wizard
L""
}
};
__declspec(dllexport) double SumCells(XLOPER12& arg1)
{
double result = 0;
size_t numCols = arg1.val.array.columns;
size_t numRows = arg1.val.array.rows;
for (size_t i = 0; i < numCols * numRows; ++i)
{
result += arg1.val.array.lparray[i].val.num;
}
return result;
}
解决方法
您必须至少检查XLOPER的类型(xltypeStr,xltypeNum ...)并正确访问数据(数组是行主要的):
double result = 0;
if ((arg1.xltype & xltypeMulti) !=0)
{
size_t numCols = arg1.val.array.columns;
size_t numRows = arg1.val.array.rows;
for (int r=0;r<numRows ;r++)
for (int c = 0; c < numCols; c++)
{
LPXLOPER12 cell = arg1.val.array.lparray + ((r * numCols) + c);
if ((cell->xltype & xltypeNum) !=0)
result += cell->val.num;
}
}
return result;
,
SDK下载中随附的大多数示例(例如,GENERIC XLL示例中GENERIC.C文件中的“ FuncSum”示例)都使用LPXLOPER12指针和'U'作为参数类型。您已选择传递XLOPER12&引用,并在功能注册中使用“ Q”参数类型。
尽管我不是API方面的专家,但该参考文献建议类型“ Q”涉及在传递之前对数据数组进行某些处理(例如,将范围引用转换为值数组),因此可能需要进行一些内存清理后。我对“ U”类型的回忆是,它是指向传递的数据数组的更直接的指针。
根据参考资料: “当DLL函数参数注册为采用类型P XLOPER或类型Q XLOPER12s时,Excel在准备这些参数时会将单单元格引用转换为简单值,将多单元格引用转换为数组。”