2017-02-09 3 views
0

Ниже приведены два метода: один использует MemoryStream, а другой использует реальный файл на диске.Как вставить изображение в excel с помощью 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 
     } 
    } 

Если я вызываю первый метод (используйте реальный файл на диске), это нормально, я могу вставить картинку в Ехчел. Но если я прочитаю файл в memystream и вызову method2, я вижу прямоугольник изображения с сообщением об ошибке.

Так что мой вопрос: как вставить изображение в excel через memystream? Потому что я не буду создавать слишком много файлов на диске.

+0

Используйте эту библиотеку, например, EPPplus, чтобы упростить это. [Проверьте этот аналогичный вопрос] (http://stackoverflow.com/questions/11588704/adding-images-into-excel-using-epplus). Необходимый код - 2 строки: 'var picture = ws.Drawings.AddPicture (index.ToString(), логотип); picture.SetPosition (index * 5, 0, 2, 0); ' –

+0

Мне жаль, что я не могу использовать EPPlus, потому что я создаю свой файл excel с помощью openxml в памяти, если я использую EPPlus, я должен изменить слишком много кодов – user2155362

+0

Вызов конструктора Bitmap (ms) считывает данные из потока. Таким образом, Stream.Position больше не находится в позиции 0. Неизбежно вызов FeedData (ms) обречен на чтение мусора. Добавление «ms.Position = 0;» является обходным решением, но, в свою очередь, может привести к неправильной работе растрового изображения, кодек, используемый классом Bitmap, иногда лениво считывает данные пикселя. Подумайте о том, чтобы не создавать растровый объект. –

ответ

0

ОК, я думаю, что нашел решение.

меняю MemoryStream параметр в строку, и преобразовать его в MemoryStream, как показано ниже:

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

Теперь она работает.

Я изучаю его из открытого инструмента xml sdk 2.5.

0

Я считаю, что нужно для создания растровых данных изображения из потока первого

Там это решение уже тем, что здесь на переполнение стека: массив байтов в растровое изображение скопировать-вставить код из раствора:

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

Смежные вопросы