Excel 2003,Windows XP SP3:
我们有许多Excel用户使用非常大的复杂Excel工作簿。典型的工作簿可能有60多个工作表,大小超过70MB。我们有一个.xll插件,我们生产并用于这些电子表格。我们的插件具有广泛的调试和日志记录功能。我们已经生产了插件的版本并使用了近10年。因此,Excel界面的基础设施非常稳定。
在某些情况下,Excel会挂在特定的代码段中;也就是说,它挂在Excel本身的代码中,它挂在一个特定的代码片段上。在这种情况下,有一个紧密的代码循环(可能是20个机器指令,没有“调用”),它无休止地执行。该代码似乎是一个循环的链表,通常只有很少的节点,例如只有四个节点。我看起来像是在走一个与评估树(某些部分)相对应的链表 - 但我根本不确定。
我能够通过一个非常简单的插件(3个注册函数返回固定数据)和一个非常简单的电子表格(5个单元格,3个使用3个插件函数的公式)来表现行为。只有在完成对工作表中所有单元格的评估以及使用结果更新屏幕后,Excel才会挂起。无论使用哪个Excel SDK版本(v5.0,v12.0和v14.0都经过测试),它都会挂起。
以下是示例代码的链接:Sample .xls workbook and corresponding .xll addin and source for addin
插件的来源很简单:
#include <windows.h>
#if SDK_VER == 5
#include "xlcall_v5_0.h"
#elif SDK_VER == 12
#include "xlcall_v12_0.h"
#elif SDK_VER == 14
#include "xlcall_v14_0.h"
#endif
extern "C" __declspec(dllexport) int xlAutoOpen(void) {
#define N_FUNCTIONS 3
#define N_FUNCTION_REGISTRATION_PARAMETERS 3
char* rgFuncs[N_FUNCTIONS][N_FUNCTION_REGISTRATION_PARAMETERS] = {
{"\013FunctionOne", "\002RP", "\013FunctionOne"},
{"\013FunctionTwo", "\002RP", "\013FunctionTwo"},
{"\014FunctionFour", "\003RBP", "\014FunctionFour"} };
XLOPER xlFuncParams[N_FUNCTION_REGISTRATION_PARAMETERS+1];
LPXLOPER ppxlFuncParams[N_FUNCTION_REGISTRATION_PARAMETERS+1];
Excel4(xlGetName, (ppxlFuncParams[0] = &xlFuncParams[0]), 0);
for(int i = 0; i < N_FUNCTIONS; i++) {
for (int j = 1; j <= N_FUNCTION_REGISTRATION_PARAMETERS; j++) {
xlFuncParams[j].xltype = xltypeStr;
xlFuncParams[j].val.str = rgFuncs[i][j-1];
ppxlFuncParams[j] = &xlFuncParams[j];
}
Excel4v(xlfRegister, 0, N_FUNCTION_REGISTRATION_PARAMETERS+1, ppxlFuncParams);
}
Excel4(xlFree, 0, 1, (LPXLOPER)&xlFuncParams[0]);
return 1;
}
extern "C" __declspec(dllexport) LPXLOPER xlAddInManagerInfo(LPXLOPER xAction) {
static XLOPER xInfo;
XLOPER xloCoerceType, xIntAction;
xloCoerceType.xltype = xltypeInt; xloCoerceType.val.w = xltypeInt;
Excel4(xlCoerce, &xIntAction, 2, xAction, (LPXLOPER)&xloCoerceType);
if( xIntAction.xltype == xltypeInt && xIntAction.val.w == 1) {
xInfo.xltype = xltypeStr;
xInfo.val.str = "\010ExcelBug";
} else {
xInfo.xltype = xltypeErr;
xInfo.val.err = xlerrValue;
}
return (LPXLOPER)&xInfo;
}
LPXLOPER XLReturn(const double* pdData, const int nData, bool bRow=false) {
static XLOPER xlDLLResult;
static int nAllocated = 0;
if( nAllocated==0 ) {
xlDLLResult.xltype = xltypeMulti;
nAllocated=max(nData,2);
xlDLLResult.val.array.lparray = new XLOPER[nAllocated];
} else if( nAllocated < nData ) {
delete [] xlDLLResult.val.array.lparray;
nAllocated = nData;
xlDLLResult.val.array.lparray = new XLOPER[nAllocated];
}
for(int i = 0; i < nData; ++i) {
xlDLLResult.val.array.lparray[i].xltype = xltypeNum;
xlDLLResult.val.array.lparray[i].val.num = pdData[i];
}
xlDLLResult.val.array.rows = (WORD)(bRow? 1 : nData );
xlDLLResult.val.array.columns = (WORD)(bRow? nData : 1 );
return (LPXLOPER) &xlDLLResult;
}
extern "C" __declspec(dllexport) LPXLOPER FunctionOne( LPXLOPER ) {
double dData = 41144.;
return XLReturn(&dData, 1);
}
extern "C" __declspec(dllexport) LPXLOPER FunctionTwo( LPXLOPER ) {
const double pdData[2] = {41145., 41176.};
return XLReturn(pdData, 2);
}
extern "C" __declspec(dllexport) LPXLOPER FunctionFour( double, LPXLOPER ) {
const double pdData[2] = {41145., -0.01345212};
return XLReturn(pdData, 2, true);
}
演示问题的电子表格位于上面链接指向的包中。
有没有人见过类似的行为(是的,描述很模糊,所以我意识到很难说......)?
答案 0 :(得分:0)
这已经被Microsoft确认为Excel 2003中的一个错误。它发生在我的简单示例的更多情况下。我的简单示例需要卸载和重新加载插件,但我发生错误的情况是我只是在做范围计算。当在范围计算之后尝试表单计算(shift-F9)时,似乎总是会发生这种情况。他们不愿意解决它。我很惊讶我没有看到任何其他关于这个错误的抱怨。