65.9K
CodeProject 正在变化。 阅读更多。
Home

Excel 中的自定义函数:第五部分,XLL-RTD

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.33/5 (3投票s)

2012年7月30日

CPOL

3分钟阅读

viewsIcon

21373

downloadIcon

19

介绍:为什么你想要从 XLL 调用 RTD? 回想一下,调用 RTD 的方法是通过 Excel 中的 RTD 函数,因此用户需要记住你的函数需要多少参数,以及按什么顺序提供它们,甚至函数名称是什么。 祝你好运解释

介绍 

为什么你想要从 XLL 调用 RTD? 回想一下,调用 RTD 的方法是通过 Excel 中的 RTD 函数,因此用户需要记住你的函数需要多少参数,以及按什么顺序提供它们,甚至函数名称是什么。 祝你好运向你的用户解释这些!

 

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

示例 1:本系列第三部分中的示例。 对用户不友好。 我甚至看不出它做什么,你能吗?

本系列的其他文章

XLL/RTD 混合

从 XLL 调用 RTD 实际上非常容易。 RTD 不定义具有名称的多个函数,但在 RTD 中有不同的函数并不难。 只需使用第一个参数作为函数名称,然后根据该名称在 RTD 中调用单独的函数。

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

示例 2:在一个 RTD 服务器中调用多个函数。

要创建两者的“混合”,你需要为 RTD 和 XLL 创建单独的项目。 假设这些函数是在 RTD 中定义的,让我们继续讨论 XLL。 XLL 可以使用辅助函数来调用 RTD。 这相对简单,但你需要注意几件事

  1. RTD 仅接受字符串参数。 如果你想将某些参数限制为数字、日期或布尔值,你需要在 XLL 中这样做,但你需要注意在调用 CallRTD 之前将这些类型转换为字符串。
  2. 确保 XLL 和 RTD 使用相同的数字格式。
  3. 如果 XLL 是从函数向导调用的,则不应调用 RTD。
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;
} 

示例 3:CallRTD 助手。

最后,是时候使用 CallRTD 助手了。 函数的参数需要转换为字符串,并且 XLL 函数应该返回 RTD 的结果。 它看起来应该调用 RTD,等待它完成并返回值,但是发生的情况是调用 CallRTD 立即返回 RTD 函数的默认值(例如,它可能是“正在加载...”)。 然后,当 RTD 准备好时,它会通知 Excel,Excel 再次调用 XLL 函数,这次 CallRTD 将返回最终值。

__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;
} 

现在你可以在像这样的电子表格中使用它

=GetStockPrice("ABC.XY") 

该函数将返回一个随机数,该随机数每隔几秒钟更新一次新数字(它从之前的价格随机移动,因此它不会到处都是)。

RTD 设计

下载中的 RTD 示例与我的 RTD 文章中的示例略有不同。 旧版本为每次调用 GetStockPrice 启动一个新线程。 想象一下,如果用户用 GetStockPrice 填充 10 万行。 结果不会很好,所以这个版本限制了线程数(可以调整),并且不是启动新线程,而是将主题 ID 放入队列中。 或者,如果 RTD 主要进行网络通信,你可以使用异步套接字,并且所有请求都可以通过单个工作线程。

示例的要求

该示例使用了 2010 XLL SDKboost 库 (1.5)。 在构建项目之前,你需要构建 boost 库和 XLL SDK 的 samples 目录中的 Framework 项目。 然后将目录添加到 Visual studio(你的目录结构可能不同)

包含文件:

c:\boost_1_50_0

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

库文件:

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

c:\boost_1_50_0\stage\lib

 

 

结论 

使用这种技术可以让你两全其美。 该函数易于最终用户使用 (XLL),并且你可以获得异步的优点和推送更新的能力 (RTD)。 此外,没有缺点! 如果你已经开发了一个 RTD,那么很容易添加 XLL 组件,因为 RTD 组件不需要修改,并且用户甚至可以在同一张表格上混合使用两者。

© . All rights reserved.