VSTO 學習筆記(十)Office 2010 Ribbon開發
微軟的Office系列辦公套件從Office 2007開始首次引入了Ribbon導航菜單模式,其將一系列相關的功能集成在一個個Ribbon中,便于集中管理、操作。這種Ribbon是高度可定制的,用戶可以將自己常用的功能進行單獨設置,提高工作效率。但是由于Office 2003時代用戶的操作習慣已經養成,結果到了Office 2007很多菜單、按鈕都找不到了,著實有些尷尬。經過一段時間的適應,相信大多數用戶已經習慣Ribbon式的界面了。到了Office 2010時代,微軟已經將所有Office產品加上了Ribbon界面:
本系列所有示例代碼均在 Visual Studio 2010 Ultimate RTM + Office 2010 Professional Plus RTM x64 中測試通過
轉載請注明出處:http://www.rzrgm.cn/brooks-dotnet/archive/2010/12/31/1923519.html
Word 2010
Excel 2010
PowerPoint 2010
Publisher 2010
Project 2010
Visio 2010
Access 2010
SharePoint Workspace 2010(原Groove)
也有很多軟件也推出了Ribbon界面,著名的如Autodesk系列、WinZip、Xencoder等:
作為開發人員我們就想如何才能開發這種Ribbon界面。我查找了一些資料,整理如下,如果你有更好的方案,歡迎補充。
Developer Audience
The Windows Ribbon framework is designed for use by C/C++ developers and UI designers.
Recommended proficiencies:
- COM programming
- Windows API programming
- XML/XAML programming
Recommended foundational knowledge:
- UI programming concepts
- General UI concepts
Minimum Requirements
Minimum supported client | Windows 7 Windows Vista with Service Pack 2 (SP2) and Platform Update for Windows Vista |
Minimum supported server | Windows Server 2008 R2 Windows Server 2008 with SP2 and Platform Update for Windows Server 2008 |
Windows Software Development Kit (SDK) | 7.0 |
Header and IDL files | uiribbon.h, uiribbon.idl |
二、Office 2010 AddIns
Office PIA中提供了接口、類來對Ribbon進行操作,可以參見我之前的一篇博文:VSTO學習筆記(三) 開發Office 2010 64位COM加載項
主要利用CommandBar類進行相關操作。利用Office PIA操作Ribbon很不直觀,需要控制很多細節,但是非常靈活,可以最大程度的自定義Ribbon。
三、OpenXML SDK 2.0
如果你還沒有安裝OpenXML SDK 2.0,可以在這里下載。
Office 2007時代首次推出了OpenXML格式,并且通過了ISO國際標準。OpenXML格式有諸多好處,微軟也發布了OpenXML SDK來對Office 2007、Office 2010的文檔進行操作,提供了除Office PIA之外的另一種選擇。采用OpenXML格式的Office文檔實際上就是一個標準ZIP壓縮包,可以將一個Office文檔的擴展名修改為.zip并解壓縮來查看其中的內容。
用戶自定的Ribbon在OpenXML中保存在一個名為customUI.xml的XML文件中,如圖,我打開了一個包含有加載宏的Word 2010文檔,其中有一個自定義Ribbon,Office Developer Resources:
將這個文檔的擴展名修改為.zip:
可以看到其文檔結構,在customUI文件夾下保存了用戶自定義Ribbon的信息:
打開customUI文件:
可以看到用戶自定義Ribbon的具體描述,customUI.xml需要遵循Office 2010的XML架構規范,可以在這里下載。Office 2007的XML架構規范可以在這里下載。
下載下來解壓縮后,是一個xsd文件,查找關于Ribbon的部分:
閱讀這個xsd文件需要有一定的XML Schema基礎,我們只需要大概了解即可,主要為了后面添加自定義的customUI文件。OpenXML SDK 2.0對此提供了支持,可以對Ribbon進行控制:
下面我們給一個Word 2010的文檔添加一個自定義Ribbon。
首先準備customUI.xml文件,寫入如下內容:
<customUI xmlns='http://schemas.microsoft.com/office/2006/01/customui'>
<ribbon>
<tabs>
<tab id='odcTab' label='Office Developer Resources' >
<group id='getStartedGrp' label='Getting Started' >
<button id='devCenterBtn' label='Office' size='normal' image='MSDN' tag='http://msdn.microsoft.com/en-us/office/default.aspx' onAction='openPage' screentip='Learn about the possibilities offered by the Microsoft Office system to develop solutions.' />
<button id='spBtn' label='SharePoint' size='normal' image='MSDN' tag='http://msdn.microsoft.com/en-us/sharepoint/default.aspx' onAction='openPage' screentip='Helps teams stay connected and productive by providing easy access to the people, documents, and information that they need.' />
<button id='devMapBtn' label='Developer Map' size='normal' imageMso='ShowTimeZones' tag='http://msdn.microsoft.com/en-us/office/bb497969.aspx' onAction='openPage' screentip='Helps you visualize the different programs, servers, services, and tools that will help build Office solutions.' />
</group>
<group id='productsGrp' label='Products and Technologies' >
<button id='officeSysBtn' label='Office System ' size='normal' image='officesystem' tag='http://msdn.microsoft.com/en-us/office/aa905369.aspx' onAction='openPage' screentip='A powerful collection of integrated programs, servers, services, tools, and technologies.' />
<gallery id='productsGal' label='Products' size='normal' imageMso='SmartArtChangeColorsGallery' onAction='galOpenPage' screentip='Get the help and information you need on each Office product.' >
<item id='Access' label='Access' imageMso='MicrosoftAccess' />
<item id='Excel' label='Excel' imageMso='MicrosoftExcel' />
<item id='InfoPath' label='InfoPath' imageMso='OpenInfopathForm' />
<item id='Outlook' label='Outlook' imageMso='MicrosoftOutlook' />
<item id='PowerPoint' label='PowerPoint' imageMso='MicrosoftPowerPoint' />
<item id='Project' label='Project' imageMso='MicrosoftProject' />
<item id='SPDesigner' label='SharePoint Designer' imageMso='AccessOnlineLists'/>
<item id='SharePoint' label='SharePoint Server' imageMso='FileCreateDocumentWorkspace' />
<item id='Visio' label='Visio' imageMso='TableExportTableToVisioPivotDiagram' />
<item id='Word' label='Word' imageMso='ExportWord' />
</gallery>
<gallery id='technologiesGal' label='Technologies' imageMso='PageMenu' onAction='galOpenPage' screentip='Learn about the technologies supported by the Microsoft Office system.' >
<item id='OBA' label='OBA' imageMso='CreateClassModule' />
<item id='FluentUI' label='Office Fluent UI' imageMso='FormRegionMenu' />
<item id='OpenXML' label='Open XML' imageMso='FileSaveAsCurrentFileFormat' />
<item id='VBA' label='VBA' imageMso='CreateModule' />
<item id='VSTO' label='VSTO' image='VSTO' />
</gallery>
</group>
<group id='libraryGrp' label='Library' >
<button id='offSysBtn' label='Office Development' size='normal' imageMso='AppointmentColorDialog' tag='http://msdn.microsoft.com/en-us/library/bb726436.aspx' onAction='openPage' screentip='A set of helpful links to get you up to speed on Office development.' />
<button id='spDevBtn' label='SharePoint Development' size='normal' imageMso='AccessOnlineLists' tag='http://msdn.microsoft.com/en-us/library/bb931739.aspx' onAction='openPage' screentip='A set of helpful links to get you up to speed on SharePoint products and technologies.' />
<button id='officeTalkBtn' label='Office Talk' size='normal' imageMso='MailSelectNames' tag='http://msdn.microsoft.com/en-us/library/bb660514(office.11).aspx' onAction='openPage' screentip='Columns by long-time Office developers and members of the Office Developer Documentation team.' />
</group>
<group id='learnGrp' label='Learn' >
<button id='offDevelopmentBtn' label='Learn Office' size='normal' imageMso='AppointmentColorDialog' tag='http://msdn.microsoft.com/en-us/office/aa905375.aspx' onAction='openPage' screentip='Explore this set of helpful links to get you up-to-speed creating Office system solutions.' />
<button id='sdkAndRefDocsBtn' label='SDKs and References' size='normal' imageMso='FunctionsLookupReferenceInsertGallery' tag='http://msdn.microsoft.com/en-us/office/aa905496.aspx' onAction='openPage' screentip='Use these SDKs and developer references to leverage your skills in creating rich Office and SharePoint solutions.' />
<button id='booksdBtn' label='Books' size='normal' imageMso='VisualBasicReferences' tag='http://msdn.microsoft.com/en-us/office/dd537534.aspx' onAction='openPage' screentip='Want to buy a book? Read a sample chapter online? Visit this bookstore first.' />
<button id='howDoIBtn' label='How To Center' size='normal' imageMso='TentativeAcceptInvitation' tag='http://msdn.microsoft.com/en-us/office/bb266408.aspx' onAction='openPage' screentip='Find over 200 how-to video demos, sample code, and conceptual overviews.' />
<button id='videosBtn' label='Videos and Webcasts' size='normal' imageMso='SlideMasterMediaPlaceholderInsert' tag='http://msdn.microsoft.com/en-us/office/aa905350.aspx' onAction='openPage' screentip='Need information quickly? No time to read about it? Watch these videos.' />
<button id='channel9Btn' label='Channel 9' size='normal' image='Channel9' tag='http://channel9.msdn.com/tags/MS%20Office' onAction='openPage' screentip='Channel 9 is a place for learning and sharing information, created by developers for developers.' />
</group>
<group id='communityGrp' label='Community' >
<button id='communityBtn' label='Office Developers' size='normal' imageMso='OutlookGears' tag='http://msdn.microsoft.com/en-us/office/aa905341.aspx' onAction='openPage' screentip='Check out the latest from the Office developer community.' />
<button id='mvpBtn' label='MVP Content' size='normal' imageMso='MeetingsWorkspace' tag='http://msdn.microsoft.com/en-us/office/cc441428.aspx' onAction='openPage' screentip='Take a look at the latest content submitted by Office and SharePoint MVPs, third-parties, and experts in the Office developer community.' />
<button id='codePlexBtn' label='CodePlex' size='normal' image='CodePlex' tag='http://www.codeplex.com/site/search?projectSearchText=office' onAction='openPage' screentip='Provides you with access to a variety of resources, including download areas, communication forums and product information.' />
<button id='codeGalleryBtn' label='Code Gallery' size='normal' image='CodeGallery' tag='http://code.msdn.microsoft.com/Project/ProjectDirectory.aspx?ProjectSearchText=office' onAction='openPage' screentip='Download and share sample applications, code snippets, and other resources with the developer community.' />
<button id='facebookBtn' label='facebook' size='normal' image='facebook' tag='http://www.facebook.com/group.php?gid=51196093535' onAction='openPage' screentip='A place for comments, questions, and answers about development with Office products.' />
<button id='twitterBtn' label='Twitter' size='normal' image='twitter' tag='http://twitter.com/MSDN_Office' onAction='openPage' screentip='Follow what is currently happening with Microsoft Office development.' />
</group>
<group id='supportGrp' label='Forums and Support' >
<button id='forumsBtn' label='Forums' size='normal' imageMso='WorkgroupAdmin' tag='http://social.msdn.microsoft.com/Forums/en-US/category/officedev,oldevelopment,sharepoint,uc/' onAction='openPage' screentip='Get your questions answered by experts in their respective Office products.' />
<button id='newsgroupBtn' label='Newsgroups' size='normal' imageMso='FileCreateDocumentWorkspace' tag='http://msdn.microsoft.com/en-us/office/aa905346.aspx' onAction='openPage' screentip='Ask questions, share information, or exchange ideas with others, including experts from around the globe.' />
<button id='supportBtn' label='Support' size='normal' imageMso='ControlsGallery' tag='http://msdn.microsoft.com/en-us/office/aa905515.aspx' onAction='openPage' screentip='Search to find a resource, ask a question in the forums, or contact Microsoft support for help.' />
</group>
</tab>
</tabs>
</ribbon>
</customUI>
注意為了避免轉義,全部使用了單引號。
使用OpenXML SDK 2.0添加此Ribbon:
使用OpenXML SDK 2.0添加此Ribbon:{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(v_strWordPath, true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
if (myDoc.GetPartsCountOfType<RibbonExtensibilityPart>() > 0)
myDoc.DeletePart(myDoc.GetPartsOfType<RibbonExtensibilityPart>().First());
RibbonExtensibilityPart ribbonExtensibilityPart = myDoc.AddNewPart<RibbonExtensibilityPart>();
ribbonExtensibilityPart.CustomUI = new DocumentFormat.OpenXml.Office.CustomUI.CustomUI(v_strCustomerXML);
}
}
運行后可以看到Word中出現了一個自定義Ribbon:
這個自定義Ribbon我取自MSDN上的一篇博客,原文地址。下面的這個例子就來自這篇博客,我對其進行了少許修改。
注:作者寫此Demo時使用的OpenXML SDK版本較老,導致在OpenXML SDK 2.0下編譯失敗,經查是一個類的繼承關系做了更改,我已經做了修正。
Demo2:將一個文檔中的Ribbon復制到另一個文檔中。
將一個文檔中的Ribbon復制到另一個文檔中{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(filename, true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
if (myDoc.GetPartsCountOfType<RibbonExtensibilityPart>() > 0)
myDoc.DeletePart(myDoc.GetPartsOfType<RibbonExtensibilityPart>().First());
myDoc.AddPart<RibbonExtensibilityPart>(customRibbonPart);
OpenXmlPart extendedPart = null;
foreach (IdPartPair partPair in mainPart.Parts)
{
if (partPair.OpenXmlPart.RelationshipType == "http://schemas.microsoft.com/office/2006/relationships/vbaProject")
{
extendedPart = partPair.OpenXmlPart;
break;
}
}
if (extendedPart != null)
mainPart.DeletePart(extendedPart);
if (vbaPart != null)
mainPart.AddPart<OpenXmlPart>(vbaPart);
}
}
static void ImportCustomUI(string templateFile, string outputFile)
{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(templateFile, true))
{
MainDocumentPart mainPart = myDoc.MainDocumentPart;
RibbonExtensibilityPart customRibbonPart = myDoc.GetPartsOfType<RibbonExtensibilityPart>().First();
OpenXmlPart vbaPart = null;
foreach (IdPartPair partPair in mainPart.Parts)
{
if (partPair.OpenXmlPart.RelationshipType == "http://schemas.microsoft.com/office/2006/relationships/vbaProject")
{
//vbaPart = (ExtendedPart)partPair.OpenXmlPart;
vbaPart = partPair.OpenXmlPart;
break;
}
}
AddCustomUIParts(outputFile, customRibbonPart, vbaPart);
ChangeDocumentType(outputFile);
}
}
static void ChangeDocumentType(string filename)
{
using (WordprocessingDocument myDoc = WordprocessingDocument.Open(filename, true))
{
myDoc.ChangeDocumentType(WordprocessingDocumentType.MacroEnabledDocument);
}
//注意因為包含了宏,必須要保存為.docm格式。
string newFileName = Path.GetDirectoryName(filename) + @"\" + Path.GetFileNameWithoutExtension(filename) + "(was docx).docm";
File.Move(filename, newFileName);
File.Delete(filename);
}
運行結果:
Alt + F11 打開VBA 7.0的編輯器,可以看到Ribbon中的事件處理函數:
函數的功能很簡單,是當點擊Ribbon中的按鈕時跳轉到指定網站,相當于一個瀏覽器收藏夾的作用。
四、VSTO 4.0 Ribbon Controls
安裝Visual Studio 2010的Office開發工具后,就可以使用VSTO 4.0來方便的進行Office開發了。
如圖我建立了一個Excel 2010 Workbook項目,Add Item時有一個可視化Ribbon的選項:
添加之后就可以像開發Windows Form一樣設計Ribbon,同時工具箱中葉出現了Office Ribbon Controls:
如上圖所示,我添加了一個Tab,分了4個組,每個組中添加了圖標按鈕,Excel中添加了一個Web Browser控件,當點擊相應按鈕時Web Browser跳轉到各自項目官方網站:
代碼void btnDF_Click(object sender, Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs e)
{
this.wbIE.Navigate("http://www.documentfoundation.org/");
}
void btnOracle_Click(object sender, Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs e)
{
this.wbIE.Navigate("http://www.openoffice.org/");
}
void btnOffice2010_Click(object sender, Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs e)
{
this.wbIE.Navigate("http://office.microsoft.com/zh-cn/");
}
void btnGoogleDocs_Click(object sender, Microsoft.Office.Tools.Ribbon.RibbonControlEventArgs e)
{
this.wbIE.Navigate("http://docs.google.com/");
}
private void Sheet1_Startup(object sender, System.EventArgs e)
{
Globals.Ribbons.Ribbon1.btnDF.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(btnDF_Click);
Globals.Ribbons.Ribbon1.btnGoogleDocs.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(btnGoogleDocs_Click);
Globals.Ribbons.Ribbon1.btnOffice2010.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(btnOffice2010_Click);
Globals.Ribbons.Ribbon1.btnOracle.Click += new Microsoft.Office.Tools.Ribbon.RibbonControlEventHandler(btnOracle_Click);
}
運行結果:
Ribbon支持右鍵導出為XML,即上文提到的customUI.xml:
點擊導出為XML后會自動生成兩個文件:
XML文件的內容格式符合Office 2010 XML架構規范:
五、第三方商業組件
現在有很多的控件、組件開發公司設計的軟件也相當好用,如果你的項目有充足的預算,可以考慮使用這些商業組件。
5.1、add-in-express
這是一家專門做插件的公司,官方主頁:http://www.add-in-express.com
其產品線包括:
Add-in Express 2010 for Microsoft Office and .net
Add-in Express 2010 for Microsoft Office and CodeGear VCL
Add-in Express 2010 for Internet Explorer and Microsoft .net
Security Manager 2010 for Microsoft Outlook
add-in-express公司對Office的插件開發做了很好的封裝,大大簡化了開發Office插件的過程,如果你感興趣,可以進行試用。
5.2、devcomponents
這家公司的業務范圍稍微大了一些,官方主頁:http://www.devcomponents.com/
其主要為Windows Forms、WPF、Silverlight設計Ribbon界面,產品線包括:
小結
本次介紹了5種Office 2010 Ribbon的開發方法,適合不同的人群與需求。如果你的C++水平很高,且對Windows API很熟悉,那么我建議你使用微軟的Windows Ribbon Framework,有官方支持,且效率很高。
我個人更傾向于使用VSTO 4.0 + OpenXML SDK 2.0的方式,這樣可以使用更熟悉的技術來開發,便于系統后續升級、維護。Office AddIn的方式處理起來非常復雜,需要進行很多控制,如果你需要非常高的自由度,建議采用此方法。至于最后一種商業組件,那屬于有錢人了 :) 開個玩笑。采用哪種方案,具體應取決于業務需求,合適的才是最好的。如果你有其他更好的方案,歡迎討論。


浙公網安備 33010602011771號