Getting Started
Compatible with Office 365.
github.com/bijoux_plugin/xll/blob/master/ExcelSDK/
Visual Studio 2022
Download the SDK to the following folder: C:\XLL\
C:\XLL\Excel2013XLLSDK\
Create a new project
language - C++, platform - Windows, project - Library
Dynamic Link Library (DLL)
Enter a project name and place the solution and project in the same folder
Precompiled Headers
Switch off precompiled headers.
Change this project property to switch off precompiled headers.
Project Properties > Configuration Properties > C/C++ > Precompiled Headers
Precompiled Header - Not Using Precompiled Headers
Change this project property to remove the precompiled header file.
Remove the "pch.h" header file.
Project Properties > Configuration Properties > C/C++ > Precompiled Headers
Precompiled Header File - (blank)
xlcall.h
This file is part of the Excel 2013 SDK.
This is a header file that contains all the necessary data structures, constant definitions and enumerations that are used by Excel.
It also contains all the C API interface functions that are needed for information to pass between Excel and the DLL.
We don't need to add this file to the actual project we just need to be able to link to this file.
This file is linked at compile time and the code is embedded into your solution.
Change this project property and add this folder.
Project Properties > Configuration Properties > C/C++ > General
Additional Include Directories - C:\XLL\Excel2013XLLSDK\Include\
(do not use VC++ Directories > Include Directories)
xlcall32.lib
This file is part of the Excel 2013 SDK.
This is a static import library that contains all the symbol definitions and function declarations that are implemented in the xlcall32.dll
We don't need to add this file to the actual project we just need to be able to link to this file.
This file is linked at compile time and the code is embedded into your solution.
Change this project property and add this folder.
Project Properties > Configuration Properties > Linker > General
Additional Library Directories - C:\XLL\Excel2013XLLSDK\LIB\x64\
(do not use VC++ Directories > Library Directories)
xlcall.cpp
This file is part of the Excel 2013 SDK.
This is a source file that contains the code for the Excel12() and Excel12v() functions.
This file is necessary because these two functions are not exported by the xlcall32.lib or xlcall32.dll files.
This file needs to be added to your project and is therefore dynamically linked to the Excel callback.
Copy the following file.
C:\XLL\Excel2013XLLSDK\SRC\xlcall.cpp
Paste this file into the project folder and add this file to the project (Project > Add Existing Item).
C:\Users\"username"\source\repos\"myprojectname"\xlcall.cpp
example.c
This file is part of the Excel 2013 SDK.
This source file contains everything you need to register and unregister user defined functions.
Copy the following file.
C:\XLL\Excel2013XLLSDK\Samples\example\example.c
Paste this file into the project folder and add this file to the project (Project > Add Existing Item).
C:\Users\"username"\source\repos\"myprojectname"\example.c
Change the angle brackets and replace them with quotes.
This is to tell the compiler to look in the source file directory for this file first, before looking in the include paths.
We will add the FRAMEWRK.h file to our project eventually.
#include <FRAMEWRK.h>
#include "FRAMEWRK.h"
example.c - xlAutoOpen
The original file registers a large number of functions but for this example we are only going to register one of them.
Replace the following function so it only registers the function called "CalcCircum".
__declspec(dllexport) int WINAPI xlAutoOpen(void)
{
static XLOPER12 xDLL;
/* Get the XLL filename */
Excel12f(xlGetName, &xDLL, 0);
Excel12f(xlfRegister, 0, 4,
(LPXLOPER12)&xDLL,
(LPXLOPER12)TempStr12(L"CalcCircum"),
(LPXLOPER12)TempStr12(L"BB"),
(LPXLOPER12)TempStr12(L"CalcCircum"));
/* Free the XLL filename */
Excel12f(xlFree, 0, 1, (LPXLOPER12)&xDLL);
/* Display a dialog box indicating that the XLL was successfully added */
XCHAR szBuf[255];
wsprintfW((LPWSTR)szBuf, L"xlAutoOpen has run successfully");
Excel12f(xlcAlert, 0, 2, TempStr12(szBuf), TempInt12(2));
return 1;
}
example.c - xlAutoClose
Replace the following function so it unregisters the function called "CalcCircum".
Excel12f(xlfSetName, 0, 1, TempStr12(L"CalcCircum"));
example.c - CalcCircum
This file includes the definition of the CalcCircum function at the bottom of the example.c file.
__declspec(dllexport) double WINAPI CalcCircum(double pdRadius)
{
return pdRadius * 6.283185308;
}
example.c
On line 808 change the "(HANDLE)" to "(HANDLE)(INT_PTR)"
???
example.def
In this example we are exporting our functions so we do not need to include this file as well.
If your functions are not being exported they can be supplied in a ".def" file.
If you are using a ".def" file you need to add the name of the file here.
Project Properties > Configuration Properties > Linker > Input
Module Definition File = example.def
framewrk.c
Copy the following file and paste them into the project folder.
C:\XLL\Excel2013XLLSDK\SAMPLES\FRAMEWRK\FRAMEWRK.c
Add the following existing item to the project.
C:\Users\"username"\source\repos\"myprojectname"\
Comment out this header from the top of the file.
'#include <xlcall.cpp>
Change the angle brackets and replace them with quotes.
#include <FRAMEWRK.h>
#include "FRAMEWRK.h"
Change the angle brackets and replace them with quotes.
#include <memorymanager.h>
#include "memorymanager.h"
On line 252 change the "Excel4v" reference to "Excel12v".
xlret = Excel12v(xlfn,pxResult,count,(LPXLOPER *)ppxArgs);
On line 991 change the "Excel4v" reference to "Excel12v".
wRet = Excel12v(xlSheetId, lpx, 0);
On line 223 comment out function "Excel" because we do not need backwards compatibility.
On line 975 comment out function "TempActiveRef".
On line 1101 comment out function "TempActiveCell"
On line 1157 comment out function "TempActiveRow"
On line 1215 comment out function "TempActiveColumn"
framewrk.h
On line ?? comment out these lines
???
Add Files
C:\XLL\Excel2013XLLSDK\SAMPLES\FRAMEWRK\FRAMEWRK.h
C:\XLL\Excel2013XLLSDK\SAMPLES\FRAMEWRK\MemoryManager.h
C:\XLL\Excel2013XLLSDK\SAMPLES\FRAMEWRK\MemoryManager.cpp
C:\XLL\Excel2013XLLSDK\SAMPLES\FRAMEWRK\MemoryPool.h
C:\XLL\Excel2013XLLSDK\SAMPLES\FRAMEWRK\MemoryPool.cpp
Add the following existing items to the project.
C:\Users\"username"\source\repos\"myprojectname"\
Remove Files
Remove the following files from the project.
framework.h
pch.h
dllmain.cpp
pch.cpp
Target File Extension
Change the target file extension from ".dll" to ".xll".
Project Properties > Configuration Properties > Advanced
Target File Extension = .xll
Build Solution
Check the selected platform.
Build > Configuration Manager
Active solution platform = x64
Build > Build Solution
Testing the Function in Excel
To test the function we need to load the add-in into Excel.
There are two ways you can do this: either through Visual Studio or manually browsing to the file.
It is possible to launch Excel from within Visual Studio.
Project Properties > Configuration Properties > Debugging
Command = C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE
This will add the necessary registry key automatically and will start Excel with a new blank workbook.
Debug > Start Debugging
Alternatively you can open Excel and browse to the add-in to install it.
Developer Tab, Excel Add-ins, Browse.
C:\XLL\Debug\XLL.xll
Testing the Function
In Excel type ="CalcCircum(12)" into a cell.
ReturnString
This function returns a text string.
This function take 2 parameters, both numbers.
Excel12f(xlfRegister, 0, 4,
(LPXLOPER12)&xDLL,
(LPXLOPER12)TempStr12(L"XL_ReturnString"),
(LPXLOPER12)TempStr12(L"UBB"),
(LPXLOPER12)TempStr12(L"XL_ReturnString"));
__declspec(dllexport) LPXLOPER12 WINAPI XL_ReturnString(double P, double T)
{
static XLOPER12 xResult;
xResult.xltype = xltypeStr;
xResult.val.str = L"\023BetterSolutions.com";
return(LPXLOPER12)&xResult;
}
ReturnArray
This function returns a (1 x 2) array containing two values.
This function has no parameters.
Excel12f(xlfRegister, 0, 4,
(LPXLOPER12)&xDLL,
(LPXLOPER12)TempStr12(L"XL_ReturnArray"),
(LPXLOPER12)TempStr12(L"Q"),
(LPXLOPER12)TempStr12(L"XL_ReturnArray"));
__declspec(dllexport) LPXLOPER12 WINAPI XL_ReturnArray(void)
{
static XLOPER12 xlArray; // not thread safe because it is static
XLOPER12 xlValues[2];
xlValues[0].xltype = xltypeNum;
xlValues[1].xltype = xltypeNum;
xlValues[0].val.num = 123;
xlValues[1].val.num = 456;
xlArray.xltype = xltypeMulti;
xlArray.val.array.rows = 1;
xlArray.val.array.columns = 2;
xlArray.val.array.lparray = &xlValues;
return (LPXLOPER12)&xlArray;
}
ReturnArrayDimensions
This function returns an array with a given size containing random numbers.
This function takes 2 parameters, to specify the number of rows and columns.
Excel12f(xlfRegister, 0, 4,
(LPXLOPER12)&xDLL,
(LPXLOPER12)TempStr12(L"XL_ReturnArrayDimensions"),
(LPXLOPER12)TempStr12(L"QJJ"),
(LPXLOPER12)TempStr12(L"XL_ReturnArrayDimensions"));
__declspec(dllexport) LPXLOPER12 WINAPI XL_ReturnArrayDimensions(int columns, int rows)
{
static XLOPER12 xlArray;
int totalcells;
totalcells = columns * rows;
LPXLOPER12 xlValues3 = (LPXLOPER12)malloc(totalcells * sizeof(XLOPER12));
if (xlValues3 != NULL){
for (int c = 0; c < totalcells; c++)
{
xlValues3[c].xltype = xltypeNum;
xlValues3[c].val.num = rand(); // built-in C function
}
// Free the memory
//free(xlValues3);
//xlValues2 = NULL; // optional but recommended to avoid dangling pointer
xlArray.xltype = xltypeMulti;
xlArray.val.array.columns = columns;
xlArray.val.array.rows = rows;
xlArray.val.array.lparray = xlValues3;
}
return (LPXLOPER12)&xlArray;
From the Book
Page 124
The xlAutoFree12 function is an XLL interface function that will be automatically called to release memory.
This function will be called automatically when functions return pointers back to Excel.
Assume all string elements were allocated using malloc, and need to be freed using free. Then free the array itself.
__declspec(dllexport) void WINAPI xlAutoFree12(LPXLOPER12 pxFree)
{
if(pxFree->xltype & xltypeMulti)
{
int size = pxFree->val.array.rows * pxFree->val.array.columns;
LPXLOPER12 p = pxFree->val.array.lparray;
for(; size-- > 0; p++) // check elements for strings
{
if((p->xltype & ~(xlbitDLLFree | xlbitXLFree)) == xltypeStr)
{
if(p->xltype & xlbitDLLFree)
{
free(p->val.str);
}
else if(p->xltype & xlbitXLFree)
{
Excel12(xlFree, 0, 1, p);
}
}
}
free(pxFree->val.array.lparray);
}
else if(pxFree->xltype == (xltypeStr | xlbitDLLFree))
{
free(pxFree->val.str);
}
else if(pxFree->xltype == (xltypeRef | xlbitDLLFree))
{
free(pxFree->val.mref.lpmref);
}
// Assume pxFree was itself dynamically allocated using malloc.
free(pxFree);
}
© 2026 Better Solutions Limited. All Rights Reserved. © 2026 Better Solutions Limited TopPrevNext