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






3.33/5 (3投票s)
介绍:为什么你想要从 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。 这相对简单,但你需要注意几件事
- RTD 仅接受字符串参数。 如果你想将某些参数限制为数字、日期或布尔值,你需要在 XLL 中这样做,但你需要注意在调用 CallRTD 之前将这些类型转换为字符串。
- 确保 XLL 和 RTD 使用相同的数字格式。
- 如果 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 SDK 和 boost 库 (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 组件不需要修改,并且用户甚至可以在同一张表格上混合使用两者。