如何使用MemoryStream将图片插入excel?

时间:2017-02-09 12:40:46

标签: c# excel openxml

以下是两种方法,一种使用MemoryStream,另一种使用磁盘上的真实文件。

        public void InsertImage(long x, long y, long? width, long? height, string sImagePath, WorksheetPart wsp)
    {
        try
        {
            DrawingsPart dp;
            ImagePart imgp;
            WorksheetDrawing wsd;

            ImagePartType ipt;
            switch (sImagePath.Substring(sImagePath.LastIndexOf('.') + 1).ToLower())
            {
                case "png":
                    ipt = ImagePartType.Png;
                    break;
                case "jpg":
                case "jpeg":
                    ipt = ImagePartType.Jpeg;
                    break;
                case "gif":
                    ipt = ImagePartType.Gif;
                    break;
                default:
                    return;
            }

            if (wsp.DrawingsPart == null)
            {
                //----- no drawing part exists, add a new one

                dp = wsp.AddNewPart<DrawingsPart>();
                imgp = dp.AddImagePart(ipt, wsp.GetIdOfPart(dp));
                wsd = new WorksheetDrawing();
            }
            else
            {
                //----- use existing drawing part

                dp = wsp.DrawingsPart;
                imgp = dp.AddImagePart(ipt);
                dp.CreateRelationshipToPart(imgp);
                wsd = dp.WorksheetDrawing;
            }

            using (FileStream fs = new FileStream(sImagePath, FileMode.Open))
            {
                imgp.FeedData(fs);
            }

            int imageNumber = dp.ImageParts.Count<ImagePart>();
            if (imageNumber == 1)
            {
                Drawing drawing = new Drawing();
                drawing.Id = dp.GetIdOfPart(imgp);
                wsp.Worksheet.Append(drawing);
            }

            NonVisualDrawingProperties nvdp = new NonVisualDrawingProperties();
            nvdp.Id = new UInt32Value((uint)(1024 + imageNumber));
            nvdp.Name = "Picture " + imageNumber.ToString();
            nvdp.Description = "";
            DocumentFormat.OpenXml.Drawing.PictureLocks picLocks = new DocumentFormat.OpenXml.Drawing.PictureLocks();
            picLocks.NoChangeAspect = true;
            picLocks.NoChangeArrowheads = true;
            NonVisualPictureDrawingProperties nvpdp = new NonVisualPictureDrawingProperties();
            nvpdp.PictureLocks = picLocks;
            NonVisualPictureProperties nvpp = new NonVisualPictureProperties();
            nvpp.NonVisualDrawingProperties = nvdp;
            nvpp.NonVisualPictureDrawingProperties = nvpdp;

            DocumentFormat.OpenXml.Drawing.Stretch stretch = new DocumentFormat.OpenXml.Drawing.Stretch();
            stretch.FillRectangle = new DocumentFormat.OpenXml.Drawing.FillRectangle();

            BlipFill blipFill = new BlipFill();
            DocumentFormat.OpenXml.Drawing.Blip blip = new DocumentFormat.OpenXml.Drawing.Blip();
            blip.Embed = dp.GetIdOfPart(imgp);
            blip.CompressionState = DocumentFormat.OpenXml.Drawing.BlipCompressionValues.Print;
            blipFill.Blip = blip;
            blipFill.SourceRectangle = new DocumentFormat.OpenXml.Drawing.SourceRectangle();
            blipFill.Append(stretch);

            DocumentFormat.OpenXml.Drawing.Transform2D t2d = new DocumentFormat.OpenXml.Drawing.Transform2D();
            DocumentFormat.OpenXml.Drawing.Offset offset = new DocumentFormat.OpenXml.Drawing.Offset();
            offset.X = 0;
            offset.Y = 0;
            t2d.Offset = offset;
            Bitmap bm = new Bitmap(sImagePath);

            DocumentFormat.OpenXml.Drawing.Extents extents = new DocumentFormat.OpenXml.Drawing.Extents();

            if (width == null)
                extents.Cx = (long)bm.Width * (long)((float)914400 / bm.HorizontalResolution);
            else
                extents.Cx = width * (long)((float)914400 / bm.HorizontalResolution);

            if (height == null)
                extents.Cy = (long)bm.Height * (long)((float)914400 / bm.VerticalResolution);
            else
                extents.Cy = height * (long)((float)914400 / bm.VerticalResolution);

            bm.Dispose();
            t2d.Extents = extents;
            ShapeProperties sp = new ShapeProperties();
            sp.BlackWhiteMode = DocumentFormat.OpenXml.Drawing.BlackWhiteModeValues.Auto;
            sp.Transform2D = t2d;
            DocumentFormat.OpenXml.Drawing.PresetGeometry prstGeom = new DocumentFormat.OpenXml.Drawing.PresetGeometry();
            prstGeom.Preset = DocumentFormat.OpenXml.Drawing.ShapeTypeValues.Rectangle;
            prstGeom.AdjustValueList = new DocumentFormat.OpenXml.Drawing.AdjustValueList();
            sp.Append(prstGeom);
            sp.Append(new DocumentFormat.OpenXml.Drawing.NoFill());

            DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture picture = new DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture();
            picture.NonVisualPictureProperties = nvpp;
            picture.BlipFill = blipFill;
            picture.ShapeProperties = sp;

            Position pos = new Position();
            pos.X = x * 914400 / 72;
            pos.Y = y * 914400 / 72;
            Extent ext = new Extent();
            ext.Cx = extents.Cx;
            ext.Cy = extents.Cy;
            AbsoluteAnchor anchor = new AbsoluteAnchor();
            anchor.Position = pos;
            anchor.Extent = ext;
            anchor.Append(picture);
            anchor.Append(new ClientData());
            wsd.Append(anchor);
            wsd.Save(dp);
        }
        catch (Exception ex)
        {
            throw ex; // or do something more interesting if you want
        }
    }

    //use memorystream
public void InsertImage(long x, long y, long? width, long? height, MemoryStream ms, WorksheetPart wsp)
        {
            try
            {
                DrawingsPart dp;
                ImagePart imgp;
            WorksheetDrawing wsd;

            ImagePartType ipt = ImagePartType.Jpeg;

            if (wsp.DrawingsPart == null)
            {
                //----- no drawing part exists, add a new one

                dp = wsp.AddNewPart<DrawingsPart>();
                imgp = dp.AddImagePart(ipt, wsp.GetIdOfPart(dp));
                wsd = new WorksheetDrawing();
            }
            else
            {
                //----- use existing drawing part

                dp = wsp.DrawingsPart;
                imgp = dp.AddImagePart(ipt);
                dp.CreateRelationshipToPart(imgp);
                wsd = dp.WorksheetDrawing;
            }
            Bitmap bitmap = new Bitmap(ms);
            imgp.FeedData(ms);

            int imageNumber = dp.ImageParts.Count<ImagePart>();
            if (imageNumber == 1)
            {
                Drawing drawing = new Drawing();
                drawing.Id = dp.GetIdOfPart(imgp);
                wsp.Worksheet.Append(drawing);
            }

            NonVisualDrawingProperties nvdp = new NonVisualDrawingProperties();
            nvdp.Id = new UInt32Value((uint)(1024 + imageNumber));
            nvdp.Name = "Picture " + imageNumber.ToString();
            nvdp.Description = "";
            DocumentFormat.OpenXml.Drawing.PictureLocks picLocks = new DocumentFormat.OpenXml.Drawing.PictureLocks();
            picLocks.NoChangeAspect = true;
            picLocks.NoChangeArrowheads = true;
            NonVisualPictureDrawingProperties nvpdp = new NonVisualPictureDrawingProperties();
            nvpdp.PictureLocks = picLocks;
            NonVisualPictureProperties nvpp = new NonVisualPictureProperties();
            nvpp.NonVisualDrawingProperties = nvdp;
            nvpp.NonVisualPictureDrawingProperties = nvpdp;

            DocumentFormat.OpenXml.Drawing.Stretch stretch = new DocumentFormat.OpenXml.Drawing.Stretch();
            stretch.FillRectangle = new DocumentFormat.OpenXml.Drawing.FillRectangle();

            BlipFill blipFill = new BlipFill();
            DocumentFormat.OpenXml.Drawing.Blip blip = new DocumentFormat.OpenXml.Drawing.Blip();
            blip.Embed = dp.GetIdOfPart(imgp);
            blip.CompressionState = DocumentFormat.OpenXml.Drawing.BlipCompressionValues.Print;
            blipFill.Blip = blip;
            blipFill.SourceRectangle = new DocumentFormat.OpenXml.Drawing.SourceRectangle();
            blipFill.Append(stretch);

            DocumentFormat.OpenXml.Drawing.Transform2D t2d = new DocumentFormat.OpenXml.Drawing.Transform2D();
            DocumentFormat.OpenXml.Drawing.Offset offset = new DocumentFormat.OpenXml.Drawing.Offset();
            offset.X = 0;
            offset.Y = 0;
            t2d.Offset = offset;


            DocumentFormat.OpenXml.Drawing.Extents extents = new DocumentFormat.OpenXml.Drawing.Extents();
            //Bitmap bitmap = new Bitmap(ms);
            if (width == null)
                extents.Cx = (long)bitmap.Width * (long)((float)914400 / bitmap.HorizontalResolution);
            else
                extents.Cx = width * (long)((float)914400 / bitmap.HorizontalResolution);

            if (height == null)
                extents.Cy = (long)bitmap.Height * (long)((float)914400 / bitmap.VerticalResolution);
            else
                extents.Cy = height * (long)((float)914400 / bitmap.VerticalResolution);

            bitmap.Dispose();

            t2d.Extents = extents;
            ShapeProperties sp = new ShapeProperties();
            sp.BlackWhiteMode = DocumentFormat.OpenXml.Drawing.BlackWhiteModeValues.Auto;
            sp.Transform2D = t2d;
            DocumentFormat.OpenXml.Drawing.PresetGeometry prstGeom = new DocumentFormat.OpenXml.Drawing.PresetGeometry();
            prstGeom.Preset = DocumentFormat.OpenXml.Drawing.ShapeTypeValues.Rectangle;
            prstGeom.AdjustValueList = new DocumentFormat.OpenXml.Drawing.AdjustValueList();
            sp.Append(prstGeom);
            sp.Append(new DocumentFormat.OpenXml.Drawing.NoFill());

            DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture picture = new DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture();
            picture.NonVisualPictureProperties = nvpp;
            picture.BlipFill = blipFill;
            picture.ShapeProperties = sp;

            Position pos = new Position();
            pos.X = x * 914400 / 72;
            pos.Y = y * 914400 / 72;
            Extent ext = new Extent();
            ext.Cx = extents.Cx;
            ext.Cy = extents.Cy;
            AbsoluteAnchor anchor = new AbsoluteAnchor();
            anchor.Position = pos;
            anchor.Extent = ext;
            anchor.Append(picture);
            anchor.Append(new ClientData());
            wsd.Append(anchor);
            wsd.Save(dp);
        }
        catch (Exception ex)
        {
            throw ex; // or do something more interesting if you want
        }
    }

如果我调用第一种方法(在磁盘上使用真实文件),没关系,我可以将我的图片插入excel文件。但是如果我将文件读入memorystream并调用method2,我可以看到带有错误信息的图片矩形。

所以我的问题是如何通过memorystream将图片插入excel?因为我不会在磁盘上创建太多文件。

2 个答案:

答案 0 :(得分:0)

我相信您需要先从流中创建位图图像数据

Stack Overflow上有一个解决方案:字节数组到位图图像 我从解决方案中复制粘贴代码:

int w= 100;
int h = 200;
int ch = 3; //number of channels (ie. assuming 24 bit RGB in this case)

byte[] imageData    = new byte[w*h*ch]; //you image data here
Bitmap bitmap       = new Bitmap(w,h,PixelFormat.Format24bppRgb);
BitmapData bmData   = bitmap.LockBits(new System.Drawing.Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
IntPtr pNative      = bmData.Scan0;
Marshal.Copy(imageData,0,pNative,w*h*ch);
bitmap.UnlockBits(bmData);

答案 1 :(得分:0)

好的,我想我找到了解决方案。

我将memorystream参数更改为字符串,并将其转换为内存流,如下所示:

MemoryStream ms = new System.IO.MemoryStream(System.Convert.FromBase64String(str))

现在,它有效。

我是从开放的xml sdk 2.5生产力工具中学习的。