How to save ImageMSO icon from Microsoft Office 2007? How to save ImageMSO icon from Microsoft Office 2007? vba vba

How to save ImageMSO icon from Microsoft Office 2007?


I use ImageMso quite frequently in my Excel development. Having stumbled on this post, I took it a step further and put a package together to visually search, extract and save icons from Microsoft Excel as a file or copy and paste (with alpha channel transparency) to another application. I also compiled a list of 8,899 distinct ImageMso names from the various sources. I hope others can find this useful.

Microsoft Office Icons (ImageMSO) Gallery & Extraction

ImageMSO Gallery on Microsoft Excel 2013 running Windows 8


I've wrapped up a C# Utility class for extracting Office2007 gallery icons to .png files, while maintaining their transparency properly. The main code is taken from a great article written by Andrew Whitechapel (http://blogs.msdn.com/b/andreww/archive/2007/10/10/preserving-the-alpha-channel-when-converting-images.aspx). I've integrated this with the Office 2007 sample icon sheet, in case you want to extract all of these icons to a target folder.

Steps are:

1) Download the Office Gallery spreadsheet at http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=11675

2) Call OfficeIcons.ExtractAllIcons() with the location of the Office2007IconsGallery.xlsm sample spreadsheet, and the target folder where you want the icons extracted.

{code}

using System;using System.Drawing;using System.Drawing.Imaging;using System.IO;using System.Runtime.InteropServices;using System.Xml.Linq;using ExcelDna.Integration;using ICSharpCode.SharpZipLib.Zip;using Microsoft.Office.Interop.Excel;using stdole;public class OfficeIconUtils{    public static void ExtractAllIcons(string xlsmPath, string targetFolder)    {        // extract  customUI.xml        var zf = new ZipFile(xlsmPath);        var entry = zf.GetEntry("customUI/customUI.xml");        var zipStream = zf.GetInputStream(entry);        XNamespace ns = "http://schemas.microsoft.com/office/2006/01/customui";        var root = XElement.Load(zipStream);        foreach (var gallery in root.Descendants(ns + "gallery"))        {            //create a sub-folder for the gallery            var subFolder = Path.Combine(targetFolder,                 gallery.Attribute("label").Value);            var width = int.Parse(gallery.Attribute("itemWidth").Value);            var height = int.Parse(gallery.Attribute("itemHeight").Value);            Directory.CreateDirectory(subFolder);            foreach (var item in gallery.Descendants(ns + "item"))            {                SaveIcon(item.Attribute("imageMso").Value,                     subFolder, width, height);            }        }    }    public static void SaveIcon(string msoName, string folder,         int width = 32, int height = 32)    {        ConvertPixelByPixel(            ((Application)(ExcelDnaUtil.Application))                .CommandBars.GetImageMso(msoName, width, height))            .Save(Path.Combine(folder, string.Format("{0}.png",             msoName)), ImageFormat.Png);    }    public static Bitmap ConvertPixelByPixel(IPictureDisp ipd)    {        // get the info about the HBITMAP inside the IPictureDisp        var dibsection = new DIBSECTION();        GetObjectDIBSection((IntPtr)ipd.Handle, Marshal.SizeOf(dibsection), ref dibsection);        var width = dibsection.dsBm.bmWidth;        var height = dibsection.dsBm.bmHeight;        // create the destination Bitmap object        var bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb);        unsafe        {            // get a pointer to the raw bits            var pBits = (RGBQUAD*)(void*)dibsection.dsBm.bmBits;            // copy each pixel manually            for (var x = 0; x < dibsection.dsBmih.biWidth; x++)                for (var y = 0; y < dibsection.dsBmih.biHeight; y++)                {                    var offset = y * dibsection.dsBmih.biWidth + x;                    if (pBits[offset].rgbReserved != 0)                    {                        bitmap.SetPixel(x, y, Color.FromArgb(pBits[offset].rgbReserved, pBits[offset].rgbRed, pBits[offset].rgbGreen, pBits[offset].rgbBlue));                    }                }        }        return bitmap;    }    [StructLayout(LayoutKind.Sequential)]    private struct RGBQUAD    {        public byte rgbBlue;        public byte rgbGreen;        public byte rgbRed;        public byte rgbReserved;    }    [StructLayout(LayoutKind.Sequential)]    public struct BITMAP    {        public Int32 bmType;        public Int32 bmWidth;        public Int32 bmHeight;        public Int32 bmWidthBytes;        public Int16 bmPlanes;        public Int16 bmBitsPixel;        public IntPtr bmBits;    }    [StructLayout(LayoutKind.Sequential)]    public struct BITMAPINFOHEADER    {        public int biSize;        public int biWidth;        public int biHeight;        public Int16 biPlanes;        public Int16 biBitCount;        public int biCompression;        public int biSizeImage;        public int biXPelsPerMeter;        public int biYPelsPerMeter;        public int biClrUsed;        public int bitClrImportant;    }    [StructLayout(LayoutKind.Sequential)]    public struct DIBSECTION    {        public BITMAP dsBm;        public BITMAPINFOHEADER dsBmih;        public int dsBitField1;        public int dsBitField2;        public int dsBitField3;        public IntPtr dshSection;        public int dsOffset;    }    [DllImport("gdi32.dll", EntryPoint = "GetObject")]    public static extern int GetObjectDIBSection(IntPtr hObject, int nCount, ref DIBSECTION lpObject);}

{code}


All of the PNG files can be found here These are all in PNG format already. Good programming! (a nice ZIP archive is also available Here) The ZIP archive contains all 17 of the Excel icons.

When you use the GetImageMso method, you end up with an IPicture interface to the object. The IPicture interface accesses the icon suitable for saving to a file in the original format - an .ICO, .WMF or a .BMP The PNG format is not supported. The following links explain why this is not directly possible:

http://msdn.microsoft.com/en-us/library/aa434604.aspx (msoGetImageMso method)http://msdn.microsoft.com/en-us/library/ms680761%28VS.85%29.aspx (IPicture Interface)http://msdn.microsoft.com/en-us/library/ms694504%28VS.85%29.aspx (Save As File method)

However, using a more complex approach will yield what you want:

http://blogs.msdn.com/mshneer/archive/2007/10/10/preserving-transparency-when-rendering-office-icons.aspx