Chamar funções definidas pelo usuário a partir de DLLs
Aplica-se a: Excel 2013 | Office 2013 | Visual Studio
Chamar UDFs (funções definidas pelo usuário) de uma planilha é tão simples quanto chamar funções internas: você insere a função por meio de uma fórmula de célula. No entanto, na API C, não há códigos de função pré-definidos a serem usados com os retornos de chamada. Para permitir que você chame UDFs, a API C exporta uma função somente XLL, a função xlUDF . O primeiro argumento da função é o nome da função como uma cadeia de caracteres e os argumentos subsequentes são aqueles que a UDF normalmente esperaria.
Você pode obter uma lista das funções e comandos de suplemento XLL registrados no momento usando a função xlfGetWorkspace com o argumento 44. Isso retorna uma matriz de três colunas em que as colunas representam o seguinte:
O caminho completo e o nome da XLL
O nome do UDF ou comando conforme exportado da XLL
A cadeia de caracteres de código de retorno e argumento
Observação
O nome exportado da XLL pode não ser o mesmo que o nome registrado pelo qual o Excel conhece a UDF ou o comando.
A partir do Excel 2007, as funções ATP (Analysis Toolpak) são totalmente integradas e a API C tem suas próprias enumerações para funções como PRICE, xlfPrice. Em versões anteriores, você precisava usar xlUDF para chamar essas funções. Se o suplemento precisar trabalhar com o Excel 2003 e o Excel 2007 ou versões posteriores, e ele usar essas funções, você deverá detectar a versão atual e chamar a função da maneira apropriada.
Exemplos
O exemplo a seguir mostra a função xlUDF sendo usada para chamar a função ATP PRICE quando a versão em execução do Excel for 2003 ou anterior. Para obter informações sobre a configuração de uma variável de versão global, como gExcelVersion12plus neste exemplo, consulte Retrocompatibilidade.
Observação
Este exemplo usa as funções Framework TempNum, TempStrConst para configurar os argumentos e o Excel para chamar a API C.
LPXLOPER TempNum(double d);
LPXLOPER TempStrConst(const LPSTR lpstr);
int cdecl Excel(int xlfn, LPXLOPER pxResult, int count, ...);
double call_ATP_example(void)
{
XLOPER xPrice;
int xl_ret_val;
if(gExcelVersion12plus) // Starting in Excel 2007
{
xl_ret_val = Excel(xlfPrice, &xPrice, 7,
TempNum(39084.0), // settlement date 2-Jan-2007
TempNum(46706.0), // maturity date 15-Nov-2027
TempNum(0.04), // Coupon
TempNum(0.05), // Yield
TempNum(1.0), // redemption value: 100% of face
TempNum(1.0), // Annual coupons
TempNum(1.0)); // Rate basis Act/Act
}
else // Excel 2003-
{
xl_ret_val = Excel(xlUDF, &xPrice, 8,
TempStrConst("PRICE"),
TempNum(39084.0), // settlement date 2-Jan-2007
TempNum(46706.0), // maturity date 15-Nov-2027
TempNum(0.04), // Coupon
TempNum(0.05), // Yield
TempNum(1.0), // redepmtion value: 100% of face
TempNum(1.0), // Annual coupons
TempNum(1.0)); // Rate basis Act/Act
}
if(xl_ret_val != xlretSuccess || xPrice.xltype != xltypeNum)
{
// Even though PRICE is not expected to return a string, there
// is no harm in freeing the XLOPER to be safe
Excel(xlFree, 0, 1, &xPrice);
return -1.0; // an error value
}
return xPrice.val.num;
}
Quando você está chamando uma função XLL que retorna um valor modificando um argumento em vigor, a função xlUDF ainda retorna o valor por meio do endereço do resultado XLOPER/XLOPER12. Em outras palavras, o resultado é retornado como se fosse por meio de uma instrução de retorno normal. O XLOPER/XLOPER12 que corresponde ao argumento usado para o valor retornado não é modificado. Por exemplo, considere os dois UDFs a seguir.
// Registered as "1E". Returns its argument incremented by 1.
void WINAPI UDF_1(double *pArg)
{
*pArg += 1.0;
}
// Registered as "QQ". Returns its argument unmodified
// unless it is a number, in which case it increments it
// by calling UDF_1.
LPXLOPER12 WINAPI UDF_2(LPXLOPER12 pxArg)
{
static XLOPER12 xRetVal; // Not thread-safe
XLOPER12 xFn;
xFn.xltype = xltypeStr;
xFn.val.str = L"\005UDF_1";
Excel12(xlUDF, &xRetVal, 2, &xFn, pxArg);
xRetVal.xltype |= xlbitXLFree;
return &xRetVal;
}
Quando UDF_2 chama UDF_1, o valor de pxArg fica inalterado após a chamada para o Excel12 e o valor retornado por UDF_1 está contido em xRetVal.
Ao fazer um grande número de chamadas para uma UDF dessa forma, você pode avaliar o nome da função primeiro usando a função xlfEvaluate. O número resultante, que é o mesmo que a ID de registro retornada pela função xlfRegister , pode ser passado no lugar do nome da função como o primeiro argumento para a função xlUDF . Isso permite que o Excel localize e chame a função mais rapidamente do que se precisar pesquisar o nome da função sempre.