Excel XLL SDK

You can use the Microsoft Excel XLL Software Development Kit and the C API to create high-performance worksheet functions.
The C API is based on the Excel 4 macro language (XLM).
You can use the SDK to create DLLs that can integrate directly into Excel.
These DLLs have the file extension ".xll".
These DLLs provide the most direct and fastest interface for the addition of high-performance user defined functions.

link - learn.microsoft.com/en-us/office/client-developer/excel/developing-dlls 
link - learn.microsoft.com/en-us/office/client-developer/excel/excel-xll-sdk-api-function-reference
link - learn.microsoft.com/en-us/previous-versions/office/developer/office-2007/aa730920(v=office.12)
link - stackoverflow.com/questions/tagged/xll?tab=Newest

Versions

There have been four versions of the SDK.
Excel 2013 - (Excel 15) Latest Version
Excel 2010 - (Excel 14 or 10.0) no longer available for download.
Excel 2007 - (Excel 12 or 8.1) no longer available for download.
Excel 1997 - (Excel or 8.0) no longer available for download.


Download

The Microsoft Excel 2013 XLL SDK contains source files for three projects.
A Framework library that is designed to speed up the writing of XLLs, and two sample projects, Example and Generic.

link - microsoft.com/en-us/download/details.aspx?id=35567 

SAMPLES\FRAMEWRK\ - Contains a project that can be built to a library, FRAMEWRK.lib, which can then be linked into other XLL projects.
This library contains a number of tools for writing XLLs easier and is used in both of the other projects in conjunction with the header file FRAMEWRK.h.
The FRAMEWRK.H it contains C wrappers for useful helper functions.
SAMPLES\EXAMPLE\ - Contains a project that can be built to an XLL, EXAMPLE.xll.
The XLL contains many examples of the use of the Framework library, and example implementations of the XLL add-in interface functions such as xlAutoOpen.
SAMPLES\GENERIC\ - Contains a project that can be built to an XLL, GENERIC.xll.
The XLL demonstrates several example functions and commands and is a good starting point for writing your own XLLs.


EXAMPLE.C

link - learn.microsoft.com/en-us/office/client-developer/excel/functions-in-the-framework-library 

The original file contains code to register 29 functions.
These functions are all registered (in xlAutoOpen) when you open the XLL. Before every string, leave a space for the byte count.
The format of this table is the same as the last seven arguments to the REGISTER function.
rgFuncsRows define the number of rows in the table. The dimension [3] represents the number of columns in the table.

*********************************************************** 
** add the headers **
***********************************************************

#define rgFuncsRows 29
static LPWSTR rgFuncs[rgFuncsRows][7] = {
   {L"CallerExample", L"I", L"CallerExample"},
   {L"debugPrintfExample", L"I", L"debugPrintfExample"},
   {L"EvaluateExample", L"I", L"EvaluateExample"},
   {L"Excel12fExample", L"I", L"Excel12fExample"},
   {L"Excel12Example", L"I", L"Excel12Example"},
   {L"InitFrameworkExample", L"I", L"InitFrameworkExample"},
   {L"TempActiveCellExample", L"I", L"TempActiveCellExample"},
   {L"TempActiveColumnExample", L"I", L"TempActiveColumnExample"},
   {L"TempActiveRefExample", L"I", L"TempActiveRefExample"},
   {L"TempActiveRowExample", L"I", L"TempActiveRowExample"},
   {L"TempBoolExample", L"I", L"TempBoolExample"},
   {L"TempErrExample", L"P", L"TempErrExample"},
   {L"TempIntExample", L"I", L"TempIntExample"},
   {L"TempMissingExample", L"I", L"TempMissingExample"},
   {L"TempNumExample", L"I", L"TempNumExample"},
   {L"TempStrExample", L"I", L"TempStrExample"},
   {L"fArray", L"Q", L"fArray"},
   {L"xlCoerceExample", L"II",L"xlCoerceExample"},
   {L"xlFreeExample", L"I", L"xlFreeExample"},
   {L"xlGetInstExample", L"I", L"xlGetInstExample"},
   {L"xlGetInstPtrExample", L"I", L"xlGetInstPtrExample"},
   {L"xlGetNameExample", L"I", L"xlGetNameExample"},
   {L"xlSetExample", L"II",L"xlSetExample"},
   {L"xlSheetIdExample", L"I", L"xlSheetIdExample"},
   {L"xlSheetNmExample", L"I", L"xlSheetNmExample"},
   {L"xlStackExample", L"I", L"xlStackExample"},
   {L"xlUDFExample", L"I", L"xlUDFExample"},
   {L"InternationalExample", L"I", L"InternationalExample"},
   {L"CalcCircum", L"BB", L"CalcCircum"}
}

DllMain

This function is called by LibEntry which is called by Windows when the DLL is first loaded. LibEntry initializes the DLL's heap if a HEAPSIZE is specified in the DLL's .DEF file, and then calls DllMain. The following DllMain function satisfies that call. The DllMain function should perform additional initialization tasks required by the DLL. In this example, we byte-count all the strings in the preceding table. DllMain will be called will be called once per process. In Win32 DllMain replaces both the LibMain and WEP functions.
Returns 1 if initialization is successful.
In the following for loops, the strings in rgFuncs[] are byte-counted so that they won't need to be byte-counted later.

BOOL WINAPI DllMain(HANDLE hInstance, ULONG ul_reason_for_call, 
   LPVOID lpReserved)
{

   /*if(ul_reason_for_call == DLL_PROCESS_ATTACH)
   {
   int i,j;

   for (i = 0; i < rgFuncsRows; i++)
   {
   for (j = 0; j < 7; j++)
   {
   rgFuncs[i][j][0] = (BYTE)lstrlen (rgFuncs[i][j]+1);
   }
   }
   }*/

   return 1;
}

xlAutoOpen

This function is called by Microsoft Excel when the XLL file is loaded.
This is also called by the Add-in Manager when you add this XLL as an add-in. The Add-in Manager first calls xlAutoAdd, then calls REGISTER("EXAMPLE.XLL"), which in turn calls xlAutoOpen.
This should register all the functions you want to make available
It return 1 if successful, or return 0 if your XLL cannot be opened.

__declspec(dllexport) int WINAPI xlAutoOpen(void) 
{
   static XLOPER12 xDLL;
   int i;

   Excel12f(xlGetName, &xDLL, 0);

   for (i=0;i<rgFuncsRows;i++)
   {
      Excel12f(xlfRegister, 0, 4,
         (LPXLOPER12)&xDLL,
         (LPXLOPER12)TempStr12(rgFuncs[i][0]),
         (LPXLOPER12)TempStr12(rgFuncs[i][1]),
         (LPXLOPER12)TempStr12(rgFuncs[i][2]));
   }

   /* Free the XLL filename */
   Excel12f(xlFree, 0, 1, (LPXLOPER12)&xDLL);

   return 1;
}

xlAutoClose

This function is called by Microsoft Excel when the XLL file is unloaded.
The Add-in Manager first calls xlAutoRemove, then calls UNREGISTER("EXAMPLE.XLL"), which in turn calls xlAutoClose.
This function does not have to unregister the functions that were registered in xlAutoOpen. This is done automatically by Excel.
This function should return 1.

__declspec(dllexport) int WINAPI xlAutoClose(void) 
{
   int i;

   for (i = 0; i < rgFuncsRows; i++)
   {
      Excel12f(xlfSetName, 0, 1, TempStr12(rgFuncs[i][2]));
   }
   return 1;
}

lpwstricmp

Compares a pascal string and a null-terminated C-string to see if they are equal. Method is case insensitive
Unlike the usual string functions, lpwstricmp doesn't care about collating sequence.
This function returns 0 if they are equal and nonzero otherwise
LPWSTR s First string (null-terminated)
LPWSTR t Second string (byte counted)

int lpwstricmp(LPWSTR s, LPWSTR t) 
{
   int i;

   if (wcslen(s) != *t)
   {
      return 1;
   }

   for (i = 1; i <= s[0]; i++)
   {
      if (towlower(s[i-1]) != towlower(t[i]))
      {
         return 1;
      }
   }
   return 0;
}

xlAutoRegister

This function is called by Microsoft Excel if a macro sheet tries to register a function without specifying the type_text argument.
If that happens, Microsoft Excel calls xlAutoRegister, passing the name of the function that the user tried to register. xlAutoRegister should use the normal REGISTER function to register the function, but this time it must specify the type_text argument.
If xlAutoRegister does not recognize the function name, it should return a #VALUE! error. Otherwise, it should return whatever REGISTER returned.
LPXLOPER12 pxName xltypeStr containing the name of the function to be registered. This is not case sensitive, because Microsoft Excel uses Pascal calling convention.
This function returns LPXLOPER12 xltypeNum containing the result of registering the function, or xltypeErr containing #VALUE! if the function could not be registered.

__declspec(dllexport) LPXLOPER12 WINAPI xlAutoRegister12(LPXLOPER12 pxName) 
{
   static XLOPER12 xDLL, xRegId;
   int i;

   xRegId.xltype = xltypeErr;
   xRegId.val.err = xlerrValue;

   for (i = 0; i < rgFuncsRows; i++)
   {
      if (!lpwstricmp(rgFuncs[i][0], pxName->val.str))
      {
         Excel12f(xlGetName, &xDLL, 0);

         Excel12f(xlfRegister, 0, 4,
         (LPXLOPER12)&xDLL,
         (LPXLOPER12)TempStr12(rgFuncs[i][0]),
         (LPXLOPER12)TempStr12(rgFuncs[i][1]),
         (LPXLOPER12)TempStr12(rgFuncs[i][2]));

         /* Free the XLL filename */
         Excel12f(xlFree, 0, 1, (LPXLOPER12)&xDLL);

         return (LPXLOPER12)&xRegId;
      }
   }

   //Word of caution - returning static XLOPERs/XLOPER12s is not thread safe
   //for UDFs declared as thread safe, use alternate memory allocation mechanisms

   return (LPXLOPER12)&xRegId;
}

xlAutoAdd

This function is called by the Add-in Manager only. When you add a DLL to the list of active add-ins, the Add-in Manager calls xlAutoAdd() and then opens the XLL, which in turn calls xlAutoOpen.

__declspec(dllexport) int WINAPI xlAutoAdd(void) 
{
   XCHAR szBuf[255];

   wsprintfW((LPWSTR)szBuf, L"Thank you for adding Example.XLL\n build date %hs, time %hs",__DATE__, __TIME__);

   /* Display a dialog box indicating that the XLL was successfully added */
   Excel12f(xlcAlert, 0, 2, TempStr12(szBuf), TempInt12(2));
   return 1;
}

xlAutoRemove

This function is called by the Add-in Manager only. When you remove an XLL from the list of active add-ins, the Add-in Manager calls xlAutoRemove() and then UNREGISTER("EXAMPLE.XLL").
You can use this function to perform any special tasks that need to be performed when you remove the XLL from the Add-in Manager's list of active add-ins.
For example, you may want to delete an initialization file when the XLL is removed from the list.
This function display a dialog box indicating that the XLL was successfully removed */

__declspec(dllexport) int WINAPI xlAutoRemove(void) 
{
   Excel12f(xlcAlert, 0, 2, TempStr12(L"Thank you for removing Example.XLL!"), TempInt12(2));
   return 1;
}

xlAddInManagerInfo12

This function is called by the Add-in Manager to find the long name of the add-in.
If xAction = 1, this function should return a string containing the long name of this XLL, which the Add-in Manager will use to describe this XLL.
If xAction = 2 or 3, this function should return an error.

__declspec(dllexport) LPXLOPER12 WINAPI xlAddInManagerInfo12(LPXLOPER12 xAction) 
{
   static XLOPER12 xInfo, xIntAction;

   Excel12f(xlCoerce, &xIntAction, 2, xAction, TempInt12(xltypeInt));

   if(xIntAction.val.w == 1)
   {
      xInfo.xltype = xltypeStr;
      xInfo.val.str = L"\026Example Standalone DLL";
   }
   else
   {
      xInfo.xltype = xltypeErr;
      xInfo.val.err = xlerrValue;
   }

   //Returning static XLOPERs/XLOPER12s is not thread safe
   //For UDFs declared as thread safe, use alternate memory allocation mechanisms

   return (LPXLOPER12)&xInfo;
}

CallerExample

This function illustrates the xlfCaller function, which selects the cell from which it was called.

__declspec(dllexport) short WINAPI CallerExample(void) 
{
   XLOPER12 xRes;

   Excel12(xlfCaller, &xRes, 0);
   Excel12(xlcSelect, 0, 1, (LPXLOPER12)&xRes);
   Excel12(xlFree, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

debugPrintfExample

This function prints a string to show that control was passed to the function.
The _DEBUG flag must be defined before compiling or else this function does nothing.

__declspec(dllexport) short WINAPI debugPrintfExample(void) 
{

   #ifdef _DEBUG
   debugPrintf("Made it!\r");
   #endif

   return 1;
}

EvaluateExample

This function demonstrates using evaluate to look up a cell reference.
It uses xlfEvaluate to coerce the text "!B38" to the contents of cell B38.

__declspec(dllexport) short WINAPI EvaluateExample(void) 
{
   XLOPER12 xFormulaText, xRes, xRes2, xInt;

   xFormulaText.xltype = xltypeStr;
   xFormulaText.val.str = L"\004!B38";
   Excel12(xlfEvaluate, &xRes, 1, (LPXLOPER12)&xFormulaText);

   xInt.xltype = xltypeInt;
   xInt.val.w = 2;
   Excel12(xlcAlert, &xRes2, 2, (LPXLOPER12)&xRes, (LPXLOPER12)&xInt);
   Excel12(xlFree, 0, 1, (LPXLOPER12)&xRes);
   Excel12(xlFree, 0, 1, (LPXLOPER12)&xRes2);

   return 1;
}

Excel12fExample

This function demonstrates the debugging capability of Excel12f().
It passes a bad argument to the Excel12f() function, which outputs a debug message on the terminal attached to COM1.

__declspec(dllexport) short WINAPI Excel12fExample(void) 
{
   Excel12f(xlcDisplay, 0, 1, 0);
   return 1;
}

Excel12Example

This function illustrates the Excel12() function. It uses Excel12() to select the cell from which it was called.

__declspec(dllexport) short WINAPI Excel12Example(void) 
{
   XLOPER12 xRes;

   Excel12(xlfCaller, &xRes, 0);
   Excel12(xlcSelect, 0, 1, (LPXLOPER12)&xRes);
   Excel12(xlFree, 0, 1, (LPXLOPER12)&xRes);

   return 1;
}

InitFrameworkExample

This function uses InitFramework() to free all temporary memory.

__declspec(dllexport) short WINAPI InitFrameworkExample(void) 
{
   InitFramework();
   return 1;
}

TempActiveCellExample

This function uses TempActiveCell() to display the contents of cell B94 on the active sheet.

__declspec(dllexport) short WINAPI TempActiveCellExample(void) 
{
   Excel12f(xlcAlert, 0, 1, TempActiveCell12(93,1));
   return 1;
}

TempActiveColumnExample

This function uses TempActiveColumn() to select an entire column.

__declspec(dllexport) short WINAPI TempActiveColumnExample(void) 
{
   Excel12f(xlcSelect, 0, 1, TempActiveColumn12(1));
   return 1;
}

TempActiveRefExample

This function uses TempActiveRef() to select A105:C110.

__declspec(dllexport) short WINAPI TempActiveRefExample(void) 
{
   Excel12f(xlcSelect, 0, 1, TempActiveRef12(104, 109, 0, 2));
   return 1;
}

TempActiveRowExample

This function uses TempActiveRow() to select an entire row.

__declspec(dllexport) short WINAPI TempActiveRowExample(void) 
{
   Excel12f(xlcSelect, 0, 1, TempActiveRow12(112));
   return 1;
}

TempBoolExample

This function uses TempBool to clear the status bar. Temporary memory is freed when Excel12f() is called.

__declspec(dllexport) short WINAPI TempBoolExample(void) 
{
   Excel12f(xlcMessage, 0, 1, TempBool12(0));
   return 1;
}

TempErrExample

This function uses TempErr to return a #VALUE! error to Microsoft Excel.
This function can cause a memory leak as temp memory allocated by TempErr12 may never be freed.

__declspec(dllexport) LPXLOPER12 WINAPI TempErrExample(void) 
{
   return TempErr12(xlerrValue);
}

TempIntExample

This function uses TempInt() to pass an argument to xlfGetWorkspace.

__declspec(dllexport) short WINAPI TempIntExample(void) 
{
   XLOPER12 xRes;

   Excel12f(xlfGetWorkspace, &xRes, 1, TempInt12(44));
   Excel12f(xlFree, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

TempMissingExample

This example uses TempMissing12 to provide 3 missing arguments to xlcWorkspace followed by a Boolean FALSE to suppress the display of worksheet scroll-bars.
The first 3 arguments correspond to other workspace settings which are unaffected.

__declspec(dllexport) short WINAPI TempMissingExample(void) 
{
   XLOPER12 xBool;

   xBool.xltype = xltypeBool;
   xBool.val.xbool = 0;
   Excel12f(xlcWorkspace, 0, 4, TempMissing12(), TempMissing12(),
   TempMissing12(), (LPXLOPER12)&xBool);
   return 1;
}

TempNumExample

This function uses TempNum() to pass an argument to GET.WORKSPACE.

__declspec(dllexport) short WINAPI TempNumExample(void) 
{
   XLOPER12 xRes;

   Excel12f(xlfGetWorkspace, &xRes, 1, TempNum12(44));
   Excel12f(xlFree, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

TempStrExample

This function uses TempStrConst() to create a string for an alert message box.

__declspec(dllexport) short WINAPI TempStrExample(void) 
{
   Excel12f(xlcAlert, 0, 1, TempStr12(L"Made it!"));
   return 1;
}

fArray

This example consists of two routines: fArray and xlAutoFree().
This function creates an xltypeMulti containing eight values. It returns this array to Microsoft Excel with the xlbitDLLFree bit set.
When Microsoft Excel is done with the values, it calls xlAutoFree(), which frees the memory that fArray() allocated.

HANDLE hArray; 

__declspec(dllexport) LPXLOPER12 WINAPI fArray(void)
{
   LPXLOPER12 pxArray;
   static XLOPER12 xMulti;
   int i;
   int rwcol;

   xMulti.xltype = xltypeMulti | xlbitDLLFree;
   xMulti.val.array.columns = 1;
   xMulti.val.array.rows = 8;

   //For large values of rows and columns, this would overflow
   //use __int64 in that case and return an error if rwcol
   //contains a number that won't fit in sizeof(int) bytes

   rwcol = xMulti.val.array.columns * xMulti.val.array.rows;

   pxArray = (LPXLOPER12)GlobalLock(hArray = GlobalAlloc(GMEM_ZEROINIT, rwcol * sizeof(XLOPER12)));

   xMulti.val.array.lparray = pxArray;

   for(i = 0; i < rwcol; i++)
   {
      pxArray[i].xltype = xltypeInt;
      pxArray[i].val.w = i;
   }

   //Word of caution - returning static XLOPERs/XLOPER12s is not thread safe
   //for UDFs declared as thread safe, use alternate memory allocation mechanisms

   return (LPXLOPER12)&xMulti;
}

xlAutoFree

Demonstrates the xlAutoFree callback. Frees the memory allocated by fArray as noted in the comment above.

__declspec(dllexport) void WINAPI xlAutoFree12(LPXLOPER12 pxFree) 
{
   GlobalUnlock(hArray);
   GlobalFree(hArray);
   return;
}

xlCoerceExample

This function takes a value and converts it to a string. Then, the function displays the string in an alert box.

__declspec(dllexport) short WINAPI xlCoerceExample(short iVal) 
{
   XLOPER12 xStr, xInt, xDestType;

   xInt.xltype = xltypeInt;
   xInt.val.w = iVal;

   xDestType.xltype = xltypeInt;
   xDestType.val.w = xltypeStr;

   Excel12f(xlCoerce, &xStr, 2, (LPXLOPER12)&xInt, (LPXLOPER12)&xDestType);

   Excel12f(xlcAlert, 0, 1, (LPXLOPER12)&xStr);
   Excel12f(xlFree, 0, 1, (LPXLOPER12)&xStr);

   return 1;
}

xlFreeExample

This example calls GET.WORKSPACE(1) to return (as a string) the platform on which Microsoft Excel is currently running.
The code copies this returned string into a buffer for later use.
The standard strcpy() function is not used to copy the string to the buffer because strcpy() expects a null-terminated string and the returned value is a byte-counted string.
The code places the buffer back into the XLOPER12 for later use with Excel12f(). Finally, the code displays the string in an alert box.

__declspec(dllexport) short WINAPI xlFreeExample(void) 
{
   XLOPER12 xRes, xInt;
       XCHAR buffer[cchMaxStz];
       int i,len;

   // Create an XLOPER12 for the argument to Getworkspace
   xInt.xltype = xltypeInt;
   xInt.val.w = 1;
   // Call GetWorkspace
   Excel12f(xlfGetWorkspace, &xRes, 1, (LPXLOPER12)&xInt);

   // Get the length of the returned string
   len = (int)xRes.val.str[0];
   if (len > cchMaxStz - 2) //Take into account 1st char, which contains the length
           len = cchMaxStz - 2; //and the null terminator. Truncate if necessary to fit

   // Copy to buffer
   for(i = 1; i <= len; i++)
   {
      buffer[i] = xRes.val.str[i];
   }

   // Null terminate, Not necessary but a good idea
   buffer[len] = '\0';
   buffer[0] = len;

   // Free the string returned from Excel
   Excel12f(xlFree, 0, 1, &xRes);

   // Create a new string XLOPER12 for the alert
   xRes.xltype = xltypeStr;
   xRes.val.str = buffer;

   // Show the alert
   Excel12f(xlcAlert, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

xlGetInstExample

The following example compares the last instance of Microsoft Excel to the current instance of Microsoft Excel.
If they are the same, the code returns 1; if they are not the same, it returns 0; if the function fails, it returns -1.

__declspec(dllexport) short WINAPI xlGetInstExample(void) 
{
   XLOPER12 xRes;
   static HANDLE hOld = 0;
   short iRet;

   if (Excel12f(xlGetInst, &xRes, 0) != xlretSuccess)
   {
      iRet = -1;
   }
   else
   {
      HANDLE hNew;

      hNew = (HANDLE)xRes.val.w;

      if (hNew != hOld)
         iRet = 0;
      else
         iRet = 1;

      hOld = hNew;
   }

   return iRet;
}

xlGetInstPtrExample

The following example compares the last instance of Microsoft Excel to the current instance of Microsoft Excel. If they are the same, the code returns 1; if they are not the same, it returns 0; if the function fails, it returns -1.

__declspec(dllexport) short WINAPI xlGetInstPtrExample(void) 
{
   XLOPER12 xRes;
   static HANDLE hOld = 0;
   short iRet;

   if (Excel12f(xlGetInstPtr, &xRes, 0) != xlretSuccess)
      iRet = -1;
   else
   {
      HANDLE hNew;

      hNew = xRes.val.bigdata.h.hdata;

      if (hNew != hOld)
         iRet = 0;
      else
         iRet = 1;
      hOld = hNew;
   }

   return iRet;
}

xlGetNameExample

The following code retrieves the name of the DLL that contains the code, and then displays it in an alert box.

__declspec(dllexport) short WINAPI xlGetNameExample(void) 
{
   XLOPER12 xRes;

   Excel12f(xlGetName, &xRes, 0);
   Excel12f(xlcAlert, 0, 1, (LPXLOPER12)&xRes);
   Excel12f(xlFree, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

xlSetExample

The following code places the passed-in value into B205:B206.

__declspec(dllexport) short WINAPI xlSetExample(short iVal) 
{
   XLOPER12 xRef, xValue;

   xRef.xltype = xltypeSRef;
   xRef.val.sref.count = 1;
   xRef.val.sref.ref.rwFirst = 204;
   xRef.val.sref.ref.rwLast = 205;
   xRef.val.sref.ref.colFirst = 1;
   xRef.val.sref.ref.colLast = 1;
   xValue.xltype = xltypeInt;
   xValue.val.w = iVal;
   Excel12(xlSet, 0, 2, (LPXLOPER12)&xRef, (LPXLOPER12)&xValue);
   return 1;
}

xlSheetIdExample

This function gets the sheet ID for Sheet1 in workbook BOOK1.XLSX.

__declspec(dllexport) short WINAPI xlSheetIdExample(void) 
{
   XLOPER12 xSheetName, xRes;
   XCHAR szBuf[sizeof(IDSHEET)*2+2+1];

   xSheetName.xltype = xltypeStr;
   xSheetName.val.str = L"\022[BOOK1.XLSX]Sheet1";
   Excel12(xlSheetId, &xRes, 1, (LPXLOPER12)&xSheetName);
   wsprintfW((LPWSTR)szBuf, L"0x%p",xRes.val.mref.idSheet);
   Excel12f(xlcAlert, 0, 1, TempStr12(szBuf));
   Excel12(xlFree, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

xlSheetNmExample

This function displays a message containing the name of the sheet that called it.

__declspec(dllexport) short WINAPI xlSheetNmExample(void) 
{
   XLOPER12 xRes, xSheetName;

   Excel12(xlfCaller, &xRes, 0);
   Excel12(xlSheetNm, &xSheetName, 1, (LPXLOPER12)&xRes);
   Excel12(xlcAlert, 0, 1, (LPXLOPER12)&xSheetName);
   Excel12(xlFree, 0, 1, (LPXLOPER12)&xSheetName);
   return 1;
}

xlStackExample

This function displays a message that indicates the amount of stack space remaining.

__declspec(dllexport) short WINAPI xlStackExample(void) 
{
   XLOPER12 xRes;

   Excel12(xlStack, &xRes, 0);
   Excel12(xlcAlert, 0, 1, (LPXLOPER12)&xRes);
   return 1;
}

xlUDFExample

This function demonstrates how to run a macro from an XLL. It runs a macro called TestMacro in a workbook called BOOK1.XLSX

__declspec(dllexport) short WINAPI xlUDFExample(void) 
{
   XLOPER12 xMacroName, xMacroRef, xRes;

   xMacroName.xltype = xltypeStr;
   xMacroName.val.str = L"\034[BOOK1.XLSX]Macro1!TestMacro";
   Excel12(xlfEvaluate, &xMacroRef, 1, (LPXLOPER12)&xMacroName);
   Excel12(xlUDF, &xRes, 1, (LPXLOPER12)&xMacroRef);
   return 1;
}

InternationalExample

This routine demonstrates how to set the xlIntl bit to allow function names to be intepreted correclty on international versions of Excel.

__declspec(dllexport) int WINAPI InternationalExample() 
{
   XLOPER12 xResult, xSum;

   xSum.xltype = xltypeStr;
   xSum.val.str = L"\011=SUM(1,2)";

   return Excel12f(xlcFormula | xlIntl, &xResult, 2, (LPXLOPER12) &xSum, TempActiveRef12(237,237,1,1));
}

CalcCircum

Calculates the circumference of a circle given the radius

__declspec(dllexport) double WINAPI CalcCircum(double pdRadius) 
{
   return pdRadius * 6.283185308;
}

© 2026 Better Solutions Limited. All Rights Reserved. © 2026 Better Solutions Limited TopPrevNext