vba 如何从 Microsoft Office 2007 保存 ImageMSO 图标?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1073322/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 10:32:51  来源:igfitidea点击:

How to save ImageMSO icon from Microsoft Office 2007?

vbaiconsoffice-2007

提问by Soul_Master

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?

我从 Microsoft Office 2007 中找到了很多不错的图标。您知道使用 VBA 提取所有图标并将其保存为 PNG 文件吗?

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

部分图像 MSO http://rabu4g.bay.livefilestore.com/y1p2SF1q63YjDjPNmK4nYMW2644r9AO2aAsE__vBYznTeXD0b4SJUU0O07fxPD0r7aO_83gCJ-8OfcOQsFneCapBUture.PNG/

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

以下代码是用于从 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.

我可以将所有显示为 PictureBox 控件并将 excel 文件保存为网页。但是,每个图标的质量都非常低。

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.

此外,我尝试使用以下代码创建用于导出为 Bitmap 对象的 C# Excel 插件项目。但我发现它不能导出为半透明的 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.

附注。我想将所有图标保存为 PNG 格式,因为我需要使用它的半透明功能。它允许我在大多数背景颜色上使用所有图标而不是白色背景。

回答by Alton XL

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.

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

Microsoft Office Icons (ImageMSO) Gallery & Extraction

Microsoft Office 图标 (ImageMSO) 图库和提取

ImageMSO Gallery on Microsoft Excel 2013 running Windows 8

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

回答by Ismail Degani

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.

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

Steps are:

步骤是:

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

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

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

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

{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}

{代码}

回答by caving

All of the PNG files can be found hereThese 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.

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

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:

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

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)

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(另存为文件方法)

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

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

回答by gbr

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:

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

The solution requires ExcelDna from codeplex: link.

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

As I am using Net 4.0I do not have .zipsupport so I first extracted the .xslmfiles 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

由于我使用Net 4.0我没有.zip文件的支持,所以我第一次提取的.xslm文件到一个平面目录结构,然后,我改变了代码直接从文件中读取。然后在 Excel 中,我将 ExcelDna 扩展方法称为

=ExtractIcons("Office2207IconsGallery";"folder_where_to_store_icons")

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

实用程序类的 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;

Hope this helps.... Thank you Ismail!

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