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.

4

4 回答 4

8

我在 Excel 开发中经常使用 ImageMso。偶然发现这篇文章后,我更进一步,将一个包放在一起,以直观地搜索、提取和保存 Microsoft Excel 中的图标作为文件或复制并粘贴(具有 alpha 通道透明度)到另一个应用程序。我还从各种来源编制了一份包含 8,899 个不同 ImageMso 名称的列表。我希望其他人可以发现这很有用。

Microsoft Office 图标 (ImageMSO) 库和提取

运行 Windows 8 的 Microsoft Excel 2013 上的 ImageMSO 库

于 2013-09-15T05:09:21.663 回答
4

我已经完成了一个 C# Utility 类,用于将 Office2007 画廊图标提取到 .png 文件,同时正确地保持它们的透明度。主要代码取自 Andrew Whitechapel 撰写的一篇精彩文章 ( http://blogs.msdn.com/b/andreww/archive/2007/10/10/preserving-the-alpha-channel-when-converting-images。 .aspx)。我已将其与 Office 2007 示例图标表集成,以防您要将所有这些图标提取到目标文件夹。

步骤是:

1) 在http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=11675下载 Office Gallery 电子表格

2) 使用 Office2007IconsGallery.xlsm 示例电子表格的位置以及您想要提取图标的目标文件夹调用 OfficeIcons.ExtractAllIcons()。

{代码}

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);

}

{代码}

于 2011-09-26T19:38:16.163 回答
0

所有的 PNG 文件都可以在这里找到。这些都是 PNG 格式的。好编程!(这里也提供了一个不错的 ZIP 存档) ZIP 存档包含所有 17 个 Excel 图标。

当您使用 GetImageMso 方法时,您最终会得到对象的 IPicture 接口。IPicture 界面访问适合以原始格式保存到文件的图标 - .ICO、.WMF 或 .BMP 不支持 PNG 格式。以下链接解释了为什么这不能直接实现:

http://msdn.microsoft.com/en-us/library/aa434604.aspx(msoGetImageMso 方法 ) http://msdn.microsoft.com/en-us/library/ms680761%28VS.85%29.aspx(IPicture接口) http://msdn.microsoft.com/en-us/library/ms694504%28VS.85%29.aspx (另存为文件方法)

但是,使用更复杂的方法将产生您想要的结果:

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

于 2009-11-24T18:50:27.057 回答
0

我已经尝试过 Ismail 的回答,效果很好。然而,我花了一段时间才弄清楚如何让它工作。我可以分享一点知识:

该解决方案需要来自 codeplex: link的 ExcelDna 。

当我使用时,Net 4.0我没有.zip支持,所以我首先将.xslm文件解压缩到一个平面目录结构,然后我将代码更改为直接从文件中读取。然后在 Excel 中,我将 ExcelDna 扩展方法称为

=ExtractIcons("Office2207IconsGallery";"folder_where_to_store_icons")

实用程序类的 using 语句(对我而言):

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;

希望这会有所帮助....谢谢伊斯梅尔!

于 2013-06-19T17:00:21.340 回答