ClosedXML add image

给你一囗甜甜゛ 提交于 2020-01-02 07:17:28

问题


I am able to add in an image to an excel spreadsheet by using OpenXML. However for the rest of the program I use ClosedXML to add data. I can add data at a specific cell using the column and row index. If I can add an image to an excel (It currently is a separate layer it seems, hovering over cells), how can I add it to a cell using ClosedXML?

    //Adds an image to the excel file
    public void AddImageToExcel(SpreadsheetDocument sd, MemoryStream imagestream)
    {
        DrawingsPart dp = sd.WorkbookPart.WorksheetParts.First().AddNewPart<DrawingsPart>();
        ImagePart imgp = dp.AddImagePart(ImagePartType.Jpeg, sd.WorkbookPart.WorksheetParts.First().GetIdOfPart(dp));

        MemoryStream bmstream = new MemoryStream(imagestream.ToArray());
        bmstream.Seek(0, SeekOrigin.Begin);

        MemoryStream fs;
        using (fs = imagestream)
        {
            fs.Position = 0;
            imgp.FeedData(fs);
        }

        DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualDrawingProperties nvdp = new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualDrawingProperties();
        nvdp.Id = 1025;
        nvdp.Name = "Chart Image";
        nvdp.Description = "Image";
        DocumentFormat.OpenXml.Drawing.PictureLocks piclocks = new DocumentFormat.OpenXml.Drawing.PictureLocks();
        piclocks.NoChangeAspect = true;
        piclocks.NoChangeArrowheads = true;
        DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualPictureDrawingProperties nvpdp = new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualPictureDrawingProperties();
        nvpdp.PictureLocks = piclocks;
        DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualPictureProperties nvpp = new DocumentFormat.OpenXml.Drawing.Spreadsheet.NonVisualPictureProperties();
        nvpp.NonVisualDrawingProperties = nvdp;
        nvpp.NonVisualPictureDrawingProperties = nvpdp;

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

        DocumentFormat.OpenXml.Drawing.Spreadsheet.BlipFill blipfill = new DocumentFormat.OpenXml.Drawing.Spreadsheet.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(bmstream);

        DocumentFormat.OpenXml.Drawing.Extents extents = new DocumentFormat.OpenXml.Drawing.Extents();
        extents.Cx = ((long)bm.Width * (long)((float)914400 / bm.HorizontalResolution));
        extents.Cy = ((long)bm.Height * (long)((float)914400 / bm.VerticalResolution));
        bm.Dispose();
        t2d.Extents = extents;
        DocumentFormat.OpenXml.Drawing.Spreadsheet.ShapeProperties sp = new DocumentFormat.OpenXml.Drawing.Spreadsheet.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;

        DocumentFormat.OpenXml.Drawing.Spreadsheet.Position pos = new DocumentFormat.OpenXml.Drawing.Spreadsheet.Position();

        //The position corrosponds these numbers. X= 600000 & y = 200000 adds up to 1 cell
        pos.X = 600000;
        pos.Y = 200000;

        Extent ext = new Extent();
        ext.Cx = extents.Cx;
        ext.Cy = extents.Cy;
        AbsoluteAnchor anchor = new AbsoluteAnchor();

        Xdr.Position pp = new Xdr.Position();
        pp.X = 0;
        pp.Y = 0;


        anchor.Position = pp;
        anchor.Position = pos;
        anchor.Extent = ext;
        anchor.Append(picture);
        anchor.Append(new ClientData());
        WorksheetDrawing wsd = new WorksheetDrawing();
        wsd.Append(anchor);
        Drawing drawing = new Drawing();
        drawing.Id = dp.GetIdOfPart(imgp);
        wsd.Save(dp);
        sd.WorkbookPart.WorksheetParts.First().Worksheet.Append(drawing);
        MessageBox.Show("Excel File created");
    }

This is the code I used, which I found here on stack overflow somewhere. I modified it to use a MemoryStream for the image. So firstly one of the problems I have is that I pass a spreadsheet document to the method, however I'm not sure what I can do in ClosedXML to fix this Really appreciate any help with how I could go about this. Ideally I would love to simply say

ws.Cell(colnum, rownum).Value = AddImageToExcel(wb, ImageToMemoryStream(imagelocation));

Thanks for any help!


回答1:


I little bit late here, but in case someone else comes looking I've added (limited) image support to ClosedXML.

Fork can be found at https://closedxml.codeplex.com/SourceControl/network/forks/ajwhiteway/ClosedXMLImageSupport

EDIT: Adding some detail to how it works.

New classes, XLPicture and XLMarker, have been added.

Picture can be created by

  XLPicture pic = new XLPicture
  {
    NoChangeAspect = true,
    NoMove = true,
    NoResize = true,
    ImageStream = fIn,
    Name = "Test Image"
  };

As of now it only accepts streams, not files, and it only spits out JPEGs. This can be changed if there is demand.

Once your picture is created you create a marker for where it goes

  XLMarker fMark = new XLMarker
  {
    ColumnId = 2,
    RowId = 2
  };
  pic.AddMarker(fMark);

If you add a single marker it will embed the image directly into the cell. If you add 2 markers it will span the image across the two markers.

Then to add it to the sheet just

 worksheet.AddPicture(pic);

Cheers guys.




回答2:


ClosedXML now has basic image/picture support. As per https://github.com/ClosedXML/ClosedXML/wiki/How-can-I-insert-an-image :

using (var wb = new XLWorkbook())
{
  var ws = wb.AddWorksheet("Sheet1");

  var imagePath = @"c:\path\to\your\image.jpg";
  var image = ws.AddPicture(ImageLocation)
      .MoveTo(ws.Cell("B3").Address)
      .Scale(.5); // optional: resize picture

  wb.SaveAs("file.xlsx");
}



回答3:


Where you able to solve it? We are facing a similar problem, we are bound to ClosedXML, inserting pictures will not be supported by ClosedXML unless someone volunteer to write the code... If you where able to solve it we would appreciate if you would share your solution! Regards, Benno




回答4:


This feature has been included in closed XML from version 0.89.0

This code is for MVC5 but you can use it else where as well.

        public ActionResult Contact()
    {
        //Creating excelsheet and adding workbook with name Picture
        XLWorkbook workbook = new XLWorkbook();
        IXLWorksheet worksheet = workbook.Worksheets.Add("Picture");

        //Adjusting size of the excel cell as per requirement
        worksheet.Column(3).Width = 60;
        worksheet.Row(3).Height = 50;

        var imagePath = @"~/Images/Picture2.png";

        //Adding image to the worksheet and moving it to the cell
        var image = worksheet.AddPicture(Server.MapPath(imagePath))
            .MoveTo(worksheet.Cell(3, 3).Address);
        image.Name = "Logo";

        //Scaling down image as per our cell size
        image.ScaleWidth(.5);
        image.ScaleHeight(.3);

        //Formating the cell with border and color
        worksheet.Cell(3, 3).Style.Border.OutsideBorder = XLBorderStyleValues.Thick;
        worksheet.Cell(3, 3).Style.Border.OutsideBorderColor = XLColor.Blue;

        //asving worksheet in memory stream
        MemoryStream stream = new MemoryStream();
        workbook.SaveAs(stream);
        stream.Position = 0;
        //returning the final excelsheet with name Picture
        return new FileStreamResult(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
        { FileDownloadName = "Pictures.xlsx" };
    }

You can refer to the link for detailed explaination. Hope it helps somebody

https://www.youtube.com/watch?v=8X0kg0YzI2g&t=242s



来源:https://stackoverflow.com/questions/18661239/closedxml-add-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!