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!
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.
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");
}
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
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://stackoverflow.com/questions/18661239/closedxml-add-image