在開始Excel開發之前,需要把架子搭起來。最直接的那就是Excel裡面的菜單了,他向用戶直觀的展現了我們的插件具有哪些功能。菜單出來之後我們就可以實現裡面的事件和功能了。Excel菜單有兩種形式,一種是Excel 2003及之前的傳統菜單樣式,一種是Excel 2007及之後的Ribbon菜單。本文首先講解Excel 2007中菜單的創建,包括使用Visual Studio可視化設計菜單,菜單的RibbonXml配置,然後講解如何在Excel 2003中創建自定義菜單。最後演示如何使用SharedAddin技術將兩者結合起來,即在2003版本中顯示原始的菜單樣式,在以2003上版本中動態加載Ribbon菜單,從而達到版本的兼容。
一 Excel 的Ribbon菜單及Ribbon Xml文件
要演示菜單的創建,我們首先創建一個VSTO程序,如圖在VS中創建一個Excel外接程序:
然後接下來,添加項,添加一個Ribbon菜單:
在創建菜單之前,需要明確我們的插件具有哪些模塊。這裡為了演示如何創建菜單以及後面的功能點,我們的插件打算做四個功能點。 首先是財經模塊,包括從一些開放的財經API如新浪財經API,雅虎API中獲取實時或者歷史行情數據;地圖模塊,包括地圖顯示,地址檢索,專題制圖等;天氣模塊,獲取天氣,天氣保表;系統模塊,包括登錄,幫助,關於模塊等。確定好功能點之後,就可以開始創建菜單了。
添加了Ribbon菜單之後,就可以打開ToolBox開始設計了,如下圖。下面介紹各個菜單項的功能及設計要點。
基本控件
相關文章:
淺談Excel開發(1) Excel開發概述:http://www.bianceng.cn/Programming/net/201312/39219.htm
2.1 Tab控件
首先介紹的是RibbonTab控件,它是所有控件的容器,當我們添加一個Ribbon菜單的時候,VS默認會給我們創建一個RibbonTab控件,一個VSTO項目可以創建多個Tab控件,您需要做的只是從ToolBox中推拽一個Tab至設計界面上即可。Tab控件有一些屬性。
其中比較重要的屬性為ControlIdType,如果類型是Office的話,他會嵌入到Office內置系統的 Tab頁中,而不是默認的新創建一個以Label為名稱的Tab頁。下圖是ControlIdType為Office的效果,如果PositionType屬性設置為Default的話,會出現在Office加載項 這個標簽頁中。
如果將ControlIdType設置為Custom,則在界面上會顯示以Label命名的一個新的Tab頁,這裡將Label改為歪歪插件。效果如下圖:
一般的,我們會采用Custom的方式,讓我們的插件以獨立的Tab頁展現出來。
Tab控件還有一個重要的名為Position的屬性,他決定了我們的Tab在哪個地方展現,PositionType的默認值為Default,這時,如果ControlIdType為Office,我們的插件會在加載項中顯示,如果為Custom,插件會顯示在Office裡面的最後一個加載項後面,如果有多個加載項,則按順序往後面排列。PositionType屬性還有BeforeOfficeId和AfterOfficeId兩值,設置這兩個屬性時,需要指定OfficeId,Office內置的菜單的ID值,您可以到MSDN上下載。指定好OfficeId後,我們的Tab也會在該內置Tab頁裡面,前面或者後面顯示。一般的,我們保持這個屬性為空即可。讓我們的插件在Office系統Tab頁之後顯示。
2.2 Group控件
Group控件的作用是將我們的功能進行分組。回到我們之前的規劃,我們的歪歪插件有財經,地圖,天氣,關於這幾大功能。所以我們需要在界面上放置4個Group控件,並對其進行命名。
2.3 Menu控件和SpliterButton控件
在分好類之後,我們需要對每個分類的細小功能進行設計,這裡面我們需要放置各種控件,首先我們可能會接觸到的就是Menu控件,裡面可以包含Button,SplitButton等。我們規劃的財經項主要包括,實時行情,歷史行情和導入功能。實時行情和歷史行情包括從Sina或者Yahoo財經API接口中獲取所有股票的實時和歷史行情數據,導入功能即是從本地或者網絡上導入數據。所以在頁面上添加三個Menu控件。
Menu控件幾個比較重要的屬性,一個是ControlSize,它確定了控件的大小,一般地,如果功能較重要,或者是有比較明顯的分類用途,使用RibbonControlSizeLarge。然後需要設置菜單的圖標,可以指定自定義的圖片,也可以使用默認的Office內置的菜單的圖片,如果要使用內置的圖片,需要設置OfficeImageId,具體內置Id及圖片可以查看該網址。一般地,我們會為我們的菜單設計圖標,您只需要指定其Image屬性即可。
SplitButton控件和Menu控件類似,它可以包含Button,Seperator控件,不同的是,SplitButton控件本身自己可以響應Click事件,通常在Menu中如果需要將該菜單項中常用的功能設置為默認的,那麼可以使用SplitButton控件,將最常用的功能設置到該控件的Click事件上來。
2.4 Button,Seperator控件
Button控件是最基礎的響應單擊事件的UI控件。點開Menu的下拉圖標,然後向裡面添加Button按鈕即可,可以設置按鈕的Image屬性。在設計按鈕的時候,可能我們需要對其進行分組,這時候,使用Seperator控件是一種比較好的選擇,直接在ToolBox中拖動一個Seperator控件到界面上想分割的地方即可。默認情況下Seperator控件是一條豎線,但是當設置Seperator控件的Title屬性時,他可以以文本的形式來進行分割,這和其他系統中的Seperator控件不一樣。
同理,按照規劃,我們將所有的菜單設計好,並注冊其Click事件。這裡只講解了這幾個基本的菜單項控件,更多的控件您可能以自己往界面上拖拽試試看,利用這些內置的控件,您可以設計出和Office內置的Ribbon菜單媲美的自定義菜單界面來。
RibbonXml
在Office中Ribbon菜單時可以通過RibbonXML進行配置,也就是說,上面的可視化界面設計其實是為我們提供了編輯RibbonXML的設計時支持。其實我們也可以直接創建一個XML文件進行設計,然後在代碼中進行加載,同樣能夠實現這樣的功能。在有些情況下,比如我們創建SharedAddin程序時,根本沒有設計時支持。所以了解RibbonXML對於創建可兼容多版本Excel菜單系統顯得尤為重要。
要創建RibbonXML最好的做法是對著新建的可視化菜單,然後右鍵->將功能區導出到XML。然後項目會自動創建Ribbon.xml和Ribbon.cs文件,其中Ribbon.xml是布局文件,Ribbon.cs是事件處理代碼。
打開Ribbon.xml可以看到如下代碼,可以看到這個UI界面的展現即是使用了該XML文件來進行渲染的,其中在XML中還可以聲明一些事件,後面會講。
現在,如何在我們的應用程序中加載該RibbonXML並渲染出Ribbon菜單呢?首先,我們將之前的添加的可視化設計的Ribbon菜單YYMenu.cs排除到項目外。然後轉到ThisAddIn.cs中,覆寫Office.IRibbonExtensibility 接口的CreateRibbonExtensibilityObject方法,實例化自動生成的Ribbon類,然後返回。
private Ribbon customerRibbon; protected override Office.IRibbonExtensibility CreateRibbonExtensibilityObject() { customerRibbon = new Ribbon(); return customerRibbon; }
運行程序,即可看到如下效果:
可以看到圖片不見了,這是因為在導出功能區為XML的時候,VS沒有幫我們處理圖片,所以需要我們自己來添加。在RibbonXML文檔中, customUI節點下有loadImage事件,Button有getImage事件和image屬性。customUI節點的loadImage方法和子節點的image屬性一起使用,image屬性作為loadImage方法的參數。
loadImage方法如下:
public Image LoadImage(string imageName) { Assembly assembly = Assembly.GetExecutingAssembly(); //String[] all =assembly.GetManifestResourceNames();//GetResourceName Stream stream = assembly.GetManifestResourceStream("YYAddIn.Resources." + imageName); return Image.FromStream(stream); }
其中,imageName即為Button控件的image屬性要設置的圖片名稱。資源文件圖片,要設置為嵌入的資源。所有的按鈕的單擊事件,我們使用GeneralButton_Click事件來處理。運行程序,我們又看到了之前采用設計器時編輯的菜單時的界面了。
二 Excel 2003下面的菜單系統
創建工程
由於Excel2003及以下版本不支持Ribbon菜單,所以以上的程序在03版本下並不能運行。但是,如果開發企業級應用的話,仍不能忽視廣大使用 Office 2003 版本的客戶,所以您還需要創建2003下面的菜單系統。下面就介紹如何在Excel2003系統中創建Excel菜單及工具條。
要創建在Excel 03下的插件,我們可以創建Shared Add-in程序,如下圖,首先新建一個名為YYSharedAddin的Shared Add-in項目:
然後下一步下一步, 設置編程語言,我們這裡選擇C#
下一步,設置插件的目標應用程序,可以看到,我們的Shared Add-in程序可以為多個目標應用程序編寫同一個插件,這在前一篇文章中介紹SharedAddin和VSTO的差別時已經介紹過了。因為我們主要是編寫Excel插件,所以僅勾選Excel即可。
下一步,設置Addin的展現名稱和在編程時的名稱
創建完成之後,我們可以看到工程項目非常簡單,只有一個Connect.cs文件。打開該文件,可以看到其中實現了Extensibility.IDTExtensibility2 接口,所有Office應用程序都是用IDTExtensibility2接口與COM加載項進行通信的,該接口提供了一種通用的初始化機制,並具有在Office應用程序的對象模型中傳遞數據的能力,因此Com加載項可以與Office應用程序通信,該接口中有5個方法,分別是:
Office在對Com加載項進行實例化時,會創建Connect類,注意我們不能用Connect的構造函數創建類的實例,應該在OnConnection方法中進行初始化操作,比如菜單項的加載,自定義函數的加載,變量的初始化等等;類似的,加載項的關閉不能調用析構函數,而要用OnDisconnection方法,在該方法中需要釋放非托管的資源,進行資源清理等一系列操作。下圖展示了這5個方法的執行順序。該圖引用了MYM]Brooks同學博文中的圖片。
由分析得之,我們對菜單及工具欄的初始化,需要放到OnConnection方法中。
在OnConnection方法中,有一個很重要的參數就是application,我們聲明一個類型為
Microsoft.Office.Interop.Excel.Application的applicationObject對象,然後將這個對象保存起來,以備後面創建菜單以及對Excel進行操作時使用。
private Application applicationObject; /// <summary> /// Implements the OnConnection method of the IDTExtensibility2 interface. /// Receives notification that the Add-in is being loaded. /// </summary> /// <param term='application'> /// Root object of the host application. /// </param> /// <param term='connectMode'> /// Describes how the Add-in is being loaded. /// </param> /// <param term='addInInst'> /// Object representing this Add-in. /// </param> /// <seealso class='IDTExtensibility2' /> public void OnConnection(object application, Extensibility.ext_ConnectMode connectMode, object addInInst, ref System.Array custom) { applicationObject = application as Application; addInInstance = addInInst as COMAddIn; if (applicationObject.Version == "11.0") { if (menuDesigner == null) { menuDesigner = new MenuDesigner(applicationObject); } menuDesigner.AddMenus(); menuDesigner.AddToolBars(); } }
在OnConnection方法中,我們首先判斷Excel的版本號,版本號可以通過Version對象獲取,如果版本號為11,即為2003版本的Excel,我們需要手動的動態創建菜單和工具條。我們新建了一個名為MenuDesigner的用來創建菜單和工具條的類,在其構造函數中傳入了applicationObject對象。
添加菜單
我們把添加菜單放到了MenuDesigner的AddMenus方法中。Excel中的一個菜單項和子菜單其實都是一個MSOffice.CommandBarPopup對象,菜單項裡面的菜單按鈕是MSOffice.CommandBarButton對象。首先我們定義菜單項以及菜單按鈕,這裡只列出部分。
//YY插件菜單 MSOffice.CommandBarPopup YYMenu = null; //實時行情函數菜單按鈕 MSOffice.CommandBarButton btnQuoteFunctionMenuCommand = null; //Sina實時行情函數菜單按鈕 MSOffice.CommandBarButton btnQuoteSinaFunctionMenuCommand = null; //Yahoo實時行情函數菜單按鈕 MSOffice.CommandBarButton btnQuoteYahooFunctionMenuCommand = null;
在創建菜單時,我們要首先創建YYMenu對象,然後再在該對象上添加菜單項。創建YYMenu菜單的方法如下:
public void AddMenus() { MSOffice.CommandBar menubar = (MSOffice.CommandBar)application.CommandBars.ActiveMenuBar; int controlCount = menubar.Controls.Count; string menuCaption = "歪歪插件"; // Add the menu. try { YYMenu = (MSOffice.CommandBarPopup) application.CommandBars.ActiveMenuBar.FindControl( MSOffice.MsoControlType.msoControlPopup, System.Type.Missing, menuTag, true, true); } catch { } if (YYMenu != null) { YYMenu.Delete(Type.Missing); } YYMenu = (MSOffice.CommandBarPopup)menubar.Controls.Add(MSOffice.MsoControlType.msoControlPopup, missing, missing, controlCount, true); YYMenu.Tag = menuTag; YYMenu.Caption = menuCaption; YYMenu.BeginGroup = true; LoginGroup(); FinancialGroup(); MapServiceGroup(); WeatherReportGroup(); AboutGroup(); }
需要注意的是,在創建菜單之前,我們需要判斷之前是否已經存在相同Tag值得菜單,如果存在,需要先將之前創建的菜單項刪除,然後再重新創建。否則,在用戶在Com加載項中顯示或者隱藏菜單項時,會重復創建菜單項。創建完主菜單後,我們可以在主菜單上創建子菜單了。這些方法都寫到了最後的幾個以Group結尾的方法中。現在以創建財務項菜單的FinancalGroup方法為例講解。
private void FinancialGroup() { //實時行情 MSOffice.CommandBarPopup realTimeButton = AddPopupButton(YYMenu.Controls, MenuNameEnum.Quote); realTimeButton.BeginGroup = true; //添加子菜單 btnQuoteFunctionMenuCommand = AddCommandButton(realTimeButton.Controls, MenuNameEnum.Quote, YYSharedAddin.Properties.Resources.QuoteReal); btnQuoteSinaFunctionMenuCommand = AddCommandButton(realTimeButton.Controls, MenuNameEnum.QuoteSina, YYSharedAddin.Properties.Resources.SinaQuote_64); btnQuoteSinaFunctionMenuCommand.BeginGroup = true; btnQuoteYahooFunctionMenuCommand = AddCommandButton(realTimeButton.Controls, MenuNameEnum.QuoteYahoo, YYSharedAddin.Properties.Resources.Yahoo_Quote); //歷史行情 MSOffice.CommandBarPopup historyButton = AddPopupButton(YYMenu.Controls, MenuNameEnum.QuoteHistory); realTimeButton.BeginGroup = true; //添加子菜單 btnQuoteHistoryFunctionMenuCommand = AddCommandButton(historyButton.Controls, MenuNameEnum.QuoteHistory, YYSharedAddin.Properties.Resources.QuoteHist); btnQuoteHistorySinaFunctionMenuCommand = AddCommandButton(historyButton.Controls, MenuNameEnum.QuoteHistorySina, YYSharedAddin.Properties.Resources.SinaQuote_64); btnQuoteHistorySinaFunctionMenuCommand.BeginGroup = true; btnQuoteHistoryYahooFunctionMenuCommand = AddCommandButton(historyButton.Controls, MenuNameEnum.QuoteHistoryYahoo, YYSharedAddin.Properties.Resources.Yahoo_HistoryQuote); //導出 MSOffice.CommandBarPopup importButton = AddPopupButton(YYMenu.Controls, MenuNameEnum.Import); importButton.BeginGroup = true; btnImportFromLocalMenuCommand = AddCommandButton(importButton.Controls, MenuNameEnum.ImportFromLocal, YYSharedAddin.Properties.Resources.ImportFromDisk); btnImportFromWebMenuCommand = AddCommandButton(importButton.Controls, MenuNameEnum.ImportFromWeb, YYSharedAddin.Properties.Resources.ImportFromWeb); }
對於財務大類菜單,其中有三個一級菜單,分別是實時行情,歷史行情,導入。創建一級菜單的方法AddPopupButton代碼為:
/// <summary> /// 添加子菜單項 /// </summary> /// <param name="controls">該字菜單的父菜單容器</param> /// <param name="menu">菜單名稱</param> /// <returns></returns> private MSOffice.CommandBarPopup AddPopupButton(MSOffice.CommandBarControls controls, MenuNameEnum menu) { String tag = menu.ToString(); String caption = String.Empty; Menus.menus.TryGetValue(tag, out caption); MSOffice.CommandBarPopup command = null; try { command = controls[caption] as MSOffice.CommandBarPopup; } catch { } if (command == null) { command = controls.Add(MSOffice.MsoControlType.msoControlPopup, Type.Missing, Type.Missing, Type.Missing, Type.Missing) as MSOffice.CommandBarPopup; command.Caption = caption; } return command; }
其中第一個參數為最大的根節點菜單YYMenu對象的所有Controls容器。所以創建第一個實時行情一級菜單的方法為:
//實時行情
MSOffice.CommandBarPopup realTimeButton = AddPopupButton(YYMenu.Controls, MenuNameEnum.Quote);
realTimeButton.BeginGroup = true;
得到realTimeButton這個一級菜單之後,我們將其BeginGroup屬性設置為true表示在之前添加一個Seperator控件(一條橫線或者豎線)。有了這個realTimeButton一級菜單之後,我們可以在該對象上創建三個二級菜單按鈕項。
//添加子菜單 btnQuoteFunctionMenuCommand = AddCommandButton(realTimeButton.Controls, MenuNameEnum.Quote, YYSharedAddin.Properties.Resources.QuoteReal); btnQuoteSinaFunctionMenuCommand = AddCommandButton(realTimeButton.Controls, MenuNameEnum.QuoteSina, YYSharedAddin.Properties.Resources.SinaQuote_64); btnQuoteSinaFunctionMenuCommand.BeginGroup = true; btnQuoteYahooFunctionMenuCommand = AddCommandButton(realTimeButton.Controls, MenuNameEnum.QuoteYahoo, YYSharedAddin.Properties.Resources.Yahoo_Quote);
創建子菜單按鈕的方法封裝到了AddCommandButton方法中,方法第一個參數為第一級子菜單的所有控件的容器類。
private MSOffice.CommandBarButton AddCommandButton(MSOffice.CommandBarControls controls, MenuNameEnum menu, System.Drawing.Image icon) { string tempName = menu.ToString(); String tag = String.Format("{0}|{1}", menu, DateTime.Now.ToBinary()); String caption = String.Empty; Menus.menus.TryGetValue(tempName, out caption); MSOffice.CommandBarButton command = null; try { command = controls[caption] as MSOffice.CommandBarButton; command.Tag = tag; command.Click += new MSOffice._CommandBarButtonEvents_ClickEventHandler(command_Click); } catch { } if (command == null) { command = controls.Add(MSOffice.MsoControlType.msoControlButton, Type.Missing, Type.Missing, Type.Missing, Type.Missing) as MSOffice.CommandBarButton; command.Style = MSOffice.MsoButtonStyle.msoButtonIconAndCaption; command.Caption = caption; command.Tag = tag; command.Picture = ImageConverterHelper.ImageToPictureDisp(icon); command.Click += new MSOffice._CommandBarButtonEvents_ClickEventHandler(command_Click); } return command; }
在創建菜單按鈕時,我們需要先判斷當前的菜單中是否有該菜單項,如果有直接使用。否則創建新的對象。這裡有幾個地方需要注意,首先是CommandBarButton 的Tag屬性,該屬性應該加上一個唯一標志,比如當前時間,或者GUID,然後帶上該菜單的名稱等信息。加唯一標志的目的是每一次在創建菜單時保證是唯一的,否則會出現菜單只會響應一次按鈕點擊事件等奇怪的問題。其次設置按鈕的Style為MSOffice.MsoButtonStyle.msoButtonIconAndCaption 既帶圖片又有文字的時候,Picture屬性為想要顯示在按鈕前面的圖片,該對象是一個stdole.IPictureDisp類型的對象,您需要進行一下轉換。其次直接設置圖片會使得圖片中的背景色不會透明,背景色為Office的默認風格顏色,如果要將背景色透明,需要設置Mask屬性,Mask屬性也是一張圖片。該圖片為帶顯示圖片的蒙版,即原始圖片中需要顯示的地方,用黑色表示,那麼其余地方就會透明顯示,具體使用方式您可以參看這篇文章,這裡為了簡化,不做處理。
添加工具條
工具條其實就是一個大的一級菜單,和創建菜單一樣,我們將創建工具條的代碼封裝到了AddToolBars方法中,該方法代碼如下:
public void AddToolBars() { try { YYToolBar = application.CommandBars["YYToolBar"]; } catch { } if (YYToolBar == null) { YYToolBar = application.CommandBars.Add("YYToolBar", MSOffice.MsoBarPosition.msoBarTop, false, true); } LoginGroup_ToolBar(); FinancialGroup_ToolBar(); MapServiceGroup_ToolBar(); WeatherReportGroup_ToolBar(); AboutGroup_ToolBar(); YYToolBar.Visible = true; }
我們首先需要創建一個大的工具條,和創建菜單類似,在創建工具條之前,我們需要定義好所有的工具條中的按鈕,注意,該按鈕對象不能和菜單項裡面的對象共用,否則會導致事件注冊被沖掉的情況。
//歪歪插件工具條 MSOffice.CommandBar YYToolBar; //實時行情函數工具條 MSOffice.CommandBarButton btnQuoteFunctionToolBarCommand = null; //Sina實時行情工具條 MSOffice.CommandBarButton btnQuoteSinaFunctionToolBarCommand = null; //Yahoo實時行情工具條 MSOffice.CommandBarButton btnQuoteYahooFunctionToolBarCommand = null;
創建好YYToolBar對象後,在該對象的基礎上創建工具條裡面的工具項就和創建字菜單類似了,這裡就不再贅述了。
現在我們來看在Excel2003下面的效果。由於我們創建的SharedAddin程序,我們在調試的時候,需要設置啟動程序,Visual Studio 給我們設置的默認啟動程序是Visual Studio本身。這裡我們將默認程序指定為Excel 2003 的可執行文件,如下圖:
運行程序,Visual Studio就會啟動Excel程序,然後就可以看到我們創建的歪歪菜單和工具條了。
三 全版本兼容
前面介紹了在2003以上版本的Ribbon菜單創建和在2003版本下面的傳統菜單項的創建。一個良好的Excel應用程序應該會根據版本的不同而展現不同的菜單形式。如果您用VSTO創建的話,那麼可能在03版本上就不能很好的支持,因為03版本不支持Ribbon菜單。所以要想兼容所有的Excel版本,可以創建Shared Add-in工程。第二部分已經講解了如何在SharedAddin中創建傳統菜單的方法,要兼容03以上版本,我們只需要在SharedAddin中加載第一部分創建好的RibbonXML即可。
要讓SharedAddin能在03以上版本中渲染Ribbon菜單,我們需要讓Connect類實現Office.IRibbonExtensibility接口。由於之前生成的Ribbon.cs類已經實現了該接口,所以最簡單的方法是:將之前創建好的Ribbon.xml及Ribbon.cs拷貝到SharedAddin工程項目中來。並將Ribbon.xml設置為嵌入的資源。將Ribbon.cs 的命名空間改為和Connect.cs一致的命名空間,然後利用Partial關鍵字,將Ribbon類名稱改為partial Connect類。如下:
[ComVisible(true)] public partial class Connect : Office.IRibbonExtensibility { private Office.IRibbonUI ribbon; #region IRibbonExtensibility 成員 public string GetCustomUI(string ribbonID) { return GetResourceText("YYSharedAddin.RibbonMenu.Ribbon.xml"); } #endregion #region 功能區回調 //在此創建回調方法。有關添加回調方法的詳細信息,請在解決方案資源管理器中選擇功能區 XML 項,然後按 F1 public void Ribbon_Load(Office.IRibbonUI ribbonUI) { this.ribbon = ribbonUI; } public Image LoadImage(string imageName) { Assembly assembly = Assembly.GetExecutingAssembly(); //String[] all =assembly.GetManifestResourceNames();//GetResourceName Stream stream = assembly.GetManifestResourceStream("YYSharedAddin.Resources." + imageName); return Image.FromStream(stream); } public void GeneralButton_Click(Office.IRibbonControl control) { try { MessageBox.Show("you clicked the button id is " + control.Id); } catch (Exception ex) { } } #endregion #region 幫助器 private static string GetResourceText(string resourceName) { Assembly asm = Assembly.GetExecutingAssembly(); string[] resourceNames = asm.GetManifestResourceNames(); for (int i = 0; i < resourceNames.Length; ++i) { if (string.Compare(resourceName, resourceNames[i], StringComparison.OrdinalIgnoreCase) == 0) { using (StreamReader resourceReader = new StreamReader(asm.GetManifestResourceStream(resourceNames[i]))) { if (resourceReader != null) { return resourceReader.ReadToEnd(); } } } } return null; } #endregion }
我們需要注意的是,要設置好正確的資源名稱,您可以通過GetManifestResourceNames 來查看該程序集中的所有的資源名稱。
現在,將啟動項目設置為2007 或者2010版本的Excel,現在菜單又變成Ribbon風格的了:
將啟動項目設置為2003版本的Excel,菜單就變成傳統風格的了。
四 結語
本文介紹了Excel中的菜單系統。首先介紹了使用Visual Studio設計時支持的Ribbon菜單的創建,通過拖拉控件及設置屬性,可以創建出和Office內置菜單相媲美的自定義菜單。然後介紹了Ribbon菜單的基礎Ribbon XML文件,隨後講解了如何在VSTO中手動加載Ribbon菜單。然而Ribbon菜單僅在2003以上版本的Excel中支持。為了解決Excel 2003下菜單創建的問題,本文展示了如何創建Excel Shared Add-in程序,並演示了如何創建傳統的菜單項和工具欄。最後為了兼容所有的Excel版本,在SharedAddin中展示了如何加載Ribbon XML,使得我們的Excel插件對於不同的Excel版本,能夠展現出不同風格的菜單項。
現在我們的插件架子已經搭好了,下文我會講解Excel的對象模型,介紹Excel中的幾個核心對象,如WorkBook,WorkSheet,Range對象等,這些對象無論是您進行何種類型的Excel開發,都會遇到,這些對象也是您進行Excel開發的重要基礎,敬請期待。
本文代碼點擊此處下載,希望本文對您了解Excel菜單系統有所幫助。
作者: yangecnu(yangecnu's Blog on 博客園)
出處:http://www.cnblogs.com/yangecnu/