Customize Ribbon UI for Excel 2007 with ‘Managed’ COM Add-ins (VB.NET 2005)
For a version that cover COM Add-ins developed with classic VB please see the following post: Customize RibbonX UI for Excel 2007 with COM Add-ins (classic VB)
The Customized RibbonX ‘Manifest’
The NotesRibbon.XML file is embedded in the project and the only difference between this file and the one used in the previously post (as above) is the following:
label=“Help”
screentip=“Help with Notes Tool.”
imageMso=“AutoDial”
size=“large”
onAction=“NotesButton” />
Code in the Connection class
In this case I use Windows icon files and therefore they need to be converted to bitmaps before we can retrieve the IPictureDisp for them. The function GetResourceBitMap below takes care of the converting process. In order to retrieve the IPictureDisp for the bitmaps we need to get access to the protected method GetIPictureDispFromPicture in the class System.Windows.Forms.AxHost. For the case it’s solved by using a separately class which is presented after the code for the Connection class.
All the Windows icon files (32×32) are embedded and only the relevant code for the case is showed here.
Imports Office = Microsoft.Office.Core ‘To implement and use the IRibbonExtensibility.
Imports System.Windows.Forms ‘To use MessageBox.
Imports Extensibility ‘To implement and use the IDTExtensibility2.
Imports System.Runtime.InteropServices ‘Defines the GuidAttribute and ProgIdAttribute.
Imports System.Reflection ‘In order to use the method GetExecutingAssembly.
Imports System.IO ‘In order to use a Stream and a Streamreader.
Imports stdole ‘To work with the IPictureDisp
Imports System.Drawing ‘To work with the images.
Public Class Connect
‘In order to customize the Ribbon UI the IRibbonExtensibility interface must be implemented.
Implements Office.IRibbonExtensibility
Implements Extensibility.IDTExtensibility2
Public Sub OnDisconnection(ByVal RemoveMode As Extensibility.ext_DisconnectMode, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnDisconnection
g_xlApp = Nothing
End Sub
Public Sub OnConnection(ByVal application As Object, ByVal connectMode As Extensibility.ext_ConnectMode, ByVal addInInst As Object, ByRef custom As System.Array) Implements Extensibility.IDTExtensibility2.OnConnection
g_xlApp = CType(application, Excel.Application)
System.Windows.Forms.Application.EnableVisualStyles()
System.Windows.Forms.Application.DoEvents()
End Sub
Function GetCustomUI(ByVal ribbonID As String) As String Implements Office.IRibbonExtensibility.GetCustomUI
‘Since the NotesRibbon.xml is embedded we need to fully qualify the resource name:
‘<appnamespace>.<filewithextension>.
Return GetResourceXML(“Notes.NotesRibbon.xml”)
End Function
Public Function GetResourceXML(ByVal resourceName As String) As String
‘Set a reference to the assembly during runtime.
Dim asm As Assembly = Assembly.GetExecutingAssembly()
‘Declare the textreader.
Dim xmlDataReader As StreamReader = _
New StreamReader(asm.GetManifestResourceStream(resourceName))
With xmlDataReader
‘Read and return the XML file in a chunk.
Return .ReadToEnd()
.Close()
End With
End Function
‘The Callback function for the customized Ribbon Notes Tool.
Public Sub NotesButton(ByVal control As Office.IRibbonControl)
Try
Select Case control.Id
Case “wbk” : Show_Form(“wbk”)
Case “wst” : Show_Form(“wst”)
Case “hlp” : Process.Start(My.Application.Info.DirectoryPath & “Notes_Tool.chm”)
Case “abt” : Show_Form(“abt”)
Case “xld” : Process.Start(“http://www.excelkb.com”)
End Select
Catch ex As Exception
MessageBox.Show(ex.ToString, g_CONST_TITLE)
End Try
End Sub
‘The Callback function for the customized images.
Public Function GetImage(ByVal control As Office.IRibbonControl) As IPictureDisp
Dim pictureDisp As IPictureDisp
pictureDisp = Nothing
Select Case control.Id
Case “wbk” : pictureDisp = ImageAxHost.Image_Convert(GetResourceBitmap(“workbooks.ico”))
Case “wst” : pictureDisp = ImageAxHost.Image_Convert(GetResourceBitmap(“worksheet.ico”))
Case “abt” : pictureDisp = ImageAxHost.Image_Convert(GetResourceBitmap(“info.ico”))
Case “xld” : pictureDisp = ImageAxHost.Image_Convert(GetResourceBitmap(“xldennis.ico”))
End Select
Return pictureDisp
End Function
‘Function to convert Windows Icons to Bitmaps.
Public Function GetResourceBitmap(ByVal resourceName As String) As Bitmap
‘Set a reference to the assembly during runtime.
Dim asm As Assembly = Assembly.GetExecutingAssembly()
‘Since the icon files are embedded we need to fully qualify the resource names, i e
‘<appnamespace>.<filewithextension>.
Dim stream As Stream = asm.GetManifestResourceStream(“Notes.” & resourceName)
‘Convert the Windows icons to GDI+ Bitmaps.
Dim image As Bitmap = New Icon(stream).ToBitmap()
stream.Close()
Return image
End Function
End Class
Code in the ImageAxHost class
By using a class, which inherits from System.Windows.Forms.Axhost, we get access to the protected method GetIPictureDispFromPicture. Below is the code in the ImageAxhost class:
Imports stdole
Friend Class ImageAxHost
‘The class derives from System.Windows.AxHost.
Inherits System.Windows.Forms.AxHost
Sub New()
‘Intialize the base class to nothing.
MyBase.New(Nothing)
End Sub
Public Shared Function Image_Convert(ByVal image As System.Drawing.Image) As IPictureDisp
Return AxHost.GetIPictureDispFromPicture(image)
End Function
End Class
The Output
The following image shows the output after that the code has been executed:

Conclusion
I find it quite easy to work with the Ribbon UI no matter if I use VBA, classic VB or VB.NET. However, I hope that MSFT will provide us with a better solution then the above when it comes to obtaining the IPictureDisp with VB.NET.
What is most notable is that when using ‘managed’ COM add-ins we can mix built-in images with customized which seems not to be the case when working with VBA or with COM Add-ins developed with classic VB.
Edit: With the recent B2TR it works very well to mix customized images with built-in images.
In view of the fact that Office 2007 will be shipped with more built-in images then any previously version I don’t see any strong need to use customized images. In that way some extra code work is saved.
In the above case and in the previous classic COM Add-in’s case I’ve created a unique tab (Notes Tool). It looks great but if we assume that the end users actually will use 6-8 add-ins and each of them have their own unique tab then it will no longer look so great. In my opinion we should use tabs in a spare some way and instead make use of the general Add-ins tab. Of course, with this tab we need to consider how much space we actually should use for our add-in(s).
Kind regards,
Dennis
Hi Dennis,
Very impressive, as usual from you…
I’m curious about what you wrote here, however:
“What is most notable is that when using ‘managed’ COM add-ins we can mix built-in images with customized which seems not to be the case when working with VBA or with COM Add-ins developed with classic VB.”
Are you sure that this is right? What hapens if you attempt this from a COM Add-in? I would think that using a COM dll would be equivalent becaues IRibbonExtensibility is actually a COM interface and so it is really .NET which is being ported to the interface via the Interop, not the other way around… Not that I don’t trust you! But I was wondering what happens with COM in your experience?
Great set of articles though. You and Tushar have really shed a lot of light…
Mike,
From a logical point of view You’re correct (and that’s why I also decided to single it out to get feedback on it).
With B2 I’ve not been able to do it while with B2TR it seems to work ‘as expected’.
I’ll update the articles asap however I need to re-write the VB.NET project as Excel 2007 B2TR refuse to acceept it as a valid add-in!
The B2TR, so far, looks very impressive :)
Kind regards,
Dennis
I m developing COM AddIn using VB. But still I m not getting success to assign Images using Image Tag. I used imageMSO. It is woorking fine But I want to asign custom Images. So Can u help me how can I do this?
Hello everyone,
I have tried the code above. but when i launch excel 2007, the exact xml file is returned by the function getcustomUI, but nothing happened. no additional ribbon is found in the application. but the add-in is charged. May someone help me?
and I am using vb .net 2003 and excel 2007
pin – i believe you need VS2005 or greater