R.NET用于Excel Add-In的多实例(multi-Instance)问题及解决方法(2)

先来吐槽下Excel一些奇奇怪怪的行为。(本文基于Excel2010,其它版本适用性未考证)


1. 你是怎么打开Excel的?

双击文件?还是从开始菜单打开Excel,再Open?

实话讲,在这次遇到棘手问题之前,我一直没有认真考虑过这两种打开方式的区别。而事实上,这俩还是有很大区别。这个帖子里讲述了Excel的一点黑历史,摘录其中一段:

MS Excel however, is a whole different story. MS Excel used to be a SDI application up until 2003. For some … err, interesting reason, and in their infinite wisdom, Microsoft then decided to change that up and turn Excel into an MDI application. For 2013, this has been reverted and changed back to an SDI application. Now, if you are using Excel 2003, 2007 or 2010 and want to open more than one workbook in a separate window, you just might be out of luck.

SDI是一个文档一个窗口,MDI是多个文档共用一个窗口。所以在Excel2010中,双击打开多个文档,这些货其实是在一个窗口里面的,试试调整下窗口大小,会发现所有的文档所在的窗口大小都变了。。。而从开始菜单启动Excel,其实是强制启动了新的进程,这才是SDI的正确打开方式。庆幸的是,从2013起又回归到SDI了。


2. SDI和MDI对编程的影响

简单的使用,用何种打开方式几乎没什么影响。但对程序员来说,影响太大了。用我的这个项目举例:

我开发的是document-level的ribbon add-in,在文档打开的时候初始化一个R引擎,只有在文档关闭时引擎才会被释放。在对文档的整个操作过程中,都会有与R的交互,数据在两者之间传来传去,并且这些数据不是一次性用完就完了,这个操作对数据的修改结果会一直保存直到别的操作也修改了这个数据。

当Excel以MDI模式运行,多个文档共用一个窗口、一个ribbon。如果addin要做的事是一次性的计算,比如根据一列数据计算出均值并直接显示在某单元格里,那么切换文档不会造成影响;但如果是计算出均值并保留在内存里以备后续计算使用,那么MDI会有很大的隐患,数据可能会串,除非做特别处理把每个文档的相关数据隔离开。

如果是SDI模式,不同的进程可以使用不同的R引擎,就不存在数据串门的情况。

当然,如果有多个文档数据聚合的需求,MDI或许是一个好的解决方案?


3. MDI与R.NET、Excel Add-In的冲突

上篇提到R.NET的瓶颈,不允许一个进程里多个Instance,只能初始化一次。而MDI下要实现多个独立的R分析,就只能通过environment或其它方式人为进行隔离。document-level的ribbon add-in,当文档打开时才加载。当打开多个文档时,add-in也相应的依次加载,但R.NET一个实例的约束会使第二次初始化失败,进而导致add-in加载失败或Excel崩溃。

所以这种情况下,最有效的解决方法就是让Excel以SDI模式运行。


4. 打开一个Excel文件时,它都干了啥?

Excel是怎样默认以MDI模式运行的呢?参考 秘密在注册表中。这些Excel.*的key中,规定了各种后缀文件的new、open、edit等行为的默认模式。修改注册表,就可以实现从MDI到SDI的转变。

第一步需要先找到某个后缀对应哪个key。在命令行中操作,可以直接看到结果,等号后面的就是key值:


第二步到相应key,展开找到shell。以Template为例:


shell的value只有default一个,定义了双击*.xltx的行为,这里面的值是New,这也就解释了为什么双击一个template文件会新建一个文档,而不是打开它本身。(如果没有新建,建议检查该值是不是变成了Open)。

第三步修改value值。参照链接中的步骤,把/dde改为“%1”,以及ddeexec的重命名。

修改完重新打开Excel文档就会看到变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值