dingsir的个人博客分享 http://blog.sciencenet.cn/u/dingsir

博文

详解用XML 定义Word/Excel的弹出菜单

已有 2947 次阅读 2017-10-26 13:29 |个人分类:软件杂谈|系统分类:教学心得|关键词:Office,Word,Excel,弹出菜单,快捷菜单,自定义,XML格式,按钮,子菜单| EXCEL, office, word, 弹出菜单, 快捷菜单

update:  2017-11-18 增加极简介绍

先来点极简介绍:


1.看看我的电脑上EXCEL的弹出菜单是不是有点不一样?



2.背后的XML规定是这样的.


以下讲讲怎么做,例子与上面有所不同.

---------------------

你想根据自己的需要隐藏掉弹出菜单中某些不常用的菜单项吗? 抑或是增加一些自己需要的特定功能,或者在弹出菜单下增加“上标”、“下标”、“保存”等常用的命令? 如果是,请往下看,我这里要讲的就是“定制“自己的个性化弹出菜单。

该技术不仅适用于WORD,也适用EXCEL,Powerpoint等Office应用程序。 文中以Excel为例 。

微软自Office 2007起采用了Ribbon风格的控件,这种方式条理清晰,易于学习(对新手来讲,对老手反而是个麻烦).后期在Office2013, 2016还提供了对Ribbon界面的自定义修订, 使用起来很方便. 可惜的是, 不知为何,微软取在Office2007之后取消了原来比较便捷的右键弹出菜单的自定义方式,即通过”自定义-快捷菜单”来调出自定义界面,现在这个方式不支持了.

不过,Office其实并没有关上自定义弹出菜单的大门.还是有几种方法可以对弹出菜单(或Ribbon界面)进行自定义的。

第一种方法: 通过VBA编程或VSTO编程或加装外部插件. 可以对弹出菜单进行来各种定义的. 不过普通用户如果没有掌握VBA或VSTO编程,这一技术有点复杂。因为不是本文的重点,这里不作解释。 不过,网上可以搜索到非常多的用VBA编程来定制菜单的方法和代码。

'删除WORD的弹出菜单中不常用的"同义词库" 菜单项.

Sub HideThesaurusButton()

   For i = 1 To CommandBars("Text").Controls.Count

       If InStr(CommandBars("Text").Controls(i).Caption, "同义词") > 0 Then

          CommandBars("Text").Controls(i).Delete

           Beep

           Exit For

       End If

   Next i

End Sub


第二种方法. 通过编辑XML文件自定义界面.  也是本文要讲的重点.

在Office 2007起, 它提供了一种新的自定义方式,即通过XML文件来定义office的界面, 也包括对弹出菜单的订制.

先讲一下具体的操作程序[①]

1.在桌面新建一个目录,名为 customUI.(这个目录名可以是其它名字,只要保证第10步建立文档与自定义界面的关系时写法一致即可以,这里用这个名字演示)

2.使用文本编辑器创建自定义界面的文件. (不要用Windows自带的记事本,可以用UltraEdit, Emeditor, Notepad2, Notepad++等文本编辑器) 编辑XML内容,具体做法下面详述.文件保存为 customUI.xml (或其它名字), 保存到刚才创建的customUI目录. 如果有中文的内容,请注意用UTF-8格式保存. 用ANSI编码保存中文可能在打开时出错.后面详述.

3.验证编写的XML标记是否合规(可选).

4.在Office应用中新建一个文件,随便输入一点内容,然后保存为OfficeOpen XML格式文件,也就是扩展名最后是x或m的文件格式. (如 .docx,.docm, .xlsx, .xlsm, .pptm, 或 .pptx). 文件中有VBA代码(“宏”)的要保存为含m后缀的格式(如.docm, .dotm,.xlsm,.xltm,pptm),  这种格式允许存放能够为Ribbon扩展命令和组件调用的VBA代码.

5.退出Office应用.

6.在资源管理器中,给刚才保存的文件(如XXX.docm, yyy.xlsm等)的扩展名末尾再增加一个后缀.zip, 把它变成一个ZIP文件.然后双击,作为一个压缩文件夹打开.

这里有人可能觉得有点费解,为什么docm文件加上.zip后缀就可以打开? 其实背后的逻辑很简单,所谓的 .docm 或.xlsm文件本身实际上就是一个ZIP格式的文件, 采用.docm或.xlsm只是为了方便office程序识别它们是WORD或EXCEL的数据文件.因此将其后缀改为ZIP并没有问题,可以正常打开.

7.customUI目录拖放到上面的压缩文件夹中. (将自定义文件加入到文件容器).

8.将压缩文件夹下的_rels 目录拖放到桌面. _rels 目录包含了.rels 文件(这个文件没有文件名,只有一个后缀,但是可以在文本编辑器中正常的打开和编辑, 注意不要修改这个文件名)

9.用文本编辑器打开这个.rels 文件.

10.在.rels文件最末尾的 <Relationship> 元素和封闭的 <Relationships>元素之间(注意后面这个标签带有s), 加入一行语句, 以创建文档文件和自定义文件的关系. 例如

<<Relationship Id="Rb4af401bff6346e8" Type="http://schemas.microsoft.com/office/2007/relationships/ui/extensibility"  Target="DxhcustomUI/DxhModifiedUI.xml" />

注意: 这里Target后面的值是自定义界面的文件的相对路径.这个要与第1步的文件名和路径都相符. 即你刚才在ZIP压缩文件夹里放的自定义界面文件,如CustomUI.xml(或随便其它名字);注意XML是区分大小写的; id值可以任意指定,有唯一性即可.

这一步其实很关键,它告诉Office这个定义文件放在哪个目录,写错了Office找不到XML定义,就只好调用默认的设置了,你的订制效果就出不来.

11.保存.rels 文件.

12.将修改过的.rels 从桌面(刚才释放在桌面的目录里)拖放到压缩文件夹下面的_rels 目录目录,以替换掉原来的 .rels 文件.

13.去除文档刚才附加的.zip后缀,变回原来的文件名. 当你再在Office应用中打开该文件时,界面的订制效果就会出现.

以上操作的基本思路,就是  a)在rels目录下的.resl文件中增加一个关系,指定自定义界面的xml文件放在哪里. b)在指定的xml文件中编写内容,规定菜单项的调整内容.

其实上面13步, 真正的订制内容在第2步,编写XML文件来定义界面.

下面举个我已经写好的例子,是个扩展名为xml的文件.(为了充分演示例子比较长, 如果你需要订制的地方不多,完全可以不必这么复杂)

如果看不明白可以跳过直接往下看 示例  


<customUI xmlns="http://schemas.microsoft.com/office/2009/07/customui">

<contextMenus>

<contextMenu idMso="ContextMenuText">

<!--更新于2017-10-25by dingsir@qq.com -->


<!--以下为增加命令 -->

<!--增加保存按钮到菜单 -->

<button idMso="FileSave" insertBeforeMso="Cut" />

<!--粘贴文本-->

<button idMso="PasteTextOnly" insertBeforeMso="Cut" />

<!--插入脚注 -->

<button idMso="FootnoteInsert" insertBeforeMso="SymbolsDialog" />

<!--插入尾注-->

<button idMso="EndnoteInsertWord" insertBeforeMso="SymbolsDialog"  />

<!--下标-->

<toggleButton idMso="Subscript" insertBeforeMso="SymbolsDialog" />

<!--上标 -->

<toggleButton idMso="Superscript" insertBeforeMso="SymbolsDialog" />

<!--分隔线-->

<menuSeparator id="MySeparator1" insertBeforeMso="Cut" />

<!--将以下几个按钮隐藏 -->

<!--粘贴选项 -->

<gallery idMso="PasteGalleryMini" visible="false" />

<!--汉字重选 -->

<button idMso="ImeReconvert" visible="false" />

<!--英语助手 -->

<button idMso="EnglishAssistance" visible="false" />

<!--翻译 -->

<button idMso="Translate" visible="false" />

<!--智能搜索 -->

<button idMso="Insights" visible="false" />

<!--超链接 -->

<button idMso="HyperlinkInsert" visible="false" />

<!--隐藏结束 -->

<menuSeparator id="MySeparator" insertBeforeMso="InsertNewComment" />

<!--增加myButton按钮-->

<button id="MyButton" label="My Button" onAction="GetButtonID" />

<!--增加子菜单 -->

<menu id="MySubMenu" label="My Submenu">

<button id="MyButton2" label="Button on submenu" onAction="btnAction" />

</menu>

<!--增加多选按钮 -->

<gallery id="galleryOne" label="MyGallery" >

<item id="item1" imageMso="HappyFace" />

<item id="item2" imageMso="HappyFace" />

<item id="item3" imageMso="HappyFace" />

<item id="item4" imageMso="HappyFace" />

</gallery>

<!--增加动态菜单,其菜单根据VBA代码动态生成,详见方法的代码-->

<dynamicMenu id="MyDynamicMenu" label="My Dynamic Menu" getContent="GetMyContent" />

</contextMenu>

</contextMenus>

</customUI>


该XML结构是这样的.


实际运行的结果是这样的


如果你需要将某个按钮或菜单项添加到弹出菜单, 需要这么几个信息:

1. 知道你要添加的弹出菜单,它在XML定义中叫什么名字.比如说WORD中处理文本的弹出菜单叫ContextMenuText, Excel中处理单元格的弹出菜单叫ContextMenuCell.

2. 知道这个按钮或菜单项的内部名字.可以通过微软提供的idMso清单找(见本文末尾的参考阅读4或本文的附件内素材),也可以在office界面定义上的提示找.前者通过英文与中文的意思,在ExcelControls.xlsx或WorkControls.xlsx中找, 这个要求你懂英文;  后者的方法更简单点,如下:


3.根据菜单命令的类型编写标记.

该XML文件支持以下控件类型.

control

button

checkBox

dynamicMenu

gallery

menu

menuSeparator

splitButton

toggleButton

注意以上示例中,如果该控件是Office自已本来就有的控件, 名字用idMso 属性来表示, 如果是用户自己新规定的,用id来表示.

(完整的XML标记语言的规范,参见末尾的扩展阅读5)


举几个例子来讲一下怎么编写xml

---------------------------------XML命令解释--------------------------------------------

增加菜单项

增加内部已定义的按钮

<button idMso="FileSave" insertBeforeMso="Cut" />

表示要增加一个FileSave按钮(即文件保存),它是内置的命令(用idMso属性指定),插入的位置在 “Cut”命令(菜单上显示为“剪切”)的前面.

如果你想规定在某命令之后插入,可以使用类似的 insertAfterMso, 将上面的Before修改为After即可.

如果你需要更改内部命令的名字,可以用label 属性来指定.比如

<button idMso="FileSave" label="保存当前文件"  insertBeforeMso="Cut" />

增加一个已定义的切换按钮

   <toggleButton idMso="Subscript" insertBeforeMso="SymbolsDialog" />

表示要增加一个下标按钮,插入到”插入字符”菜单项前面.


增加一个菜单分隔线

<menuSeparator id="MySeparator" insertBeforeMso="InsertNewComment" />

表示在”插入批注”前面加入一个菜单分隔线. 它的ID可以由你指定,不是内置的,所以你可以看到.这个属性是由id而不是idMso指定的.


需要用到VBA的定制

增加新定义的按钮

增加新定义的按钮或功能,需要用到VBA代码,因此,保存这些定义的文档必须是docm或xlsm或pptm这种扩展名末尾为m的文件格式. 对VBA不了解的这一节可以路过.


例如:

<button id="MyButton" label="MyButton" onAction="GetButtonID"/>

表示在菜单上增加一个名字叫MyButton的按钮,它显示的标题(你看到菜单文字)是 My Button, 点击它, 它执行的动作(过程)叫GetButtonID.  GetButtonID是存放在文档中的VBA过程.它的签名(过程的标准样子) Sub OnAction(control As IRibbonControl), 实际执行的代码示例:

Sub GetButtonID(control As IRibbonControl)

   MsgBox ("你刚点击了" & control.ID & " 按钮.")

End Sub


增加新定义的子菜单

<menu id="MySubMenu" label="子菜单示例">

       <button id="MyButton2" label="Button2 onsubmenu" onAction="btnAction" />

<button id="MyButton3"  label="Button3 onsubmenu" onAction="btnAction" />

</menu>

这是一个名称MySubMenu 标题”子菜单示例”的子菜单,它下一级包括两个按钮,按钮的标题稍有不同,但响应点击的行为都是同一个过程btnAction.


增加新定义的动态菜单

所谓动态菜单就是用户文档为Office提供一个XML格式的字符串,里面定义了菜单的样式.这个内容通过过程返回给Office,从而指导Offiice生成的新菜单项

示例:

<dynamicMenu id="MyDynamicMenu" label="My DynamicMenu" getContent="GetMyContent" />


这个过程的样式签名:   Sub GetContent(controlAs IRibbonControl, ByRef content)

实际代码举例:

Sub GetMyContent(control As IRibbonControl,ByRef content)

  Dim xmlString As String

  xmlString = "<menu xmlns=""http://schemas.microsoft.com/office/2009/07/customui""><button id=""btn1"" imageMso=""HappyFace"" label=""Click Me"" onAction=""btnAction"" />"

  xmlString = xmlString & "<menu id=""mnu"" label=""My Dynamic Menu""> " & _

      "<button id=""btn2"" imageMso=""RecurrenceEdit""  /> " & _

      "<button id=""btn3"" imageMso=""CreateReportFromWizard""  /> " & _

      "</menu>"

  content = xmlString & "</menu>"

End Sub

上述代码中,因为生成的字串在VBA中要用引号包围, 字串中的引号就得用两个引号来表示.

--------------------------------XML命令解释 结束------------------------------------


如果你不想这么麻烦,有一个工具帮你节省时间,你只需要编写自定义页面的xml文件就行,其它都由这个工具来完成 ---Office Custom UI Editor,下载地址见扩展阅读3. 由于是以前的版本没有继续更新了, 需要安装.net framework 3.0

最后,本文的内容在Office2016测试OK, 其它版本没有测试过. 内容参考或引用了以下扩展阅读的内容.


写完之后, 猛然发现,其实主要的困难都是在解释怎么编写XML文件以实现定制菜单. 弄明白之后其实也不复杂.

为方便你的试验,我提供了下面的附件, 测试文件.dotm就是含有自定义弹出菜单功能的文档. 素材 目录下还有office2016版几个主要组件的控件信息清单,可以用来查idMso值. 以及这个测试文档中有定义有关的文件及目录.

用XML格式定制WORD的弹出菜单.rar

补充: Excel 弹出菜单订制示例.rar



扩展阅读:

     1.    Customizing the 2007 OfficeFluent Ribbon for Developers

        Part 1 of 3: https://technet.microsoft.com/zh-cn/library/aa338202.aspx

        Part 2 of 3: https://msdn.microsoft.com/library/aa338199.aspx

        Part 3 of 3: https://msdn.microsoft.com/en-us/library/aa722523(v=office.12).aspx

     2.    Customizing Context Menus inOffice 2010

https://msdn.microsoft.com/en-us/library/office/ee691832(v=office.14).aspx

3. Office Custom UI Editor 下载

http://openxmldeveloper.org/blog/b/openxmldeveloper/archive/2009/08/06/7293.aspx

4. 控件的内部idMso名称(即Office Fluent User Interface Control Identifiers) 下载

Office 2016: https://www.microsoft.com/en-us/download/details.aspx?id=50745

Office 2013: https://www.microsoft.com/en-us/download/details.aspx?id=36798

Office 2010: https://www.microsoft.com/en-us/download/details.aspx?id=6627

5.  微软标准 Custom UI XML Markup Specification 下载

https://msdn.microsoft.com/en-us/library/cc313070(v=office.12).aspx


[①]参考 扩展阅读1的Part1之 Customizing the Fluent UI by Using Office Open XML Formats Files 部分




http://blog.sciencenet.cn/blog-1213210-1082506.html

上一篇:漫谈碳酸酯的化学特性及其在锂电池电解液中的应用
下一篇:电解液溶剂的比热容和锂盐溶解时的温升

0

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备14006957 )

GMT+8, 2019-12-9 16:17

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部