How to save ImageMSO icon from Microsoft Office 2007?
Asked Answered
L

4

10

I found a lot of nice icons from Microsoft Office 2007. Do you any idea for extract & save all icons as PNG files by using VBA?

Partial ImageMSO http://rabu4g.bay.livefilestore.com/y1p2SF1q63YjDjPNmK4nYMW2644r9AO2aAsE__vBYznTeXD0b4SJUU0O07fxPD0r7aO_83gCJ-8OfcOQsFKG0fQMRnTEneBU1TI/Capture.PNG

The following code is code which is used to get image from ImageMSO.

Application.CommandBars.GetImageMso([name], [width], [height])

I can display all as PictureBox control and save excel file as web page. However, every icons is very low quality.

Moreover, I try to create C# Excel Add-in project for exporting as Bitmap object by using the following code. But I found that it can't export as semi-transparent PNG.

stdole.IPictureDisp p = Application.CommandBars.GetImageMso(fileName, size, size);
Bitmap b = Bitmap.FromHbitmap((IntPtr)p.Handle, (IntPtr)p.hPal);

PS. I want to save all icons as PNG format because I need to use semi-transparent feature of it. It allow me to use all icons on most background color more than white background.

Lepidosiren answered 2/7, 2009 at 9:12 Comment(2)
@Soul_Master any luck with Extracting?Phyla
Nope. I just give up about this.Lepidosiren
H
8

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

Harleigh answered 15/9, 2013 at 5:9 Comment(11)
I able to load Add-in to my Excel 2013 on Windows 8. But there is no new group/command in Insert tab.Lepidosiren
I use 32-bit version of Excel 2013. There is nothing happened after I load this add-in.Lepidosiren
Works great for me in Excel 2010 32-bit on Win7! Thanks!Fantail
I put out an update with several optimizations. I attached a screenshot of the gallery running in Microsoft Excel 2013 on Windows 8. I hope this solves your problem and if it doesn't, perhaps I can just get the PNG files for you. Most notably there are now 8,899 ImageMSO names from finding an additional source.Harleigh
"The callback function OnLoad was not found". Sigh, why does this have to be so difficult. They are just icons!!! I've been tediously searching for an hour trying to A. get some excel addin to work and B. An office icon set. Do you think you could send me a file with pngs or host it somewhere?Aforethought
Like 3,500 other folks have downloaded this add-in without a problem. It would help me help you if you started with what Excel version and edition you're running.Harleigh
This is a great utility, although using it through Excel takes a little getting used to. And, unfortunately, I don't see any instructions. I currently use Excel 2010, and I cannot find the XLL when I go to the Add-Ins option. Instead, I launch it by opening the ImageMso.Gallery.xll file directly. If there's something else that I should do to use it properly, and if I should see a button in my Ribbon, please set me straight.Discreditable
@EJMak, the way you're using it, that is double clicking on the XLL when you need it, is the way it's meant to be used. After opening directly, you should be able to launch it again from the INSERT ribbon. This sometimes only works if there's an open Workbook. Don't ask me why. If you want to have the add-in available all the time, you'll have to add it manually through the menu, File > Options > Add-Ins > Manage > Excel Add-ins > Go > Browse.Harleigh
Works like a charm on Excel 2016 on Windows 10 :-)Midship
Not sure if I'm blind, but I cannot see where you download the addin from. The site only contains an "archive" with the source code.Trend
Agreed with @GyumFox. Are we expected to load and compile the solution or is there a .xll ready somewhere?Diploblastic
B
4

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}

Brendin answered 26/9, 2011 at 19:38 Comment(2)
Would be nice if you specified the 500 dependencies that this relies on, not to mention that once you do find them all the code doesn't compile.Aforethought
References added, sorry about that. It definitely compiles though -Brendin
N
0

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

Natascha answered 24/11, 2009 at 18:50 Comment(0)
U
0

I have tried Ismail's answer and it did work great. However it took me a while to figure out how to make it work. I may share this bit of knowledge:

The solution requires ExcelDna from codeplex: link.

As I am using Net 4.0 I do not have .zip support so I first extracted the .xslm files to a flat directory structure then I changed the code to read directly from the files. Then in the Excel I call the ExcelDna extension method as

=ExtractIcons("Office2207IconsGallery";"folder_where_to_store_icons")

The using statements for the utility class (for me):

using System.Xml.Linq;

using System.IO;

using System.Drawing;

using System.Runtime.InteropServices;

using System.Drawing.Imaging;

using Application = Microsoft.Office.Interop.Excel.Application;

using ExcelDna.Integration;

using stdole;

Hope this helps.... Thank you Ismail!

Unsophisticated answered 19/6, 2013 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.