Freigeben über


Aufrufen von XLL-Funktionen über den Funktions-Assistenten oder Ersetzen von Dialogfeldern

Gilt für: Excel 2013 | Office 2013 | Visual Studio

Microsoft Excel ruft in der Regel XLL-Funktionen während der normalen Neuberechnung der Arbeitsmappe oder einen Teil davon auf, wenn die Berechnung von einem Makro gesteuert wird. Denken Sie daran, dass sich die Funktion möglicherweise nicht in einer Zellformel befindet, sondern Teil einer benannten Bereichsdefinition oder eines Ausdrucks für bedingte Formatierung ist.

Es gibt zwei Umstände, unter denen eine Funktion aus einem Excel-Dialogfeld aufgerufen werden kann. Eine ist das Dialogfeld Funktionsargumente einfügen , in dem Benutzer jeweils ein Argument für einen Funktionsaufruf erstellen können. Die andere ist, wenn Formeln geändert und von Excel im Dialogfeld Ersetzen erneut angezeigt werden. Im Dialogfeld Funktionsargumente einfügen soll die Funktion möglicherweise nicht normal ausgeführt werden. Dies kann daran zurückzuführen sein, dass die Ausführung sehr lange dauert und Sie die Verwendung des Dialogfelds nicht verlangsamen möchten.

Sowohl das Dialogfeld Funktion einfügen als auch das Dialogfeld Ersetzen weisen den Windows-Klassennamen bosa_sdm_XLn auf, wobei n eine Zahl ist. Windows stellt die API-Funktion GetClassName bereit, die diesen Namen von einem Windows-Handle abruft, einem HWND-Variablentyp. Es stellt auch eine weitere Funktion, EnumWindows, bereit, die eine bereitgestellte Rückruffunktion (innerhalb Ihrer DLL) einmal für jedes aktuell geöffnete Fenster der obersten Ebene aufruft.

Die Rückruffunktion muss nur die folgenden Schritte ausführen:

  1. Überprüfen Sie, ob das übergeordnete Element dieses Fensters der aktuelle instance von Excel ist (falls mehrere Instanzen ausgeführt werden).

  2. Rufen Sie den Klassennamen aus dem von Windows übergebenen Handle ab.

  3. Überprüfen Sie, ob der Klassenname das Format bosa_sdm_XLn hat.

  4. Wenn Sie zwischen den beiden Dialogfeldern unterscheiden müssen, überprüfen Sie, ob der Titel des Dialogfelds identifizierenden Text enthält. Der Fenstertitel wird mithilfe des Windows-API-Aufrufs GetWindowText abgerufen.

Der folgende C++-Code zeigt eine Klasse und einen Rückruf, der an Windows übergeben werden soll, der diese Schritte ausführt. Dies wird von den Funktionen aufgerufen, die test speziell für eines der betreffenden Dialogfelder aufrufen.

Hinweis

Fenstertitel zukünftiger Excel-Versionen können diesen Code ändern und für ungültig erklären. Beachten Sie auch, dass das Festlegen window_title_text auf NULL bewirkt, dass der Fenstertitel in der Rückrufsuche ignoriert wird.

#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.
}

Das Dialogfeld Funktion einfügen hat keinen Titel, daher übergibt die folgende Funktion die Suchtitelzeichenfolge "", d. h. eine leere Zeichenfolge, an den Rückruf, um anzugeben, dass die Übereinstimmungsbedingung ist, dass das Fenster keinen Titel haben soll.

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;
}

Siehe auch

Zugreifen auf XLL-Code in Excel

Aufrufen von Excel von der DLL oder XLL aus

Entwickeln von XLLs für Excel