Click here to Skip to main content
11,701,904 members (67,733 online)
Click here to Skip to main content

Custom Functions in Excel: Part V, XLL-RTDs

, 29 Jul 2012 CPOL 8K 3 8
Rate this:
Please Sign up or sign in to vote.
IntroductionWhy would you  want to call an RTD from an XLL? Recall that the way to call an RTD is through the RTD function in Excel, so the user needs to somehow remember how many parameters your function takes and in what order to supply them and even what the function is called. Good luck explaini

Introduction 

Why would you  want to call an RTD from an XLL? Recall that the way to call an RTD is through the RTD function in Excel, so the user needs to somehow remember how many parameters your function takes and in what order to supply them and even what the function is called. Good luck explaining that to your users!

 

=RTD("rtdexample.simplertdserver.1","",1.5,2.5,3.5)

Exhibit 1: The example from part 3 of this series. Not exactly user-friendly. I can’t even tell what it does can you?

Other Posts in the Series

XLL/RTD Hybrid  

Calling an RTD from an XLL is actually very easy. The RTD doesn’t define multiple functions with names but it’s not too hard to have different functions in the RTD. Just use the first parameter to be the function name and then call separate functions inside the RTD based on that name.

=RTD("rtdexample.simplertdserver.1","","Perimeter",1.5,2.5,3.5)
=RTD("rtdexample.simplertdserver.1","","Power",1.5,2.5,3.5)

Exhibit 2: Calling multiple functions in one RTD server.

To create a “hybrid” of the two you need separate projects for the RTD and XLL. Assuming those functions are defined in an RTD let's move onto the XLL. The XLL can use a helper function to call into the RTD.  It’s relatively  straightforward but you need to be aware of a couple of things:

  1. RTDs take string parameters only. If you want to restrict some parameters to numbers or dates, or boolean values you need to do so in the XLL but you need to take care of the conversion of those types to strings before calling CallRTD.
  2. Make sure the XLL and RTD are using the same number format.
  3. The XLL shouldn’t call the RTD if it’s being called from the function wizard.
XLOPER12 CallRTD( LPWSTR library, LPWSTR server, int numArgs, LPWSTR args[]) 
{
	
	int iStrings = -1;
	// 28 parameters max
	LPXLOPER12 lparameters[30];
	static XLOPER12 result;	
	
	int li = 0;
	lparameters[li++] = (LPXLOPER12)TempStr12(library);
	lparameters[li++] = (LPXLOPER12)TempStr12(server);	


	for(int i = 0; i < numArgs; i++)
	{
		lparameters[li++] = (LPXLOPER12)TempStr12(args[i]);
	}

	int rc = 0;

	rc = Excel12v(xlfRtd, &result, li, (LPXLOPER12 *)lparameters);

	if(rc != xlretSuccess)
	{
		debugPrintf("Excel12v returned %d.\n", rc);
	}

	/* Free the the temp memoery */
	FreeAllTempMemory();
	result.xltype |= xlbitXLFree;
	return result;
} 

Exhibit 3: The CallRTD helper.

Finally it’s time to use the CallRTD helper. The parameters to the function need to be converted into strings and the XLL function should return the result of the RTD. It looks like it should call the RTD, wait for it to finish and return the value but what happens is that the call to CallRTD returns immediately with the default value of the RTD function (it could for instance be “Loading…”). Then when the RTD is ready it notifies Excel and Excel calls the XLL function again, this time CallRTD will return the final value. 

__declspec(dllexport) double WINAPI GetStockPrice(char * stockTicker)
{
	LPWSTR args[1];
	WCHAR wticker[256];
	if(stockTicker == NULL || strlen(stockTicker) == 0)
		return 0.0;
	MultiByteToWideChar(CP_ACP, 0, stockTicker, -1, wticker, 256);
	args[0] = wticker;
	XLOPER12 result = CallRTD(L"RTDExample.RTDServer", L"", 1, args);
	return result.val.num;
} 

Now you can use it in a spreadsheet like this:

=GetStockPrice("ABC.XY") 

The function will return a random number that will update every couple of seconds with a new number (it moves randomly from the previous price so it's not all over the place).

RTD Design 

The RTD example in the download is a bit different from then the one from my RTD article. The old version started a new thread for each call to GetStockPrice. Imagine if the user were to fill 100k rows with GetStockPrice. The results wouldn’t be pretty, so this version has a limit number of threads (that can be adjusted), and instead of launching new threads the topic ID is just placed in a queue. Alternatively if the RTD were doing mostly network communication you could use an asynchronous socket and all the requests could go through a single worker thread. 

Requirements for the Sample 

The sample makes use of the 2010 XLL SDK and the boost libraries (1.5). Before building the project you need to build the boost libraries and the Framework project in the samples directory in the XLL SDK. Then add the directories to Visual studio (your directory structure may be different):

Include Files: 

c:\boost_1_50_0 

C:\2010 Office System Developer Resources\Excel2010XLLSDK\INCLUDE

Library Files: 

C:\2010 Office System Developer Resources\Excel2010XLLSDK\LIB\x64 

c:\boost_1_50_0\stage\lib  

 

 

Conclusion 

Using this technique gives you the best of both worlds. The function is easy to use for the end user (XLL) and you get the asynchronous goodness and the ability to push updates (RTD). Plus there's no downsides! If you already have an RTD that you've developed it's easy to add the XLL component because the RTD component needs no modification and the user will be able to mix both even on the same sheet.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Steve L. Powell
Software Developer Excel Adviser
Canada Canada
I am a freelance software developer with a variety of different interests. My main area of expertise is Microsoft Office add-ins (Excel/Outlook mostly) but I also develop Windows applications, Access Databases and Excel macros . I develop in VBA, C# and C++. My website exceladviser.com has articles on Excel, Access, Microsoft Office development, and general Windows programming (WPF, etc.).

You may also be interested in...

Comments and Discussions

 
-- There are no messages in this forum --
| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.150819.1 | Last Updated 30 Jul 2012
Article Copyright 2012 by Steve L. Powell
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid