Compartilhar via


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.

Confira também