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

VSTO中Word的Range复制方式的更多相关文章

  1. VSTO中Word转换Range为Image的方法

    VSTO中Word转换Range为Image的方法 前言 VSTO是一套用于创建自定义Office应用程序的Visual Studio工具包,通过Interop提供的增强Office对象,可以对Wor ...

  2. VSTO中Word的查找方式

    VSTO中Word的查找方式 前言 使用C#在VSTO开发Word插件的过程,经常需要对文档中的内容进行查找和替换.在Word中进行文本的查找替换,和一般对纯文本的查找替换却不太一样.因为Word文档 ...

  3. 解决vim中鼠标右键无法复制的问题

    转:http://www.cnblogs.com/jianyungsun/archive/2011/03/19/1988855.html 这是我的vim配置文件:jeffy-vim-v2.4.tar ...

  4. [转]VB.net中 excel 的range方法

    本文转自:https://blog.csdn.net/bigheadsheep/article/details/7711235 第五章 Range对象基本操作应用示例(1)Range对象可能是VBA代 ...

  5. discuz 修改亮剑积分商城2.91模板(在常用设置中添加商场首页排序方式的背景颜色)

    在应用 -> 积分商城 -> 常用设置 中添加 商场首页排序方式 的背景颜色修改功能 步骤: 1.找到并打开此页面对应的模板source\plugin\aljsc\template\set ...

  6. mysql同步复制异常的常见操作-传统复制方式

    mysql同步复制异常的常见操作-传统复制方式 一.传统复制方式是基于非gtid的,常见的错误有1032和1062 1032是主键冲突,1062是从库中没有找到对应的记录. 可以查看出现错误的binl ...

  7. Excel VBA 从一个工作簿查找另一个一个工作簿中的一些内容复制到另外一个工作簿

    帮朋友来写个Excel VBA 以前写过ASP,所以对vb略微熟悉,但VBA 没有仔细研究过. 以前只研究过 vba 写一个 计算个人所得税的程序. 这次写的功能也算是简单,但也耗费了两天的功夫. 需 ...

  8. 【咸鱼教程】Egret中可长按复制的文本(例如复制优惠码)

    一 实际效果二 实现原理三 源码下载 在egret中实现长按复制文本效果,一般用于复制优惠码什么的. 一 实际效果         二 实现原理 在egret的游戏元素都是绘制在canvas上的,我们 ...

  9. mysql-5.7 调整mysql的复制方式由master_log_file+master_log_pos 到gtid 详解

    一.祖传的master_log_file + master_log_pos的复制方式面临的问题: 在很久以前 那个时候我还没有出道,mysql就已经就有复制这个功能了.如果要告诉slave库从mast ...

随机推荐

  1. [微信小程序]编译.wxss出错,2 not found

    小程序新建项目就出错:2 not found  编译.wxss文件出错(不是一般的郁闷,新建项目就报错...) 大概的情况是开发工具没有更新.或更新不到, 第一,可以删掉开发工具重新下载最新安装: 第 ...

  2. Spring Cloud Eureka 使用 IP 地址进行服务注册

    默认情况下,Eureka 使用 hostname 进行服务注册,以及服务信息的显示,那如果我们使用 IP 地址的方式,该如何配置呢?答案就是eureka.instance.prefer-ip-addr ...

  3. [.net 面向对象程序设计深入](31)实战设计模式——使用Ioc模式(控制反转或依赖注入)实现松散耦合设计(1)

    [.net 面向对象程序设计深入](31)实战设计模式——使用IoC模式(控制反转或依赖注入)实现松散耦合设计(1) 1,关于IOC模式 先看一些名词含义: IOC: Inversion of con ...

  4. [Swift]LeetCode390. 消除游戏 | Elimination Game

    There is a list of sorted integers from 1 to n. Starting from left to right, remove the first number ...

  5. vue总结

    1.库和框架的区别 库:jquery 本质上就是一些列函数的集合,将一些函数封装到一个独立的就是文件中 在使用的jquery的时候,是由开发人员说了算的,也就是说开发人员起到了主导作用,而jquery ...

  6. (转)iOS学习——UIlabel设置行间距和字间距

    在iOS开发中经常会用到UIlabel来展示一些文字性的内容,但是默认的文字排版会觉得有些挤,为了更美观也更易于阅读我们可以通过某些方法将UIlabel的行间距和字间距按照需要调节. 比如一个Labe ...

  7. 工作5年的Java程序员,才学会阅读源码,可悲吗?

    最近一位5年开发经验的群友与我聊天 他说:最近慢慢的尝试去看spring的源码,学习spring,以前都只是会用就行了,但是越是到后面,发现只懂怎么用还不够,在面试的时候经常被问到一些开源框架的源码问 ...

  8. MySQL casting from decimal to string(mysql decimal 转 varchar)

    今天群里一个哥们问我mysql怎么将decimal转成varchar,经过查阅资料发现,mysql好像不能将decimal直接转换成varchar,但是可以转成char,原文链接:http://sta ...

  9. 机器学习 GBDT+xgboost 决策树提升

    目录 xgboost CART(Classify and Regression Tree) GBDT(Gradient Boosting Desicion Tree) GB思想(Gradient Bo ...

  10. 【java设计模式】(5)---装饰者模式(案例解析)

    设计模式之装饰者模式 一.概念 1.什么是装饰者模式 装饰模式是在不使用继承和不改变原类文件的情况下,动态的扩展一个对象的功能.它是通过创建一个包装对象,也就是装饰来包裹真实的对象.    这一个解释 ...