用微软VS2017为Word开发加载项的技巧
Word是一个大家平时办公中最常用的文字处理软件之一,其功能包罗万象,十分强大。但不排除某些用户有独特而专有的需求,Word自带的功能并没有考虑到,要由用户手动操作若干步方能完成。这些操作有时存在复用的价值,那么不妨把它们抽象并固定下来,变成Word里的一项功能吧。
对于简单的操作复用,我们可以通过内置的宏或VBA来实现。Word中甚至还提供了“录制宏”的功能,来降低编写代码的门槛。不过宏和VBA有个缺点,即不能利用Ribbon栏。(有同学说过可以使用XML映射来实现,但我没试过。)而开发一个加载项,或者说VSTO外接程序,就可以克服这个缺点。
今天,我们就来编写一个简单的VSTO外接程序,作为入门。
一、安装Visual Studio 2017,并在安装时确保选中Office/SharePoint这一选项。
二、打开VS2017,新建项目。分别选中Visual Basic→OfficeSharePoint→Word 2013和2016 VSTO外接程序。(选择VB是因为其语法与VBA的语法类似,学过VBA的同学可以马上上手,当然选择C#也是可以的。严格来说,此处的VB指的是VB.net,而VBA则基本继承VB6.0,两者的语法在某些地方还是有很大区别的。)为这个项目起个名字,比如WordAddInTest。
三、新建项目后,呈现在面前的是ThisAddIn.vb里的内容,我们稍后再来关注它。现在先来创造一个Ribbon界面。通过解决方案资源管理器添加一个新项,类型则选择“功能区(可视化编辑器)”,这样我们就得到了一个新的带有空组的Ribbon栏。
四、接下来,就是“搭积木”时间了。我们可以看到,在工具栏中出现了一些Ribbon控件,它们分别是Box、Button、ButtonGroup、CheckBox、DropDown、EditBox、Gallery、Group、Label、Menu、Separator、Tab、ToggleButton。
现在就对这些控件做一些简单的介绍。
1.容器控件:Tab、Group、Box和ButtonGroup。
a.Tab是选项卡,如果你希望使用不止一个选项卡,你可以拖放一个新的Tab。
b.Group是选项组,通常一个选项卡由若干个选项组组成。有时选项组右下角会标有一个灰色箭头,单击它能启动一个窗体。这种窗体的启动可以通过Group的DialogLauncher来实现。
c.Box(不可见)是用来排列具体的控件的,可以使控件横向或者纵向排列,目的是使界面井然有序。
d.ButtonGroup(不可见)则是专为排列按钮而存在的,而且只能是横向排列。
2.不可操作控件:Label和Separator。
a.Label即标签,是用来显示提示性文本的。
b.Separator即分割线,它可以用来位于同一个选项组中而功能又有所区别的控件或控件组。
3.单一控件:Button、CheckBox、CombolBox、DropDown、EditBox和ToggleButton。
a.Button是最普通的按钮,可以通过单击它执行一些操作。
b.CheckBox是复选框,可以用它来打钩。
c.CombolBox是组合框,可以用它来输入文本或从下拉列表中选择。
d.DropDown是下拉框,无法向它输入文本,只能从列表中选择。
e.EditBox是编辑框,可以用它来输入文本。
f.ToggleButton是类似开关的按钮,按钮在按下(呈现深色)时,是一种状态;松开时(恢复浅色)又是一种状态。
4.复合控件:Gallery、Menu和SplitButton。
这三个控件的作用比较相似,都是能生成下拉选项供用户选择。Gallery的特点是可以在下拉选项的一行中横向排列项目,且本身不能被用作按钮响应单击事件;Menu本身也不能用作按钮;而SplitButton则可以相应单击事件。
我们来看一张这些控件的示意图,就容易明白了。
五、做完界面以后,就可以着手编写代码了,但在开发具体的功能前,我们要先写一点必需的代码,为后续的工作铺路。
1.新建一个标准模块,用来存放公共的数据。我们把这个模块命名为mdlPublic。
定位到Module mdlPublic的下一行,声明Application接口,为了简便,就叫App吧。
Module mdlPublic
Public App As Word.Application
End Module
2.回到第三步中提及的ThisAddIn.vb文件中,定位到Private Sub ThisAddIn_Startup() Handles Me.Startup的下一行,对接口App进行实例化。
Private Sub ThisAddIn_Startup() Handles Me.Startup
App = Globals.ThisAddIn.Application
End Sub
这段代码的意思是,在加载项启动时(Word显示启动画面时,正是加载项启动的时候),获取当前运行的Word实例,并赋值给尚未实例化的接口App。这跟开发具体的功能有很大的关系,因为我们要通过这个接口来对Word文档进行操作。
好了,路已经铺好了,熟悉VBA的同学马上就可以自己玩儿去了,只要把VBA中的Application全部改成这里的App就可以了。不过还是来看简单的一个例子。
当我们从网页等地方复制文本时,有时会伴随着大量讨厌的空行,下面我们就通过代码来去除这些空行。
1.在Ribbon栏上放置一个按钮,更改名字为btnDeleteEmptyLine,标题为“删除空行”。然后在设计界面时双击它,进入代码编辑模式。
2.为了编写代码的便利,在首行先引入一个命名空间。
Imports Microsoft.Office.Interop.Word
3.然后编写如下代码,以实现具体的功能:
Private Sub btnDeleteEmptyLine_Click(sender As Object, e As RibbonControlEventArgs) Handles btnDeleteEmptyLine.Click
If App.Selection.Start = App.Selection.End Then App.ActiveDocument.Select()
With App.Selection.Find
.ClearFormatting()
.Text = "^p^p"
.MatchWildcards = False
.Forward = True
.Replacement.ClearFormatting()
.Replacement.Text = "^p"
.Execute(Replace:=WdReplace.wdReplaceAll)
End With
End Sub
3.单击VS工具栏上的启动按钮,片刻后Word就启动了,开始了调试过程。我们可以测试代码是否按预期工作。
这个例子其实是调用了Word的查找替换功能来实现删除空行的目的,用VBA也能完成。
那么VSTO相较于VBA,其优越性体现在哪里呢?我认为有以下几个方面:
1.VSTO可以用最新的VS以VB.net和C#等语言进行开发,而VBA基于老旧的VB6.0,不光是语法,连开发环境都几乎照搬,代码会写得很不舒服。
2.VBA是存储在文档中的,没有做到功能与文档的分离;而VSTO可以做到。而Office移动版会拒绝打开带有宏和VBA的文档,给人带来不便。
3.VSTO可以使用.net Framework提供的丰富的类库,轻松地实现五花八门的功能,相对来说,用VBA实现就比较麻烦。
4.与VB6.0一样,VBA对Unicode的支持不良,无法读取以UTF-8、UTF-16等编码的文本,只支持以系统默认代码页(ANSI)编码的文本;而VSTO根本没有这种问题。
当然VBA相较于VSTO唯一的优点是轻便,由Office程序内置,而开发VSTO外接程序要安装VS。而综合来看,肯定是VSTO的潜力要优于VBA的。
好了,入门就到这里了,大家自己玩去吧!