Building an Excel XLL in C/C++ with VS 2008


As part of a little investigation I’m doing at present, I needed to build some simple native XLLs for testing purposes. This was the first time I had a need to build XLLs since the Excel XLL SDK was updated back in September. The updated Excel 2007 XLL SDK is available for free download here. The online documentation is here. There’s also an old support article on how to build an XLL with C++ here – this refers to the Excel 97 SDK, but the information is still valid (although it doesn’t use any of the new types such as XLOPER12). The significant changes between the Excel 97 SDK and the Excel 2007 SDK are described here. In building my simple test XLLs, I based my code on the sample code in the SDK. I didn’t find any startling new information beyond the documentation, but I did encounter a few interesting issues which I thought I’d share here.


For my purposes, I wanted the simplest possible project. To start off, I created a new Visual C++ | Win32 Application project (called SimpleXll2007), and in the Win32 Application project wizard I changed the Application Type to DLL. When the wizard had generated the starter project, I deleted all the .H and .CPP source files from the project. Then I set the following project settings:


·         C++ | Additional include directories: “C:\Program Files (x86)\Excel2007XllSdk\include”


·         C++ | Precompiled Headers: Not Using Precompiled Headers


·         Linker | General | Output file: $(OutDir)\$(ProjectName).xll


·         Linker | General | Additional library directories: “C:\Program Files (x86)\Excel2007XllSdk\lib”


·         Linker | Input | Additional dependencies: xlcall32.lib frmwrk32.lib


·         Linker | Input | Module definition file: $(ProjectDir)$(ProjectName).def


·         Debugging | Command: C:\Program Files (x86)\Microsoft Office\Office12\EXCEL.EXE


 


To explain these: I needed to specify additional search paths for #includes and static linked libs because an XLL project will want to use the Excel XLL SDK headers and libraries (primarily, xlcall.h/xlcall32.lib which essentially constitute the Excel C API, and framewrk.h/frmwrk32.lib which provide additional helper functions). On my Vista machine, I had installed the SDK to C:\Program Files(x86)\Excel2007XllSdk. I had to specify that the target output should have an XLL extension not the default DLL. As one of the standard options for exporting functions, I chose to implement a DEF file. For debugging, I wanted to be able to just press F5 on the project and have VS launch Excel for me.


Next, I added the following new (empty) files to the project:


·         SimpleXll2007.def – lists the exported functions.


·         UDFs.h – defines the metadata for my UDFs (function type, signature, helpstrings, etc).


·         UDFs.c – implementation of my UDFs.


·         xlFunctions.c – implementation of the standard XLL exports that Excel will call back on.


 


The DEF file is pretty simple. It lists the standard XLL exports (xlAutoOpen, etc) and the custom UDF exports (SumTwo, etc):


LIBRARY SimpleXll2007.xll


 


EXPORTS


       ; Standard XLL functions


       xlAutoOpen


       xlAutoClose


       xlAutoRegister12


       xlAutoAdd


       xlAutoRemove


       xlAddInManagerInfo12


      


       ; UDFs


       SumTwo


       GetString


       GetChars


     


The header file (UDFs.h) defines the UDF metadata. As this defines values, not just types, this should probably be in a .C file, but the data is used when registering the UDFs, and the UDF-registering functions are part of the standard XLL exports (xlAutoOpen, etc) – and I wanted to separate out these generic functions from the metadata for my specific UDFs. For each function, I set up an array of strings for the metadata, and put all these arrays into an outer array – this enables me to register the UDF metadata in a simple loop later on. The only downside is that I need the arrays to be regular – that is, each sub-array must have the same number of elements. As some of the elements are for helpstrings for the UDF arguments, and as the number of UDF arguments varies, this forces me to define empty strings for some of my UDF argument help metadata values. The metadata values will eventually be passed to the Excel4/Excel12 function and its variants when the UDFs are registered in my implementation of xlAutoOpen and xlAutoRegister12.


// UDFs.h


#define g_rgNumUDFs 5


#define g_rgUDFdata 11


 


static LPWSTR g_rgUDFs


[g_rgNumUDFs][g_rgUDFdata] =


{


       {


              L“SumTwo”,                 // Function name/ordinal


              L“JJJ”,                    // Func signature type


              L“SumTwo”,                 // Func name in Func wizard


              L“Arg1, Arg2”,             // Arg name in Func wizard


              L“1”,                      // Function type


              L“SimpleXll2007”,           // Category in Func wizard


              L“”,                       // Shortcut (commands only)


              L“”,                       // Help topic


              L“SumTwo function help”,  // Func help in Func wizard


              L“Help for Arg1”,          // Arg help in Func wizard


              L“Help for Arg2”           // Arg help in Func wizard       


       },


       {


              L“GetString”,


              L“U”,        


              L“GetString”,


              L“”,


              L“1”,


              L“SimpleXll2007”,


              L“”,                  


              L“”,                  


              L“GetString function help”,


              L“”,


              L“”


       },


       {


              L“GetChars”,


              L“C”,        


              L“GetChars”,


              L“”,


              L“1”,


              L“SimpleXll2007”,


              L“”,                  


              L“”,                  


              L“GetChars function help”,


              L“”,


              L“”


       },


};


As you can see, the UDFs are pretty simple. The GetString and GetChars function signatures are almost identical – but I specifically wanted to test a UDF that returns a string as simple type such as a char* (specified as “C” when registering with Excel) as well as one that returns a string as an XLOPER/XLOPER12 (“U”). The SumTwo function returns a long (“J”) and takes 2 long args (“JJ”). Descriptions of the function signature identifiers are here.


These functions are implemented in the file UDFs.c (see comments inline below):


// UDFs.c


#include <windows.h>


#include <xlcall.h>


#include <framewrk.h>


#include <stdio.h>


 


// Example UDF that adds two numbers passed as longs, and


// returns a long.


__declspec(dllexport) long SumTwo(long arg1, long arg2)


{


       return arg1 + arg2;


}


 


// Example UDF that simply returns a string as an XLOPER12.


// Note that the string is length-prefixed in octal.


__declspec(dllexport) LPXLOPER12 WINAPI GetString (void)


{


       static XLOPER12 xResult;


       xResult.xltype = xltypeStr;


       xResult.val.str = L“\024Hello from GetString”;


       return(LPXLOPER12) &xResult;


}


 


// Example UDF that returns a null terminated string in a char*.


__declspec(dllexport) char* WINAPI GetChars(void)


{


       char* pszNewString = NULL;


       size_t cBytes;


       cBytes = strlen(“Hello from GetChars”) + 1;


       pszNewString = (char*)malloc(cBytes);


       sprintf_s(pszNewString, cBytes, “Hello from GetChars”);


       return pszNewString;


}


 


Finally, my xlFunctions.c file contains the standard XLL exports (xlAutoOpen, etc). This is very generic, and I pretty much just cut+pasted from the SDK sample code for these, with a few minor tweaks. I did remove the sample code for command and menu functions, because I only needed to test worksheet functions. I also sprinkled a few debugPrintfs around for good measure.


// xlFunctions.c


#include <windows.h>


#include <xlcall.h>


#include <framewrk.h>


#include “UDFs.h”


 


// Compares two strings for equality (case-insensitive).


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;


}


 


BOOL APIENTRY DllMain( HANDLE hDLL, DWORD dwReason, LPVOID lpReserved )


{


       switch (dwReason)


       {


       case DLL_PROCESS_ATTACH:


       case DLL_PROCESS_DETACH:


       case DLL_THREAD_ATTACH:


       case DLL_THREAD_DETACH:


       default:


              break;


       }


       return TRUE;


}


 


// Excel calls xlAutoOpen when it loads the XLL.


__declspec(dllexport) int WINAPI xlAutoOpen(void)


{


       static XLOPER12 xDLL;      // The filename of this XLL.


       int i;


 


       debugPrintf(“xlAutoOpen\n”);


 


       // Fetch the name of this XLL. This is used as the first arg


       // to the REGISTER function to specify the name of the XLL.


       Excel12f(xlGetName, &xDLL, 0);


       debugPrintf(“XLL Name: %S\n”, xDLL.val.str);


 


       // Loop through the g_rgUDFs[] table, registering each


       // function in the table using xlfRegister.


       for (i = 0; i < g_rgNumUDFs; i++)


       {


              Excel12f(xlfRegister, 0, 1 + g_rgUDFdata,


                       (LPXLOPER12) &xDLL,


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][0]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][1]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][2]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][3]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][4]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][5]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][6]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][7]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][8]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][9]),


                       (LPXLOPER12) TempStr12(g_rgUDFs[i][10])


                       );


       }


 


       // Free the XLL filename.


       Excel12f(xlFree, 0, 1, (LPXLOPER12) &xDLL);


       return 1;


}


 


// Excel calls xlAutoClose when it unloads the XLL.


__declspec(dllexport) int WINAPI xlAutoClose(void)


{


       int i;


       debugPrintf(“xlAutoClose\n”);


 


       // Delete all names added by xlAutoOpen or xlAutoRegister.


       for (i = 0; i < g_rgNumUDFs; i++)


       {


              Excel12f(xlfSetName, 0, 1, TempStr12(g_rgUDFs[i][2]));


       }


 


       return 1;


}


 


// Excel calls xlAutoRegister12 if a macro sheet tries to register


// a function without specifying the type_text argument.


__declspec(dllexport) LPXLOPER12 WINAPI xlAutoRegister12(LPXLOPER12 pxName)


{


       static XLOPER12 xDLL, xRegId;


       int i;


 


       debugPrintf(“xlAutoRegister12\n”);


       xRegId.xltype = xltypeErr;


       xRegId.val.err = xlerrValue;


 


       for (i = 0; i < g_rgNumUDFs; i++)


       {


              if (!lpwstricmp(g_rgUDFs[i][0], pxName->val.str))


              {


                     Excel12f(xlfRegister, 0, 1 + g_rgUDFdata,


                             (LPXLOPER12) &xDLL,


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][0]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][1]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][2]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][3]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][4]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][5]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][6]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][7]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][8]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][9]),


                             (LPXLOPER12) TempStr12(g_rgUDFs[i][10])


                             );


 


                     // Free the oper returned by Excel.


                     Excel12f(xlFree, 0, 1, (LPXLOPER12) &xDLL);


                     return(LPXLOPER12) &xRegId;


              }


       }


 


       return(LPXLOPER12) &xRegId;


}


 


// When you add an XLL 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)


{


       debugPrintf(“xlAutoAdd\n”);


       return 1;


}


 


// When you remove an XLL from the list of active add-ins, the


// Add-in Manager calls xlAutoRemove() and then


// UNREGISTER(“SimpleXll2007.XLL”).


__declspec(dllexport) int WINAPI xlAutoRemove(void)


{


       debugPrintf(“xlAutoRemove\n”);


       return 1;


}


 


// The Excel Add-in Manager calls xlAddInManagerInfo12 function


// to find the long name of the add-in.


__declspec(dllexport) LPXLOPER12 WINAPI xlAddInManagerInfo12(LPXLOPER12 xAction)


{


       static XLOPER12 xInfo, xIntAction;


 


       debugPrintf(“xlAutoAddInManagerInfo12\n”);


 


       // This code coerces the passed-in value to an integer.


       Excel12f(xlCoerce, &xIntAction, 2, xAction,


              TempInt12(xltypeInt));


 


       if (xIntAction.val.w == 1)


       {


              // Note that the string is length-prefixed in octal.


              xInfo.xltype = xltypeStr;


              xInfo.val.str = L“\016SimpleXll2007”;


       }


       else


       {


              xInfo.xltype = xltypeErr;


              xInfo.val.err = xlerrValue;


       }


 


       // Word of caution: returning static XLOPERs/XLOPER12s is


       // not thread-safe. For UDFs declared as thread-safe, use


       // alternate memory allocation mechanisms.


       return(LPXLOPER12) &xInfo;


}


 


After building the project, F5 runs Excel. You still need to register the XLL with Excel, and you can do this in the UI by going to File | Excel Options | Add-ins. Drop down the Manage listbox, and select Excel Add-ins to display the Excel Add-ins dialog (not the COM Add-ins dialog). Click the Browse button and navigate to the SimpleXll2007.xll to register this XLL with Excel:



 


After this, you can go to the Formulas tab and click Insert Function – you can see some of the UDF metadata surfaced in the Insert Function wizard dialog:



 

Comments (49)

  1. As part of a little ongoing investigation, I wanted to communicate between a managed add-in and a native

  2. As part of a little ongoing investigation, I wanted to communicate between a managed add-in and a native

  3. Steve Dalton says:

    There is a memory leak in the function __declspec(dllexport) char* WINAPI GetChars(void).  Dynamically allocated strings should be returned using XLOPERs or XLOPER12s and freed using xlAutoFree and xlAutoFree12 repsecitvely.

  4. flourishing says:

    i can’t build this project as your article.

    first report don’t have frmwk32.lib, then i delete that from the project’s settings. after that it reports that :

    1>xlFunctions.obj : error LNK2019: unresolved external symbol _TempStr12 referenced in function "int __stdcall xlAutoOpen(void)" (?xlAutoOpen@@YGHXZ)

    1>xlFunctions.obj : error LNK2019: unresolved external symbol _Excel12f referenced in function "int __stdcall xlAutoOpen(void)" (?xlAutoOpen@@YGHXZ)

    1>xlFunctions.obj : error LNK2019: unresolved external symbol _debugPrintf referenced in function "int __stdcall xlAutoOpen(void)" (?xlAutoOpen@@YGHXZ)

    1>xlFunctions.obj : error LNK2019: unresolved external symbol _TempInt12 referenced in function "struct xloper12 * __stdcall xlAddInManagerInfo12(struct xloper12 *)" (?xlAddInManagerInfo12@@YGPAUxloper12@@PAU1@@Z)

    can you please tell me how to fix this? thank you. my mail is 361571@qq.com

  5. andreww says:

    Yes, I should have pointed out that frmwrk32.lib is the output from the framewrk.sln solution. This solution is part of the Excel SDK, and is installed to a subfolder under <Excel2007XLLSDK install path>samplesframewrk. You need to build the framewrk.sln to generate the frmwrk32.lib.

  6. flourishing says:

    thanks ,it works now.

    Mr andreww ,can i talk to you ? do you have any messanger like skype or msn or yahoo messanger ? thank you.

  7. flourishing says:

    Mr andreww would you please modify this article http://support.microsoft.com/kb/178474/ so i can follow your article step by step? i use vs 2008, but i follow this article, i failed.

  8. andreww says:

    Re Steve Dalton’s comment on the  memory leak: you’re absolutely correct. I’ve committed the crime of over-simplification. For the purposes of this blog post, I wanted to build up gradually from a simply-typed function to one that uses XLOPERs, but I should have just stuck with XLOPERs in the first place. Thanks for pointing this out.

  9. flourishing says:

    hi andreww, i a a newbie, i have some questions, i hope you can help me. thank you.

    in c++

    how to get a workbooks’s worksheetss count?

    how to get all worksheets’ name ?

    how to get set a cells’s value and forluma (need one example)

    how to reference a cell,(in vb, use thisworksheets.cells(a,b).value …) in c++?

    thank you.

  10. andreww says:

    Hi Flourishing

    You need to search the documentation for answers to all your questions. The Office 2003 VBA Language Reference is here: http://msdn2.microsoft.com/en-us/library/bb190882(office.11).aspx

    and the Office 2007 equivalent is here: http://msdn2.microsoft.com/en-us/library/aa432027.aspx

  11. flourishing says:

    thank you.

    but i want to know how to do that with c++ not vba. can you give me some guid?

  12. andreww says:

    The object model is the same, regardless of which language you’re using. Of course, you’ll have to convert the code samples into C++, but that should be fairly trivial.

  13. flourishing says:

    thanks. still need your guid.

    i have read many docs.

    in vs2008 if i create a project ,type use mfc dll, the dll builded, excel report not a xll. change to win32dll it’s ok. excel can recogize the function in xll.

    but if i want to use objects about excel, docs said only can add the class to mfc project, what can i do ?

    thank you. if you spend some time to complete a sample will be very appreciated. i just want a xll that has a menu, the menu call a function, that function add a formula "=1+1" to all sheets’s cell "A5" . it’s easy for you, for me is very difficult. i have spend more time on this. please give some help. i’m sorry to disturb you, but there is not many people knows c++ xll develop, i have searched the internet, you are the only man i have found so professional. i hope you can help me.

  14. Thanks for the walkthrough Andrew! I am rusty on the C++ side, so I wanted to warn others of my folly: Where andrew instructs you to add the first two C++ project settings, make sure you actually have C++ files in the project (add the .c, .h, and .def files first)- otherwise the tab C++ under project settings will not show up in VS2008!!!

  15. Anand Raj says:

    LINK : fatal error LNK1104: cannot open file ‘LIBCD.lib’

    wile compiling i received this msg can any one find a solution for this

    by

  16. andreww says:

    Anand – libcd.lib is the static library for the debug single threaded version of the C runtime. Visual Studio no longer supports this version of the C runtime: instead you need to use the multi-threaded version (libcmtd.lib) or the dynamically linked version (msvcrtd.lib). You should change your linker settings. Alternatively, install the Microsoft Windows SDK, which includes libcd.lib.

  17. jerry says:

    I want to arbitrarily selected to the ranks of the cell, including the merger of the cell,

    XLOPER xCellRef;

    xCellRef.val.sref.ref.rwFirst,

    xCellRef.val.sref.ref.rwLast,

    xCellRef.val.sref.ref.colFirst,

    xCellRef.val.sref.ref.colLast

    how can I get rwFirst, rwLast, colFirst, colLast?

    thank you very much !

  18. Marcus T says:

    I am not able to build your example.

    Please help.

    This is the error message I got:

    1>—— Build started: Project: SimpleXll2007, Configuration: Debug Win32 ——

    1>Linking…

    1>   Creating library C:UserstanchonghuiDocumentsVisual Studio 2005ProjectsSimpleXll2007DebugSimpleXll2007.lib and object C:UserstanchonghuiDocumentsVisual Studio 2005ProjectsSimpleXll2007DebugSimpleXll2007.exp

    1>LINK : warning LNK4098: defaultlib ‘MSVCRT’ conflicts with use of other libs; use /NODEFAULTLIB:library

    1>xlFunctions.obj : error LNK2019: unresolved external symbol _debugPrintf referenced in function _xlAutoOpen@0

    1>C:UserstanchonghuiDocumentsVisual Studio 2005ProjectsSimpleXll2007DebugSimpleXll2007.xll : fatal error LNK1120: 1 unresolved externals

    1>Build log was saved at "file://c:UserstanchonghuiDocumentsVisual Studio 2005ProjectsSimpleXll2007SimpleXll2007DebugBuildLog.htm"

    1>SimpleXll2007 – 2 error(s), 1 warning(s)

    ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

  19. andreww says:

    jerry – this is really a question about XLOPERs – and you’re more likely to get an accurate answer if you post the question to the Excel programming forum: http://www.microsoft.com/communities/newsgroups/en-us/default.aspx?dg=microsoft.public.excel.programming&lang=en&cr=US

  20. andreww says:

    Marcus – the debugPrintf function is defined in the Excel XLL SDK, and documented here: http://msdn.microsoft.com/en-us/library/bb687879.aspx

    Did you forget to add a link dependency on frmwrk32.lib?

    For completeness, here are the commandline link arguments in my project:

    /OUT:"c:TempSimpleXll2007SimpleXll2007DebugSimpleXll2007.xll" /INCREMENTAL /NOLOGO /LIBPATH:"C:Program Files (x86)Excel2007XLLSDKlib" /DLL /MANIFEST /MANIFESTFILE:"DebugSimpleXll2007.xll.intermediate.manifest" /MANIFESTUAC:"level=’asInvoker’ uiAccess=’false’" /DEF:"c:TempSimpleXll2007SimpleXll2007SimpleXll2007.def" /DEBUG /PDB:"c:TempSimpleXll2007SimpleXll2007DebugSimpleXll2007.pdb" /SUBSYSTEM:WINDOWS /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT xlcall32.lib frmwrk32.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

  21. jerrydady says:

    Hi,andreww,I post the question to the Excel programming forum,

    but nobody answer my question,

    could you tell me other solutions?

    Thank you very much!

  22. cpsagman says:

    For Marcus T: If you built a release version of frmwrk32.lib then the debugPrintf function will not be included.  You need to build a debug version of frmwrk32.lib in order to get debugPrintf.  As for the other error, just add /NODEFAULTLIB:MSVCRT to the Linker command line found in Project…Properties…Linker…Command Line.  

  23. John D says:

    Hi Andrew, I built and running successfully in Excel 2007. However, I couldn’t run it under Excel 2003, I would like my add-in to be backward compatible, do you have any ideas? Thank you.

  24. andreww says:

    John – my post talked specifically about the 2007 version of the XLL SDK. This was updated for Excel 2007 and contains features that obviously only work in Excel 2007 (for example, XLOPER12 or xlAutoRegister12). Full details are in the online SDK documentation I linked to in my post. Specific information on building XLLs that are back-compatible with earlier versions is here: http://msdn.microsoft.com/en-us/library/bb687884.aspx.

  25. Mousum Dutta says:

    I have created a .XLL with VS2005 and EXCEL2007 SDK.

    1. I have created a MFC share DLL
    2. I have included all necessay files (XLCALL32.LIB, xlcall.h, and all framewrk files (instead of FRMWRK.LIB)

    3. I have included the following in all .cpp file

        a. #include "stdafx’h"

        b. #ifdef _DEBUG

           #define new DEBUG_NEW

           #endif

    "xlAutoOpen, xlAddInManagerInfo, xlAutoClose, xlAutoFree" (I have registered only one function)

    are as usual

    but if I open excel and close then it is showing memory leaks

    ‘EXCEL.EXE’: Unloaded ‘C:Program FilesMicrosoft OfficeOffice12MSOSTYLE.DLL’

    Detected memory leaks!

    Dumping objects ->

    {88} normal block at 0x04D750E8, 10240 bytes long.

    Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

    {87} normal block at 0x04D728A8, 10240 bytes long.

    Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

    {86} normal block at 0x04D70068, 10240 bytes long.

    Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD

    {85} normal block at 0x03FFC008, 10240 bytes long.

    Data: <                > 18 C0 FF 03 CD CD CD CD 02 00 CD CD CD CD CD CD

    {84} normal block at 0x03FF2EC8, 52 bytes long.

    Data: <    x           > 04 00 00 00 78 11 00 00 08 C0 FF 03 00 00 00 00

    {83} normal block at 0x03FF2E80, 12 bytes long.

    Data: <         .  > 01 00 00 00 04 00 00 00 CC 2E FF 03

    Object dump complete.

    ‘EXCEL.EXE’: Unloaded ‘C:Documents and Settingsmousum.duttaDesktopXLLMemLickageMyXLLdebugMyXLL.xll’

    I can send the project if you are interested in this problem.

    Mousum Dutta

    mousum.dutta@gmail.com

  26. andreww says:

    Mousum – does your UDF use strings? See Steve Dalton’s comment about a memory leak bug in my original code (and my response later).

  27. amborish says:

    I have created a XLL using Excel 2007 SDK. But when i am trying to load the xll in a fresh computer it is not getting loaded for vista with excel 2007 installed. Is anything else is required to load that. It is working for 2003 excel with vista.

  28. andreww says:

    amborish – what happens when you click the Browse button in Excel’s Add-Ins dialog? Does your XlL get listed in the dialog?

  29. D Dey says:

    Hi Andrew

    I’ve tried your XLL – your UDF appears in the formula automplete list.  Is it possible to add a screentip too??

    Thanks

    Debs

  30. andreww says:

    Debs – no, Excel does not support tooltips for UDFs, only for built-in functions.

  31. robert meijer says:

    Andrew, I have succesfully build an run an exclel xll with vs2008 on my vista 64 machine. It runs both with excel 2007 and 2003 (I take care of XLOPER and XLOPER12,etc). My XLL (C++) does not depend on special external libraries except for the ones you also use and C++ needs. In project setting I used all your setting above for compiling and linking.

    However, excel on another fresh xp 32 machine complains with "noth a valid add in" with a copy of the xll.

    I have set the system path to the place where this xll is, I put it, after experimenting with other locations, in the same directory as xlcall32 is located.

    I have run Dependency Walker and it complained that msvcr90.dll and dwmapi.dll (did not expect this dll!)was missing. These I supplied to the same directory. This, was no remedy.

    Do you have a receipe to create a portable XLL?

    Robert

  32. robert meijer says:

    Some dependency walker output…

    Robert

    LoadLibraryW("C:Documents and SettingsmuphyBureaubladbfxBfX.xll") called from "EXCEL.EXE" at address 0x3048C029.

    Loaded "BFX.XLL" at address 0x10000000.  Successfully hooked module.

    LDR: LdrpWalkImportDescriptor() failed to probe C:Documents and SettingsmuphyBureaubladbfxBfX.xll for its manifest, ntstatus 0xc0150002

    Unloaded "BFX.XLL" at address 0x10000000.

    LoadLibraryW("C:Documents and SettingsmuphyBureaubladbfxBfX.xll") returned NULL. Error: De toepassing kan niet worden gestart omdat de configuratie van de toepassing onjuist is. Het opnie

  33. andreww says:

    Robert – the dependency walker error re dwmapi.dll is probably a red herring. This is a delay-loaded DLL and therefore is not normally loaded unless one of its functions is called – and that won’t happen on XP. So this is irrelevant – unless of course you’ve set compiler options to force-load all delay-loaded DLLs?

    Also, are you dynamically linking to system DLLs that might only get installed with VS (and are therefore not on your clean XP machine)? Try statically linking instead.

  34. robert meijer says:

    Thanks,

    I solved the problem.

    I inherited debugPrintf calls from your code, and added some of my own, without thinking of the consequences.

    To solve the problems I put #ifdef arround them all, e.g.

        #ifdef _DEBUG
    
            debugPrintf(&quot;Excel version &quot;);
    
            debugPrintf(versie);
    
            debugPrintf(&quot;n&quot;);
    
        #endif
    

    Then your settings above for compiler and linker work fine. I created a straightforward setupproject in which I included the windows installer and de VC++ runtime libraries (X86) as a prerequisite.

  35. AlexZhang says:

    robert meijer said:

    Andrew, I have succesfully build an run an exclel xll with vs2008 on my vista 64 machine. It runs both with excel 2007 and 2003 (I take care of XLOPER and XLOPER12,etc). My XLL (C++) does not depend on special external libraries except for the ones you also use and C++ needs. In project setting I used all your setting above for compiling and linking.

    …….

    Change "LIBRARY SimpleXll2007.xll" to "LIBRARY SimpleXll2007" , worked on XP sp2

  36. lois says:

    thanks for this example. when I get to the last point, i.e. inserting the functions, I don’t see the Simple2007Xll category; this even though I added the Simple2007Xll.xll.

  37. andreww says:

    lois – it’s hard to say what might be wrong with your setup.

    In Excel, when you add an XLL in the Add-ins dialog, this adds an entry in HKCUSoftwareMicrosoftOffice<version>ExcelOptions named OPEN, OPEN1, OPEN2 etc. This has the value: /R "XXX", where XXX is the path to your XLL, eg:

    /R "C:TempSimpleXll2007SimpleXll2007DebugSimpleXll2007.xll"

    If you unregister your add-in and then uncheck the box in the Add-ins dialog, Excel will throw up an error dialog: "Cannot find add-in XXX. Delete from list?". Replying Yes to this prompt will delete the registry key when Excel next shuts down.

    If your XLL is listed in the registry, and shows up in the add-ins dialog, it should also show up in the function wizard – assuming you’ve registered each function against a function wizard category. In my example, I have arrays of REGISTER parameters in UDFs.h, where each function is registered to the "SimpleXll2007" category. The registration takes place in the xlAutoOpen function in xlFunctions.c.

  38. Sylvain says:

    I have also successfully built and run an XLL using VS 08 Express. However, the XLL won’t load on another PC unless I install VS 08 Express on it>

    Using Dependency Walker, I can see that there are calls to MSVCRT.DLL and a lot of others libs that are installed by VS 08 Express.

    As I would like to avoid telling the users of my XLL to install VS08, do you know what’s the best solution to ensure they have all the required DLLs?

    My code is not calling any DLLs as I’m using only the libs from the SDK framework.

    Thanks,

    S

  39. andreww says:

    Sylvain – MSVCRT.DLL is the Microsoft C Run-Time library. This used to be deployed as part of the OS, but now more recent versions are deployed instead. You’re right that deploying VS to your users’ machines is not a reasonable approach. You have a couple of options.

    1. You could continue to dynamically link to msvcrt.dll, and deploy it as a private DLL with your XLL solution.

    2. You could statically link to mscvrt instead. This is probably the simpler approach, as deploying private versions of msvcrt.dll may introduce servicing issues.

  40. Sylvain says:

    Andrew,

    MSVCRT(9).DLL is not the only library that is needed on the client machine, and I was actually not able to identify all of them because there are so many (unless I’m doing something wrong).

    Has anyone here deployed VS08 XLL to non-developer machines? If so, how did you link, and what else did you install on the user’s machines?

    Thank

    S

  41. Prem says:

    Hi,

    I have created a XLL project in VS2005 which calls .Net module using the COM (*.tlb). It runs fine but when i save the excel file in "save as" mode, close and then open a new excel sheet, recovery pane appears with the saved file name. I am not returning any XLOPERS and free’ing any excel returned structure.

    Can anybody suggest where the problem could be?

  42. AlexesDad says:

    Heres a clip demonstrating how to  create a C++ XLL with Visual Studio 2008 & XLW.

    http://www.youtube.com/watch?v=_mpw5_JW7T4

    XLW is free & open source and can be downloaded from here:

    https://sourceforge.net/project/showfiles.php?group_id=45222&package_id=37893&release_id=690866

    It also allows you create xlls in C#.

  43. AlexesDad says:

    ..sorry the link for download should have been

    http://sourceforge.net/project/showfiles.php?group_id=45222&package_id=37893&release_id=690866

    i.e http not https

  44. James says:

    do you need the .objs(memorymanager,etc) when you compile the framework? or do you just need the framewrk.h and the frmwrk32.lib(I want to include them in the same project dir)

  45. andreww says:

    James – no, the only binaries you need are the frmwrk32.lib and xlcall32.lib.

  46. james says:

    I’m getting a  

    EXCEL.EXE: 0xC0000005: Access violation writing location

    in TempStr in the framework.

    I need to use TempStr to add a menu at the top or it doesn’t register.

    I’ve been fallowing this as menu adding reference:

    http://support.microsoft.com/default.aspx/kb/178474

    If I use TempStrConst it doesn’t crash but it doesn’t add the menus any idea on how to solve this?

  47. james says:

    That’s weird I built it about 10 more times and it started adding the menus with TempStrConst, now it can’t find the "macros" for the UDF in the dll..

  48. ahmed says:

    Do anyone know where the reference guide to Excel4()/Excel12() is ? I want to write data to cells but passing through XLCALL.h isn’t really helpful because there is no description on what they do.