У меня есть исходный код ниже для надстройки XLL Excel. Он компилируется в XLL без каких-либо проблем, и Excel принимает его, когда я регистрирую его с помощью диспетчера надстроек (т.е. ошибка «файл не является допустимой надстройкой»). Но проблема в том, что он появляется в списке надстроек с описанием «xllSample» (имя файла XLL, а не «Образец надстройки XLL»), и ни одна из функций в нем недоступна.
Исходный код надстройки взят из книги. Помимо кода также предоставляется файл XLL, скомпилированный из того же исходного кода, который отлично работает как надстройка.
Может кто-нибудь указать, что мне не хватает?
Постскриптум Я нахожусь на Windows7 (x64) с Office 2013 (32-разрядная версия) и использую Excel 2013 XLL SDK. Я использую компилятор VC 15.2.
P.S.S. Я заметил, что есть пара моментов, которые могут иметь или не иметь отношение к делу:
Это исходный код:
xllSample.cpp
#include <windows.h>
#include "xlcall.h"
#ifdef __cplusplus
#define EXPORT extern "C" __declspec(dllexport)
#else
#define EXPORT __declspec(dllexport)
#endif
#define NUM_FUNCTIONS 3 // number of functions in the table
#define NUM_REGISTER_ARGS 11 // number of register arguments for each function
#define MAX_LENGTH 255 // maximum allowable string length for a register argument
static char gszFunctionTable[NUM_FUNCTIONS][NUM_REGISTER_ARGS][MAX_LENGTH] =
{
{" AddTwo", // procedure
" BBB", // type_text
" AddTwo", // function_text
" d1, d2", // argument_text
" 1", // macro_type
" Sample Add-In", // category
" ", // shortcut_text
" ", // help_topic
" Adds the two arguments.", // function_help
" The first number to add.", // argument_help1
" The second number to add." // argument_help2
},
{" MultiplyTwo",
" BBB",
" MultiplyTwo",
" d1, d2",
" 1",
" Sample Add-In",
" ",
" ",
" Multiplies the two arguments.",
" The first number to multiply.",
" The second number to multiply."},
{" IFERROR",
" RRR",
" IFERROR",
" ToEvaluate, Default",
" 1",
" Sample Add-In",
" ",
" ",
" If the first argument is an error value, the second ""argument is returned. Otherwise the first argument ""is returned.",
" The argument to be checked for an error condition.",
" The value to return if the first argument is an error."}
};
void HandleRegistration(BOOL);
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved) {
return TRUE;
}
EXPORT int WINAPI xlAutoOpen(void) {
static XLOPER xDLL;
int i, j;
for(i = 0; i < NUM_FUNCTIONS; ++i)
for(j = 0; j < NUM_REGISTER_ARGS; ++j)
gszFunctionTable[i][j][0] =
(BYTE)strlen(gszFunctionTable[i][j] + 1);
HandleRegistration(TRUE);
return 1;
}
EXPORT int WINAPI xlAutoClose(void) {
HandleRegistration(FALSE);
return 1;
}
EXPORT LPXLOPER WINAPI xlAddInManagerInfo(LPXLOPER xlAction) {
static XLOPER xlReturn, xlLongName, xlTemp;
xlTemp.xltype = xltypeInt;
xlTemp.val.w = xltypeInt;
Excel4(xlCoerce, &xlReturn, 2, xlAction, &xlTemp);
if(1 == xlReturn.val.w) {
xlLongName.xltype = xltypeStr;
xlLongName.val.str = "\021Sample XLL Add-In";
} else {
xlLongName.xltype = xltypeErr;
xlLongName.val.err = xlerrValue;
}
return &xlLongName;
}
static void HandleRegistration(BOOL bRegister) {
XLOPER xlXLLName, xlRegID, xlRegArgs[NUM_REGISTER_ARGS];
int i, j;
Excel4(xlGetName, &xlXLLName, 0);
for(i = 0; i < NUM_REGISTER_ARGS; ++i)
xlRegArgs[i].xltype = xltypeStr;
for(i = 0; i < NUM_FUNCTIONS; ++i) {
for(j = 0; j < NUM_REGISTER_ARGS; ++j)
xlRegArgs[j].val.str = gszFunctionTable[i][j];
if(TRUE == bRegister) {
Excel4(xlfRegister, 0, NUM_REGISTER_ARGS + 1,
&xlXLLName,
&xlRegArgs[0], &xlRegArgs[1], &xlRegArgs[2],
&xlRegArgs[3], &xlRegArgs[4], &xlRegArgs[5],
&xlRegArgs[6], &xlRegArgs[7], &xlRegArgs[8],
&xlRegArgs[9], &xlRegArgs[10]);
} else {
xlRegArgs[4].val.str = "\0010";
Excel4(xlfRegister, 0, NUM_REGISTER_ARGS + 1,
&xlXLLName,
&xlRegArgs[0], &xlRegArgs[1], &xlRegArgs[2],
&xlRegArgs[3], &xlRegArgs[4], &xlRegArgs[5],
&xlRegArgs[6], &xlRegArgs[7], &xlRegArgs[8],
&xlRegArgs[9], &xlRegArgs[10]);
Excel4(xlfRegisterId, &xlRegID, 2, &xlXLLName,
&xlRegArgs[0]);
Excel4(xlfUnregister, 0, 1, &xlRegID);
}
}
Excel4(xlFree, 0, 1, &xlXLLName);
}EXPORT double WINAPI AddTwo(double d1, double d2) {
return d1 + d2;
}EXPORT double WINAPI MultiplyTwo(double d1, double d2) {
return d1 * d2;
}
EXPORT LPXLOPER IFERROR(LPXLOPER ToEvaluate, LPXLOPER Default) {
int IsError = 0;
XLOPER xlResult;
static XLOPER xlBadArgErr;
xlBadArgErr.xltype = xltypeErr;
xlBadArgErr.val.err = xlerrValue;
if((xltypeMissing == ToEvaluate->xltype) ||
(xltypeMissing == Default->xltype))
return &xlBadArgErr;
switch(ToEvaluate->xltype) {
case xltypeNum:
case xltypeStr:
case xltypeBool:
case xltypeInt:
break;
case xltypeSRef:
case xltypeRef:
if(xlretUncalced == Excel4(xlCoerce, &xlResult, 1, ToEvaluate))
return 0;
else {
if(xltypeMulti == xlResult.xltype)
return &xlBadArgErr;
else if(xltypeErr == xlResult.xltype)
IsError = 1;
}
Excel4(xlFree, 0, 1, &xlResult);
break;
case xltypeMulti:
return &xlBadArgErr;
break;
case xltypeErr:
IsError = 1;
break;
default:
return &xlBadArgErr;
break;
}
if(IsError)
return Default;
else
return ToEvaluate;
}
Задача ещё не решена.
Других решений пока нет …