XLL+ Class Library (7.0)

Breaking changes

During the development of the XLL+ run-time libraries, every effort has been made to preserve the behavior of code that uses older versions of XLL+. However, a few exceptions have proven impossible to avoid.

XLL+ 6.0

XLL+ 6.2

String arguments

If you have existing code which uses string arguments, it will in general continue working under XLL+ 6. The old version of the function had an argument of type const char*; the upgraded version will have const CXlStringArg&. The compiler will use the casting operator CXlStringArg::operator const char* and the code will work as before.

A problem arises if your code passes the string to a loosely-typed function such as printf() or CXlOper::Format. The code will compile successfully, but the compiler will not invoke the casting operator, and you must cast the value explicitly.

For example, an XLL+ 5 add-in function with a string argument might use it as follows:

CopyC++
extern "C" __declspec( dllexport )
LPXLOPER GetCustomerDetails(const char* customer)
{
//}}XLP_SRC 
    char select[512];
    sprintf(select, "SELECT * FROM CUSTOMER WHERE NAME='%s'", 
        customer);
    ...
}

Under XLL+ 6 the converted code will fail, and the argument to sprintf must be cast to const char*:

CopyC++
CXlOper* GetCustomerDetails_Impl(CXlOper& xloResult, const CXlStringArg& 
    customer)
{
    // End of generated code 
//}}XLP_SRC 
    char select[512];
    sprintf(select, "SELECT * FROM CUSTOMER WHERE NAME='%s'", 
        (const char*)customer);
    ...
}

CXlOper::Cell and CXlOper::VectorCell

Under previous versions of XLL+ (5 and below), these methods returned a reference to a CXlOper type, which was contained within the outer CXlOper. In order to support both Excel 2007 and older versions of Excel, this functionality has had to be changed.

The methods now return a new class of object, CXlCell or CXlConstCell, which can be used to refer to the cell, but is not itself of type CXlOper.

If your code retained a copy of the return value, as in for instance:

CopyC++
const CXlOper& item = xloArray.VectorCell(i);
total += item.ToDouble();

then it must be changed. The code above becomes:

CopyC++
CXlConstCell item = xloArray.VectorCell(i);
total += item.ToDouble();

If your code simply used the returned value without retaining a copy of it, then it will continue to compile. For example, the following code does not need to change:

CopyC++
xloArray.VectorCell(i) = 0.0;

CXlOper::CallAddin

A new model for implementing add-in functions has been introduced for XLL+ 6. There are two shell functions (generally MyFunction_4 and MyFunction_12) which are called by Excel; each in turn calls a common implementation function (generally MyFunction_Impl).

If you have been calling an add-in function from another add-in function in the same project, using CXlOper::CallAddin, then you will need to change the way you call it.

The internal call should now be to MyFunction_Impl instead of to MyFunction, and it should have one extra argument, which is the destination of the result.

For an example of the code change required, see the SimpOpt sample.

CXlRef::GetRef

Under XLL+ version 5 and below, this method returned a reference to the actual CXlRef contained within the CXlOper, which could then be written to directly. In order to support Excel 2007 as well as earlier versions of Excel, this functionality has had to be changed.

The method now returns a copy of the CXlRef contained in the CXlOper; in order to change its value, you must call SetRef to apply any changes. Thus, if your existing code is:

CopyC++
xloRef.GetRef().MoveBy(0, 1);

You will need to change it to:

CopyC++
CXlRef xlr = xloRef.GetRef();
xlr.MoveBy(0, 1);
xloRef.SetRef(xlr);

Alternatively, you can use one of the new short-hand functions CXlOper::MoveRefBy or CXlOper::SetRef, e.g.:

CopyC++
xloRef.MoveRefBy(0, 1);
xloRef.SetRef(1, 2);

VersionInfo functions

Earlier versions of XLL+ generated a VersionInfo add-in function that cannot be upgraded by the XLL+ Upgrade Wizard. To upgrade this function, the easiest solution is to generate a new VersionInfo function, using the Add VersionInfo Function command (on the Tools menu of the XLL Add-ins window). Then copy over any details you wish to retain from the old function, and delete it.

COper methods

Deprecated COper methods

For XLL+ 6, the COper class has been merged into the CXlOper class. Some COper functions that have been deprecated for some time were not included in the merge:

COper validation methods

For XLL+ 6, the mechanism for validation has been completely revised. Some COper functions that were used by the code generated by the Function Wizard are no longer used, and are not supported in XLL+ 6:

COper and CXlOper data members

In earlier versions of XLL+, the CXlOper and COper classes were publicly derived from their underlying C structures, XLOPER and OPER respectively. This allowed developers to directly access the data members of the underlying structure. In particular, the val and xltype data members could be read directly.

The CXlOper class is no longer directly derived from the XLOPER structure. It now holds a pointer to either a XLOPER or a XLOPER12 structure, depending on the version of Excel under which the add-in is running.

Code that uses the xltype member should call CXlOper::IsOfType() to inspect it.

Direct access to the val data member is no longer supported.

CXllFn data members

Several of the data members of CXllFn have been removed, and replaced by Excel-version-dependent data members.

XLL+ 5.0 XLL+ 6 - Excel 2003 & below XLL+ 6 - Excel 2007 & above
m_stEntryPoint m_stEntryPoint4 m_stEntryPoint12
m_stArgTemplate m_stArgTemplate4 m_stArgTemplate12
m_stArgNames m_stArgNames4 m_stArgNames12
m_stCategory m_stCategory4 m_stCategory12
m_stHelpText m_stHelpText4 m_stHelpText12
m_astArgHelpText m_astArgHelpText4 m_astArgHelpText12

Where possible you should replace use of the data members above with calls to the following functions. Each of these functions returns the value appropriate for the version of Excel which is currently running. In addition, these calls handle any localization that is required if the strings contain resource IDs.

Data member Function call
m_stEntryPoint GetEntryPoint()
m_stArgTemplate GetArgumentTemplate()
m_stArgNames GetArgumentName(), GetArgumentNames()
m_stCategory GetCategory()
m_stHelpText GetHelpText()
m_astArgHelpText GetArgumentHelpText(), GetArgumentHelpTexts()

The following data members are no longer supported.

Data member Replacement
m_astArgExt m_stDefinition
m_stFnExt m_stDefinition

Finally, the data member m_stName has changed type from a CString to a Unicode CStringW type. In particular, code that compares the name to an ANSI string will fail to compile, e.g.:

CopyC++
if (strcmp(pfn->m_stName, "MyFunc") == 0)

This comparison would need to be changed to:

CopyC++
if (wcscmp(pfn->m_stName, L"MyFunc") == 0)

CXlHandleStore::ObjectFromHandle

The method CXlHandleStore::ObjectFromHandle, which is used to convert Excel handles to object pointers, is no longer const. The signature has been changed to non-const because the CXlHandleStore is now thread-safe, and thus calls that were previously read-only now need to mutate the object in order to lock it.

GDI32 Linker Error

Projects that built perfectly with XLL+ 6.0 may fail to build with XLL+ 6.2, with the following linker errors.

CopyC++
xlllibsd.lib(WizardHook.obj) : error LNK2019: unresolved external symbol __imp__DeleteObject@4 referenced in function "public: void __thiscall CWizardHook::Uninstall(void)" (?Uninstall@CWizardHook@@QAEXXZ)
xlllibsd.lib(WizardHook.obj) : error LNK2019: unresolved external symbol __imp__CreateFontIndirectA@4 referenced in function "private: struct HFONT__ * __thiscall CWizardHook::CreateButtonFont(void)" (?CreateButtonFont@CWizardHook@@AAEPAUHFONT__@@XZ)
xlllibsd.lib(WizardHook.obj) : error LNK2019: unresolved external symbol __imp__SetBkMode@8 referenced in function "private: void __thiscall CWizardHook::DrawButton(int,struct tagDRAWITEMSTRUCT *)" (?DrawButton@CWizardHook@@AAEXHPAUtagDRAWITEMSTRUCT@@@Z)
xlllibsd.lib(WizardHook.obj) : error LNK2019: unresolved external symbol __imp__SelectObject@8 referenced in function "private: void __thiscall CWizardHook::DrawButton(int,struct tagDRAWITEMSTRUCT *)" (?DrawButton@CWizardHook@@AAEXHPAUtagDRAWITEMSTRUCT@@@Z)
xlllibsd.lib(WizardHook.obj) : error LNK2019: unresolved external symbol __imp__GetStockObject@4 referenced in function "private: void __thiscall CWizardHook::DrawButton(int,struct tagDRAWITEMSTRUCT *)" (?DrawButton@CWizardHook@@AAEXHPAUtagDRAWITEMSTRUCT@@@Z)

To resolve this problem add the library gdi32.lib to the list of Additional Dependencies in the Linker/Input page of the project's property pages.

Asynchronous functions

For XLL+ 6.2, the Asynchronous function implementation model was improved. Asynchronous versions of functions no longer take an extra argument "RtdSignal". If you have released add-ins with asynchronous functions, you should use the UseAsyncHandleModel to ensure that existing spreadsheets still continue to work correctly.

See Upgrading asynchronous functions from XLL+ 6.0 for details.

See Also

XLL+ Class Reference