Compartilhar via


Chamar Funções XLL do Assistente de Função ou Substituir Caixas de Diálogo

Aplica-se a: Excel 2013 | Office 2013 | Visual Studio

O Microsoft Excel geralmente chama funções XLL durante o recálculo normal da pasta de trabalho ou uma parte dela se o cálculo estiver sob o controle de uma macro. Lembre-se de que a função pode não residir em uma fórmula de célula, mas pode fazer parte de uma definição de intervalo nomeada ou de uma expressão de formatação condicional.

Há duas circunstâncias em que uma função pode ser chamada de uma caixa de diálogo do Excel. Uma delas é a caixa de diálogo Colar Argumentos de Função , em que os usuários são capazes de construir um argumento de chamada de função um por vez. A outra é quando as fórmulas estão sendo modificadas e reentradas pelo Excel na caixa de diálogo Substituir . Para a caixa de diálogo Colar Argumentos de Função , talvez você não queira que sua função seja executada normalmente. Isso pode ser porque leva muito tempo para ser executado e você não deseja retardar o uso da caixa de diálogo.

A caixa de diálogo Função colar e a caixa de diálogo Substituir têm o nome da classe windows bosa_sdm_XLn, em que n é um número. O Windows fornece uma função de API, GetClassName, que obtém esse nome de um identificador do Windows, um tipo de variável HWND. Ele também fornece outra função, EnumWindows, que chama uma função de retorno de chamada fornecida (dentro de sua DLL) uma vez para cada janela de nível superior que está aberta no momento.

A função de retorno de chamada precisa executar apenas as seguintes etapas:

  1. Verifique se o pai dessa janela é a instância atual do Excel (caso haja várias instâncias em execução).

  2. Obtenha o nome da classe do identificador passado pelo Windows.

  3. Verifique se o nome da classe é do formulário bosa_sdm_XLn.

  4. Se você precisar distinguir entre as duas caixas de diálogo, marcar se o título da caixa de diálogo contiver algum texto de identificação. O título da janela é obtido usando a chamada de API do Windows GetWindowText.

O código C++ a seguir mostra uma classe e um retorno de chamada a serem passados para o Windows que executa essas etapas. Isso é chamado pelas funções que chamam de teste especificamente para qualquer uma das caixas de diálogo em questão.

Observação

Títulos de janela de versões futuras do Excel podem alterar e invalidar esse código. Observe também que a configuração window_title_text para NULL tem o efeito de ignorar o título da janela na pesquisa de retorno de chamada.

#define CLASS_NAME_BUFFSIZE  50
#define WINDOW_TEXT_BUFFSIZE  50
// Data structure used as input to xldlg_enum_proc(), called by
// called_from_paste_fn_dlg(), called_from_replace_dlg(), and
// called_from_Excel_dlg(). These functions tell the caller whether
// the current worksheet function was called from one or either of
// these dialog boxes.
typedef struct
{
  bool is_dlg;
  short low_hwnd;
  char *window_title_text; // set to NULL if don't care
}
  xldlg_enum_struct;
// The callback function called by Windows for every top-level window.
BOOL CALLBACK xldlg_enum_proc(HWND hwnd, xldlg_enum_struct *p_enum)
{
// Check if the parent window is Excel.
// Note: Because of the change from MDI (Excel 2010)
// to SDI (Excel 2013), comment out this step in Excel 2013.
  if(LOWORD((DWORD)GetParent(hwnd)) != p_enum->low_hwnd)
    return TRUE; // keep iterating
  char class_name[CLASS_NAME_BUFFSIZE + 1];
//  Ensure that class_name is always null terminated for safety.
  class_name[CLASS_NAME_BUFFSIZE] = 0;
  GetClassName(hwnd, class_name, CLASS_NAME_BUFFSIZE);
//  Do a case-insensitve comparison for the Excel dialog window
//  class name with the Excel version number truncated.
  size_t len; // The length of the window's title text
  if(_strnicmp(class_name, "bosa_sdm_xl", 11) == 0)
  {
// Check if a searching for a specific title string
    if(p_enum->window_title_text) 
    {
// Get the window's title and see if it matches the given text.
      char buffer[WINDOW_TEXT_BUFFSIZE + 1];
      buffer[WINDOW_TEXT_BUFFSIZE] = 0;
      len = GetWindowText(hwnd, buffer, WINDOW_TEXT_BUFFSIZE);
      if(len == 0) // No title
      {
        if(p_enum->window_title_text[0] != 0)
          return TRUE; // No match, so keep iterating
      }
// Window has a title so do a case-insensitive comparison of the
// title and the search text, if provided.
      else if(p_enum->window_title_text[0] != 0
      && _stricmp(buffer, p_enum->window_title_text) != 0)
        return TRUE; // Keep iterating
    }
    p_enum->is_dlg = true;
    return FALSE; // Tells Windows to stop iterating.
  }
  return TRUE; // Tells Windows to continue iterating.
}

A caixa de diálogo Função colar não tem um título, portanto, a função a seguir passa uma cadeia de caracteres de título de pesquisa de "", ou seja, uma cadeia de caracteres vazia, para o retorno de chamada para indicar que a condição de correspondência é que a janela não deve ter um título.

bool called_from_paste_fn_dlg(void)
{
    XLOPER xHwnd;
// Calls Excel4, which only returns the low part of the Excel
// main window handle. This is OK for the search however.
    if(Excel4(xlGetHwnd, &xHwnd, 0))
        return false; // Couldn't get it, so assume not
// Search for bosa_sdm_xl* dialog box with no title string.
    xldlg_enum_struct es = {FALSE, xHwnd.val.w, ""};
    EnumWindows((WNDENUMPROC)xldlg_enum_proc, (LPARAM)&es);
    return es.is_dlg;
}

Confira também

Acessar o código de XLL no Excel

Calling into Excel from the DLL or XLL

Desenvolvimento de XLLs do Excel