5

我在 c# 中实现了一些复杂且计算量大的函数。为了在 Excel 中使用它,我通过 Excel-DNA 创建了一个 Excel-AddIn。

现在,当我在 Excel 中调用该函数并开始输入值时,它甚至在我完成所有输入之前就开始计算。更重要的是,当我单击单元格并更改一些输入时,该函数也会重新计算。通常我不会介意的。但是由于性能缓慢,它变成了一种磨难

有没有办法抑制这种行为?(将计算设置为手动似乎不起作用)基本上我希望 Excel-DNA 公式仅在按下 F9 时(重新)计算。

如果有人有另一种语言的解决方案,我很乐意将其用作灵感并将其移植到 c#。

4

2 回答 2

11

根据 Govert(XL DNA 的作者)的说法,您可以这样做:

您可以调用 ExceDnaUtil.IsInFunctionWizard() 进行检查。

所以你的功能可能会:

public static object SlowFunction()
{
    if (ExcelDnaUtil.IsInFunctionWizard()) return "!!! In Function
Wizard";

    // do the real work....
} 

值得查看 Excel DNA 谷歌组的 XLDANA 相关问题和答案 https://groups.google.com/forum/#!forum/exceldna

于 2014-01-23T16:00:10.680 回答
2

您遇到的问题是 Excel 函数向导会在您输入参数值时重复调用该函数。

为了避免这种情况,您的函数需要检测函数向导的存在并相应地进行。

我有一些 C++ 代码可以在生产中稳健地执行此操作。希望您可以将其移植到 C#。它使用 Windows API。您需要注意函数向导与特定的 Excel 会话相关;特别注意Excel2013。

typedef struct _EnumStruct
{
    bool wizard;
    DWORD pid;
} EnumStruct, FAR* LPEnumStruct;

BOOL CALLBACK EnumProc(HWND hwnd, LPEnumStruct pEnum)
{
    static const char szFunctionWizardClass[] = "bosa_sdm_XL";
    static const char szFunctionWizardCaption[] = "Function Arguments";

    char szClass[sizeof(szFunctionWizardClass)];
    char szCaption[sizeof(szFunctionWizardCaption)];

    if (GetClassName(hwnd, (LPSTR)szClass, sizeof(szFunctionWizardClass))){
        if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, (LPSTR)szClass, (lstrlen((LPSTR)szClass) > lstrlen(szFunctionWizardClass)) ? lstrlen(szFunctionWizardClass) : -1, szFunctionWizardClass, -1) == CSTR_EQUAL){
            // Do the process IDs match? (The former way of checking parent windows doesn't work in Excel2013).
            DWORD pid = NULL;
            GetWindowThreadProcessId(hwnd, &pid);
            if (pid == pEnum->pid){
                // Check the window caption
                if (::GetWindowText(hwnd, szCaption, sizeof(szFunctionWizardCaption))){
                    if (CompareString(MAKELCID(MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), SORT_DEFAULT), NORM_IGNORECASE, (LPSTR)szCaption, (lstrlen((LPSTR)szCaption) > lstrlen(szFunctionWizardCaption)) ? lstrlen(szFunctionWizardCaption) : -1, szFunctionWizardCaption, -1) == CSTR_EQUAL){
                        pEnum->wizard = TRUE;
                        return FALSE;
                    }
                }
            }
        }
    }
    // Continue the enumeration
    return TRUE;
}

bool Excel12::calledFromFunctionWizard()
{
    EnumStruct enm;
    enm.wizard = FALSE;
    enm.pid = GetProcessId(GetCurrentProcess());
    EnumWindows((WNDENUMPROC)EnumProc, (LPARAM)((LPEnumStruct)&enm));
    return enm.wizard;
}
于 2014-01-23T10:51:18.153 回答