详解Office Add-in 清单文件
作者:陈希章 发表于2017年12月8日
前言
我们都知道,一个Office Add-in,最主要是由两个部分组成的:清单文件(manifest)和真正要用来执行的网站。
清单文件其实是一个标准的XML文件,它有固定的Schema。目前来说,最新版本的清单文件必须指定“http://schemas.microsoft.com/office/appforoffice/1.1”作为Schema,否则某些功能可能不能正常工作。当然,指定Schema这件事情你可能不太会需要手工去做,毕竟不管你是用Visual Studio的项目模板,还是用其他开发工具(例如Visual Studio Code),清单文件都是自动生成的,而且默认就已经指定了1.1这个版本。下面两篇文章介绍了如何在不同工具开始office Add-in的开发。
一个典型的清单文件看起来是下面这样的
在Visual Studio中,有时候会用可视化界面,取代纯文本的XML编辑界面,例如下面这样
平胸而论,Visual Studio 提供了对于清单文件的最佳编辑体验,因为它会自动根据Schema提供智能感知,甚至如你刚才看到的那样,它甚至提供了可视化界面,我爱死这个功能了。
下面我会从三个方面分别对清单文件进行详细介绍
- 基本属性定义
- 通过清单文件自定义Ribbon和快捷菜单
- 通过清单文件是实现多语言支持
基本属性定义
清单文件中的根元素是OfficeApp,这里会指定几个namespace,但同时会有一个至关重要的属性:xsi:type,目前我们支持三种不同类型的Office Add-in,分别是
- ContentApp,这是内容应用,主要是在Excel和PowerPoint中能用。通过这类Add-in,可以为宿主程序添加自定义的内容元素,例如一个自定义地图之类的。
- TaskPaneApp,这是应用最广的类型。通过这类Add-in,可以为宿主程序添加自定义的功能,例如通过一个自定义菜单,执行某些操作。
- MailApp,这是专用于Outlook的Add-in。
除此之外,OfficeApp这个根元素,还需要包含如下的基本元素
- Id,唯一的编号(一个GUID)
- Version,这个版本信息在你更新时可能需要修改
- ProviderName,作者及公司信息
- DefaultLocale,默认的语言,格式是类似于en-US这样的。我在下面还会介绍多语言支持的功能
- DisplayName,显示名称
- Description,描述
- IconUrl,图标文件路径(32*32,PNG格式)
- HighResolutionIconUrl,高清图片文件路径
- SupportUrl,技术支持网址
- AppDomains,如果你的应用中,需要导航到其他网站(不同域),则需要在这里定义。
- Hosts,宿主形式。因为一个Add-in其实可以同时用于几个不同的宿主(例如Word,Excel等),所以这里可以定义多个Host。
Document (Word)
Database (Access)
Mailbox (Outlook)
Notebook (OneNote)
Presentation (PowerPoint)
Project (Project)
Workbook (Excel)
- DefaultSettings,默认设置,这里最关键的属性有SourceLocation,这个是用来指定Add-in加载时默认显示的页面。另外,不同的Add-in可能还会有一些自己的DefaultSettings,例如ContentApp的话,还可以设置RequestedWidth和RequestedHeight这两个属性,以确定自定义内容默认的尺寸。
- Permissions,这是规定Add-in拥有的对于宿主和文档的访问权限,不同的Add-in有不同的Permission设置。
ContentApp 和 TaskPaneApp <Permissions> [Restricted | ReadDocument | ReadAllDocument | WriteDocument | ReadWriteDocument]</Permissions> MailApp <Permissions>[Restricted | ReadItem | ReadWriteItem | ReadWriteMailbox]</Permissions>
值得一提的是,如果你用Visual Studio 项目模板生成的清单文件,你会发现IconUrl以及SourceLocation 等属性,会包含一个特定的地址 ~remoteurl,这个其实会在工具进行编译和发布时自动替换为你的网站的根地址。而在Visual Studio code等工具中,你可能需要精确地设置。
通过清单文件自定义Ribbon
作为TaskPaneApp,最常见的做法是在启动后位宿主程序添加一个工具栏按钮,然后用户点击按钮的话,执行某个操作(打开内容面板和执行某个Javascript函数)。我在这一节主要介绍的是自定义Ribbon的方式。
有意思的是,要定义工具栏和清单,在清单文件中,我们称之为VersionOverrides。一个最简单的Ribbon定义如下
<VersionOverrides xmlns="http://schemas.microsoft.com/office/taskpaneappversionoverrides" xsi:type="VersionOverridesV1_0">
<Hosts>
<Host xsi:type="Workbook">
<DesktopFormFactor>
<GetStarted>
<Title resid="Contoso.GetStarted.Title"/>
<LearnMoreUrl resid="Contoso.GetStarted.LearnMoreUrl"/>
</GetStarted>
<!--函数文件,是定义可以直接被调用的Javascript函数所在的位置-->
<FunctionFile resid="Contoso.DesktopFunctionFile.Url" />
<!-- 扩展定义 -->
<ExtensionPoint xsi:type="PrimaryCommandSurface">
<!-- 如果是扩展现有的Tab,使用 OfficeTab .如果是创建新的Tab,则使用 CustomTab -->
<OfficeTab id="TabHome">
<!-- 这个id必须唯一,可以结合公司的名称. -->
<Group id="Contoso.Group1">
<Label resid="Contoso.Group1Label" />
<Icon>
<bt:Image size="16" resid="Contoso.tpicon_16x16" />
<bt:Image size="32" resid="Contoso.tpicon_32x32" />
<bt:Image size="80" resid="Contoso.tpicon_80x80" />
</Icon>
<Control xsi:type="Button" id="Contoso.TaskpaneButton">
<Label resid="Contoso.TaskpaneButton.Label" />
<Supertip>
<Title resid="Contoso.TaskpaneButton.Label" />
<Description resid="Contoso.TaskpaneButton.Tooltip" />
</Supertip>
<Icon>
<bt:Image size="16" resid="Contoso.tpicon_16x16" />
<bt:Image size="32" resid="Contoso.tpicon_32x32" />
<bt:Image size="80" resid="Contoso.tpicon_80x80" />
</Icon>
<!-- 下面这个方式是打开一个内容面板 -->
<Action xsi:type="ShowTaskpane">
<TaskpaneId>ButtonId1</TaskpaneId>
<SourceLocation resid="Contoso.Taskpane.Url" />
</Action>
<!-- 下面这个方式是执行一个Javascript函数-->
<Action xsi:type="ExecuteFunction">
<FunctionName>SubmitDataToServer</FunctionName>
</Action>
</Control>
</Group>
</OfficeTab>
</ExtensionPoint>
</DesktopFormFactor>
</Host>
</Hosts>
<!--目前规定所有的定义必须用资源的形式来做,避免重复定义 -->
<Resources>
<bt:Images>
<bt:Image id="Contoso.tpicon_16x16" DefaultValue="~remoteAppUrl/Images/Button16x16.png" />
<bt:Image id="Contoso.tpicon_32x32" DefaultValue="~remoteAppUrl/Images/Button32x32.png" />
<bt:Image id="Contoso.tpicon_80x80" DefaultValue="~remoteAppUrl/Images/Button80x80.png" />
</bt:Images>
<bt:Urls>
<bt:Url id="Contoso.DesktopFunctionFile.Url" DefaultValue="~remoteAppUrl/Functions/FunctionFile.html" />
<bt:Url id="Contoso.Taskpane.Url" DefaultValue="~remoteAppUrl/Home.html" />
<bt:Url id="Contoso.GetStarted.LearnMoreUrl" DefaultValue="https://go.microsoft.com/fwlink/?LinkId=276812" />
</bt:Urls>
<!-- ShortStrings 最长可以125. -->
<bt:ShortStrings>
<bt:String id="Contoso.TaskpaneButton.Label" DefaultValue="Show Taskpane" />
<bt:String id="Contoso.Group1Label" DefaultValue="Commands Group" />
<bt:String id="Contoso.GetStarted.Title" DefaultValue="Get started with your sample add-in!" />
</bt:ShortStrings>
<!-- LongStrings 最长可以250. -->
<bt:LongStrings>
<bt:String id="Contoso.TaskpaneButton.Tooltip" DefaultValue="Click to Show a Taskpane">
</bt:String>
<bt:String id="Contoso.GetStarted.Description" DefaultValue="Your sample add-in loaded succesfully. Go to the HOME tab and click the 'Show Taskpane' button to get started." />
</bt:LongStrings>
</Resources>
</VersionOverrides>
通过清单文件自定义快捷菜单(Context Menu)
除了Office Ribbon的自定义之外,目前也支持通过清单文件对快捷菜单进行自定义,例如下面这个例子,是给单元格的快捷菜单增加一个按钮。这个按钮,同样可以有两种操作:打开一个内容面板,还是直接执行一个Javascript函数。
<ExtensionPoint xsi:type="ContextMenu">
<OfficeMenu id="ContextMenuCell">
<!-- Define a control that shows a task pane. -->
<Control xsi:type="Button" id="Button2Id1">
<Label resid="Contoso.TaskpaneButton.Label" />
<Supertip>
<Title resid="Contoso.TaskpaneButton.Label" />
<Description resid="Contoso.TaskpaneButton.Tooltip" />
</Supertip>
<Icon>
<bt:Image size="16" resid="Contoso.tpicon_16x16" />
<bt:Image size="32" resid="Contoso.tpicon_32x32" />
<bt:Image size="80" resid="Contoso.tpicon_80x80" />
</Icon>
<Action xsi:type="ShowTaskpane">
<SourceLocation resid="Contoso.Taskpane.Url" />
</Action>
</Control>
</OfficeMenu>
</ExtensionPoint>
关于在内容面板中开发以及自定义Javascript函数的开发,我会通过另外一个专题文章来讲解。
通过清单文件实现多语言支持
Office Web Add-in的愿景是希望开发人员一次编写,处处运行——不光是在不同设备都能体验一致地工作,而且在全球都能使用。那么问题来了?如何实现这样的美好愿望呢?这个问题同样分为两个方面:通过清单文件来无代码实现UI层面的多语言支持,以及在Javascript代码中根据当前的环境实现自定义多语言支持。
后者相对简单,而且更多的是依赖于开发人员的自定义实现,这里列出来两个非常重要的属性:
- Office.context.displayLanguage,这个属性能获取到当前Office宿主程序的显示语言。代码范例如下
function sayHelloWithDisplayLanguage() {
var myLanguage = Office.context.displayLanguage;
switch (myLanguage) {
case 'en-US':
write('Hello!');
break;
case 'fr-FR':
write('Bonjour!');
break;
}
} // Function that writes to a div with id='message' on the page.
function write(message) {
document.getElementById('message').innerText += message;
}
- Office.context.contentLanguage,这个属性我觉得很酷,它是能检测当前文档内容的语言,例如是一篇中文的Word文档,还是一个英文的Excel表格。
function sayHelloWithContentLanguage() {
var myLanguage = Office.context.contentLanguage;
switch (myLanguage) {
case 'en-US':
write('Hello!');
break;
case 'fr-FR':
write('Bonjour!');
break;
}
} // Function that writes to a div with id='message' on the page.
function write(message) {
document.getElementById('message').innerText += message;
}
接下来要看一下的是在清单文件中如果定义一些UI层面的多语言支持。目前有如下的属性是支持多语言的。
- Description,这是Add-in的描述,定义方式如下
<Description DefaultValue="ExcelWebAddIn2">
<Override Locale="zh-CN" Value="我的插件描述说明......"/>
</Description>
- DisplayName,这是Add-in的显示名称,定义方式如下
<DisplayName DefaultValue="ExcelWebAddIn2">
<Override Locale="zh-CN" Value="我的第二个插件"/>
</DisplayName>
- IconUrl,这是Add-in的图标
<IconUrl DefaultValue="~remoteAppUrl/Images/Button32x32.png">
<Override Locale="zh-CN" Value="~remoteAppUrl/Images/zh-Button32x32.png"/>
</IconUrl>
- HighResolutionIconUrl,这是Add-in的高清图标,定义方式如下
<HighResolutionIconUrl DefaultValue="~remoteAppUrl/Images/Button32x32.png">
<Override Locale="zh-CN" Value="~remoteAppUrl/Images/zh-Button32x32.png"/>
</IconUrl>
- Resources,所有针对界面扩展(例如工具栏或者快捷菜单的按钮相关的文字,路径,图片等),定义方式大多如下
<bt:String id="Contoso.TaskpaneButton.Tooltip" DefaultValue="Click to Show a Taskpane">
<bt:Override Locale="zh-CN" Value="显示一个内容面板"/>
</bt:String>
- SourceLocation
<SourceLocation DefaultValue="~remoteAppUrl/Home.html">
<Override Locale="zh-CN" Value="~remoteAppUrl/zh-Home.html"/>
</SourceLocation>
关于所有目前支持的语言列表,请参考
关于Office Add-in的本地化支持,官方文档在 https://docs.microsoft.com/en-us/office/dev/add-ins/develop/localization。
其他注意事项
确保add-in ID是唯一的,这是一个GUID。如果使用Visual Studio开发的话,可以在工具菜单中,找到Create GUID的一个小工具,但也可以通过其他一些方式生成。
所有的Url都必须是https的。
所有的图片(例如用在命令按钮上面的图片),都必须是允许缓存,也就是说服务器不能在Header里面添加on-cache/no-store 这样的值。
如果add-in需要发布到Office Store,则必须提供SupportUrl这个属性。
详解Office Add-in 清单文件的更多相关文章
- 详解Github的.gitignore忽略文件+.gitignore不生效解决方案+生产配置大奉送
详解Github的.gitignore忽略文件+.gitignore不生效解决方案+生产配置大奉送 Git中有一个非常重要的一个文件-----.gitignore 今天给大家免费送一个.gitigno ...
- Mybatis系列全解(五):全网最全!详解Mybatis的Mapper映射文件
封面:洛小汐 作者:潘潘 若不是生活所迫,谁愿意背负一身才华. 前言 上节我们介绍了 < Mybatis系列全解(四):全网最全!Mybatis配置文件 XML 全貌详解 >,内容很详细( ...
- FFmpeg(2)-avformat_open_input()函数详解并示例打开mp4文件
一. 解封装 pts 是显示的时间 dts是解码的时间, 这个时间是用来做同步. av_register_all(), 注册所有的格式.包括解封装格式和加封装格式. avformat_network_ ...
- ulimit 命令详解 socket查看linux最大文件打开数
ulimit 命令详解 Linux对于每个用户,系统限制其最大进程数.为提高性能,可以根据设备资源情况,设置各linux 用户的最大进程数 可以用ulimit -a 来显示当前的各种用户进程限 ...
- 详解Office 外接程序 COM Add In的LoadBehavior及其妙用
Office的所有COM Add In,包括用Shared Add In模板和VSTO Add In模板创建的,都会在注表里面存储一些信息.对于当前用户安装的Add In,以Excel为例,对应的注册 ...
- tar命令的实用详解(C参数和排除文件 --exclude)
一.tar:从压缩包中解压出指定文件 [root@d176 test]# tar ztf nrpe-2.12.tar.gz |grep srcnrpe-2.12/src/nrpe-2.12/src/. ...
- 详解COM Add In的LoadBehavior及其妙用
Office的所有COM Add In,包括用Shared Add In模板和VSTO Add In模板创建的,都会在注册表里面存储一些信息. 对于当前用户安装的Add In,以Excel为例,对应 ...
- Hadoop IO 特性详解(2)【文件校验】
(本文引用了microheart,ggjucheng的一些资料,在此感谢.charles觉得知识无价,开源共享无价) 这一次我们接着分析文件IO校验的相关代码,看看最底层是如何实现这种大数据集的文件校 ...
- (原创)详解Quartus导出网表文件:.qxp和.vqm
当项目过程中,不想给甲方源码时,该如何?我们可以用网表文件qxp或者vqm对资源进行保护. 下面讲解这两个文件的具体生成步骤: 一.基本概念 QuartusII的qxp文件为QuartusII Exp ...
随机推荐
- ionic生成apk使用build命令下载gradle-2.2.1-all.zip卡,解决方案
ionic生成apk使用build命令下载gradle-2.2.1-all.zip卡,解决方案 直接使用ionic build android命令,自动下载gradle-2.2.1-all.zip超慢 ...
- C#执行PowserShell 脚本
Windows PowserShell能够很简洁 快速通过Script脚本方式获得我们想要执行效果. 如何在C#中任意执行PowerShell脚本.?类似目前我要在做一个进程管理工具. 通过Power ...
- ARM1
CPU有取指周期,译码周期,执行周期包括的器件有程序计数器(CP),指令cache,数据总线,指令寄存器(IR),数据地址寄存器(AR),指令译码器,时序发生器操作控制器,控制总线,数据缓冲寄存器(D ...
- Socket网络编程之概述理解
今天主要讲讲什么是socket网络编程 socketde 英文原义是"孔"或者"插座".是进程通讯的一种方式,即调用这个网络库的一些API函数实现分布在不同主机 ...
- 深入浅出Java动态代理
文章首发于[博客园-陈树义],点击跳转到原文深入浅出Java动态代理 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中,更是有举足轻重的地位.代理 ...
- java.lang.Collections
java.lang.Collections 此类完全由在collection上进行操作或返回 collection 的静态方法组成.也就是说Collections提供了对Collection集合操作的 ...
- MySql的虚拟机和Xshell5的连接过程
给大家介绍一下虚拟机和Xshell5连接的基本配置1.安装虚拟机,跟着提示一步一步安装即可,注意添加镜像文件,虚拟机就完成了.2.下载一个Xshell5,安装好之后.要修改虚拟机的网卡状态 1) ...
- 关于事件mouseover ,mouseout ,mouseenter,mouseleave的区别
轮播中大多会选择mouseover和mouseout 这个时候是没有任何问题的 但当遇到有css3动画的时候,会发现移入移出过快 动画还没加载完成就需要执行下一个动画,完了动画样式就错乱了. 这时候 ...
- 《用Java写一个通用的服务器程序》03 处理新socket
在讲监听器时说过处理的新的socket要尽快返回,监听器调用的是ClientFactory的createPhysicalConnection方法,那么就来看这个方法: public boolean c ...
- 算法帖——用舞蹈链算法(Dancing Links)求解俄罗斯方块覆盖问题
问题的提出:如下图,用13块俄罗斯方块覆盖8*8的正方形.如何用计算机求解? 解决这类问题的方法不一而足,然而核心思想都是穷举法,不同的方法仅仅是对穷举法进行了优化 用13块不同形状的俄罗斯方块(每个 ...