VSTO中Word的Range复制方式
VSTO中Word的Range复制方式
前言
VSTO是一套用于创建自定义Office应用程序的Visual Studio工具包,通过Interop提供的增强Office对象,可以对Word文档进行编程操作。Range是Word中执行操作的一个单元,可以理解成文档中一个选中的部分或者区域,针对这个选中部分,可以应用格式、修改文字和颜色等功能。在相同的文档和不同的文档之间,将Range的内容从原处复制到其他的Range中,是一种常见的业务需求。本文总结了常见的几种Range复制方式,对其特点进行了讨论分析,并提出一些改良的地方。
剪贴板复制
剪贴板是windows进程间通信的一种方式。原理是这样的,Range.Copy()
将内容复制到剪贴板中,然后AnotherRange.Paste()
从剪贴板中获取数据,然后复制到自己的区域内。
//原理示意
/// <summary>
/// range间的复制
/// </summary>
/// <param name="source">源range</param>
/// <param name="target">目标range</param>
public void Copy(Word.Range source, Word.Range target)
{
source.Copy();
target.Paste();
}
这种方式可靠性低,速度慢。就像薛定谔的猫一样,有时候可用,有时候不可用。原因在于使用了剪贴板作为中介,许多进程都在使用剪贴板,显而易见,使用剪贴板有许多未知的问题。
改良
为了缓解这种弊端,我们稍微做下修改,在剪贴板失败的时候,进行重试,大于一定次数就抛出异常。假设剪贴板失败是独立不相干的事件,可以在概率上提高成功的可能性。连续多次失败的概率将会变得很小,除非存在显著的剪贴板问题。依据的原理是贝努利分布,这里不予证明。
/// <summary>
/// range间的复制
/// </summary>
/// <param name="source">源range</param>
/// <param name="target">目标range</param>
public void Copy(Word.Range source, Word.Range target)
{
int num = 0;
//重试总次数
int limitNum = 5;
retry:
try
{
source.Copy();
target.Paste();
}
catch(Exception)
{
num++;
//连续多次失败,就抛出异常
if (num > limitNum)
{
throw;
}
goto retry;
}
}
XML复制
我们知道Word文档其实是一个OpenXml的结构树,一个复杂无比的XML,所以Word中的元素是XML的一部分,也是一个XML。参考HMTL来说,两个相同的标签内容就是相同的两个标签。
同理通过Range.XML
获取到Range的XML文本结构,再通过AnotherRange.InsertXML()
方法插入到目标range的区域,就完成了复制。
/// <summary>
/// range间的复制
/// </summary>
/// <param name="source">源range</param>
/// <param name="target">目标range</param>
public void Copy(Word.Range source, Word.Range target)
{
target.InsertXML(source.XML);
}
这种方式的稳定性比剪贴板的强,不存在中间过程的通信转换,速度也快一些。但是这种方式,也不一定完全就能成功,推测是Word的格式兼容性,有些Word文档的XML不能复制,或许是旧版本的Word文档,或许是某个版本Wps编辑的文档,原因很难探究,毕竟Word是世界上最复杂的软件之一了。
混合复制
通过上面的两种复制方式的陈述,我们知道这两种方式都有各自的特点。
方式 | 速度 | 可靠性 | 格式兼容性 |
---|---|---|---|
剪贴板 | 慢 | 低 | 高 |
XML | 快 | 中 | 中 |
这两种复制方式都有可能失败。为了避免这种情况,可以设计一个方案,优先使用XML进行复制,如果失败了,退化到使用剪贴板复制;重试若干次,直到成功或者超过重试次数。
/// <summary>
/// range间的复制
/// </summary>
/// <param name="source">源range</param>
/// <param name="target">目标range</param>
public void Copy(Word.Range source, Word.Range target)
{
int num = 0;
int limitNum = 5;
retryCopy:
//偶数次使用XML复制
if (num % 2 == 0)
{
//no
}
//奇数次使用剪贴板复制
else
{
source.Copy();
}
try
{
if (num % 2 == 0)
{
target.InsertXML(source.XML);
}
else
{
target.Paste();
}
}
catch (Exception)
{
//失败了进行重试
num++;
//超过重试次数,抛出异常
if (num > limitNum)
{
throw;
}
goto retryCopy;
}
}
最新文章
- C#设计模式-责任链模式
- webfrom 总结
- Unity 编译错误记录
- 在Eclipse中添加C/C++插件
- QQ分组显示列表ExpandableListView组件应用源码
- MMORPG大型游戏设计与开发(客户端架构 part5 of vegine)
- 快速排序算法-C语言实现
- 利器: 用Siege做Web服务器压测
- vim 缩写abbreviation
- jquery获取多个checkbox的值异步提交给php
- S3C2440 ADC详解
- 1.QT中的容器QVector,QList,QSet,QMap,QQueue,QStack,QMultiMap,QSingleList等
- Android 6.0 运行时权限处理问题
- MinHash 原理
- 一个C#程序员学习微信小程序路由的笔记
- Scrum冲刺阶段6
- MATLAB:增加噪声,同时多次叠加噪声图和原图以及求平均图像(imnoise,imadd函数)
- Architecture.SOLID-Principles
- JS中的继承链
- windows分区
热门文章
- 谨以此篇献给DJANGO学习过程中遇到的问题
- 32、可以拿来用的JavaScript实用功能代码
- hive独立配置mysql
- C++的结构体指针传参
- 依赖注入[7]: .NET Core DI框架[服务注册]
- 连接池c3p0 ,Proxool ,Druid ,Tomcat Jdbc Pool对比测试
- ubuntu-18.04 设置开机启动脚本
- 机器学习入门15 - 训练神经网络 (Training Neural Networks)
- 本地连接虚拟机_环境搭建01_VMWARE/XShell/CentOS
- SecureCRT 5.2.2版本下载和注册码