如何在input数值时停止计算Excel-DNA函数

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

现在,当我在Excel中调用函数并开始input值时,即使在完成所有input之前,它也开始计算。 更重要的是,当我点击单元格并更改一些input时,函数也会重新计算。 通常我不介意。 但是由于performance缓慢,它变成了一场考验

有没有办法抑制这种行为? (设置计算手动似乎没有工作)基本上我想要的Excel-DNA公式(重新)只有当F9按下计算。

如果任何人有另一种语言的解决scheme,我会很乐意使用它作为一个灵感,并将其移植到C#。

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

你可以调用ExceDnaUtil.IsInFunctionWizard()来检查。

所以你的function可能会去:

public static object SlowFunction() { if (ExcelDnaUtil.IsInFunctionWizard()) return "!!! In Function Wizard"; // do the real work.... } 

其值得关注的是Excel DNA Google小组针对XLDANA相关的问题和解答https://groups.google.com/forum/#!forum/exceldna

您遇到的问题是,Excel函数向导将在input参数值时重复调用该函数。

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

我有一些C ++代码可以在生产中强有力地执行此操作。 希望你可以把它移植到C#。 它使用Windows API。 您需要注意function向导与特定的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; }