2017-02-09 40 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

相關問題