我在c#中实现了一些复杂且计算量很大的函数。要在Excel中使用它,我已经通过Excel-DNA创建了Excel-AddIn。
现在,当我在Excel中调用该函数并开始输入值时,它甚至在我完成所有输入之前就开始计算。更重要的是,当我单击进入单元格并更改某些输入时,该功能也会重新计算。通常我不介意。但由于性能缓慢,它变成了一场考验。
有没有办法抑制这种行为? (将计算设置为手动似乎不起作用)基本上我希望Excel-DNA公式仅在按下F9时(重新)计算。
如果有人有其他语言的解决方案,我很乐意将其作为灵感,并将其移植到c#。
答案 0 :(得分:11)
根据Govert(XL DNA的作者),您可以这样做:
您可以调用ExceDnaUtil.IsInFunctionWizard()进行检查。
所以你的功能可能会去:
public static object SlowFunction()
{
if (ExcelDnaUtil.IsInFunctionWizard()) return "!!! In Function
Wizard";
// do the real work....
}
值得一看的是关于XLDANA相关问题和答案的Excel DNA Google小组 https://groups.google.com/forum/#!forum/exceldna
答案 1 :(得分: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;
}