2017-02-09 78 views
0

下面是两种方法,一种使用MemoryStream,另一种使用磁盘上的真实文件。如何使用MemoryStream插入图片到Excel中?

 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?因为我不会在磁盘上创建太多文件。

+0

使用图书馆像EPPplus对此进行简化。 [检查这个类似的问题](http://stackoverflow.com/questions/11588704/adding-images-into-excel-using-epplus)。所需的代码是2行:'var picture = ws.Drawings.AddPicture(index.ToString(),logo); picture.SetPosition(指数* 5,0,2,0);' –

+0

我很抱歉,我想我不能使用EPPlus,因为我在内存中创建OPENXML我的Excel文件,如果我用EPPlus,我应该修改代码太多 – user2155362

+0

Bitmap(ms)构造函数调用从流中读取数据。所以Stream.Position不再处于位置0.不可避免地,FeedData(ms)调用注定要读垃圾。添加'ms.Position = 0;'是一种变通方法,但可以反过来使位图表现不好,由位图类使用的编解码器有时懒惰地读出像素数据。考虑不要创建位图对象。 –

回答

0

OK,我想我已经找到了解决方案。

我改变MemoryStream的参数字符串,并将其转换为MemoryStream的象下面这样:现在

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

,它的工作原理。

我学习它从开放XML SDK 2.5的生产力工具。

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

你可能想添加一个链接到SO来自这个答案 – Metoniem