程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 淺談Excel開發(二) Excel 菜單系統

淺談Excel開發(二) Excel 菜單系統

編輯:關於.NET

在開始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/

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved