使用自定义XLL C ++函数删除列时Excel冻结

问题描述

我创建了一个自定义函数“ 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在准备这些参数时会将单单元格引用转换为简单值,将多单元格引用转换为数组。”

Link to xlfRegister from SDK reference