I been trying to find the solution for this for so many hours i'm really tired, i hope someone can indicate me with i'm missing. I will try to be as clear as posible with all the possible information so there is no confusion.
I'm using EPPlus 3.1.3.0, Visual Studio 2010, C#, MVC.NET Framework 4.0 and MS Excel 2007
I'm just trying to do a simple thing: download an Excel file with a picture in it. Nothing else.
I have an action that opens an excel file, fills it with data and adds a picture which code looks like this:
public ActionResult FillExcelFile(string imagePath)
{
FileInfo template = new FileInfo([path_of_excel_file]);
ExcelPackage xls = new ExcelPackage(template);
ExcelWorksheet worksheet = xls.Workbook.Worksheets["Sheet1"];
worksheet.Cells[1, 1].Value = "data1";
worksheet.Cells[1, 2].Value = "data2";
worksheet.Cells[1, 3].Value = "data3";
/* ToDo: add picture */
return File(xls.GetAsByteArray(), "application/vnd.ms-excel", "excel.xlsx"));
}
At this moment everything works great! The file have the information and i can download and open it with no problem at all.
Now i will add the picture i want, i will change the ToDo part with the next code:
Image img = Image.FromFile(imagePath);
ExcelPicture pic = worksheet.Drawings.AddPicture("img", img);
pic.SetPosition(1, 1);
Run it, download it, open it aaand... error:
Excel found unreadable content in "excel.xlsx". Do you want to recover... blah blah blah
Of course i want to recover.
Files open aaand... is empty and an error appear:
Replaced Part: /xl/worksheets/sheet1.xml part with XML error. Load error. Line...
From this moment till now i been adding different code:
Image img = Image.FromFile(imagePath);
ExcelPicture pic = worksheet.Drawings.AddPicture("img", img);
pic.SetPosition(1, 1);
pic.SetSize(100, 100);
And...
Bitmap img = new Bitmap(Image.FromFile(imagePath));
ExcelPicture pic = worksheet.Drawings.AddPicture("img", img);
pic.SetPosition(1, 1);
And...
FileInfo img = new FileInfo(imagePath);
ExcelPicture pic = worksheet.Drawings.AddPicture("img", img);
pic.SetPosition(1, 1);
With the last one there as exception:
: System.ArgumentException: Part URI is not valid per rules defined in the Open Packaging Conventions specification
And many many many more like open the image with a stream, adding the setSize because someone said some kind of problem if you don't define it, define my own URI, save the file in the server then download it, etc.
I really appreciate any help that you can give me, really. I don't known what else to check. If you require more information be free to ask.
i found the problem... or kind of. Thanks to #Chris to guide me in this one and to #Ernie for the sugestion.
The problem is the template file that i was trying to fill has something inside that doesn't work fine when i try to add an image. #Chris says "you already have a drawing part in the template and EPPlus is creating some sort of conflict". I don't know what could that be.
So i create a new template from scratch (the template i was using was done by someone else) and everything worked like charm.
Steps that i performed:
I created a new file with using EPPlus and download it and it worked.
I created a new empty template and add the image with EPPlus and it worked.
I created a new template with all the stuff i needed in it and it worked.
I hope this help someone else if they have a similar problem.
I had the same problem. With prueba prueba's answer I analysed my original template and found this: If the table formatting feature (see screenshot) is used then AddPicture causes the XML errors. My solution was to remove the table formatting.
I've had the same issue and noticed that when you add a background-picture before adding the picture the file gets corrupted. If you add the background picture afterwards it works fine.
osheet.BackgroundImage.Image = My.Resources.anyimage
I found the same problem. I'm using the version 4.1.0.0.
I try to use this code:
Bitmap arquivoLogotipo = new Bitmap(#"C:\xxxxxx.jpg");
ExcelPicture logotipoExcel = principal.Drawings.AddPicture("logotipo", arquivoLogotipo);
logotipoExcel.SetPosition(50, 250);
I try this too:
FileInfo logotipoEndereco = new FileInfo("C\okokoko.jpg");
var logotipo = principal.Drawings.AddPicture("logotipo", logotipoEndereco);
logotipo.SetPosition(50, 250);
In my case, I just have a blank sheet. My cod just insert a name of a project and one image.I really don't know what is happening.
Thanks :D!
Related
I have tried this;
var excelPicture = sheet.Drawings[0] as OfficeOpenXml.Drawing.ExcelPicture;
var img = excelPicture.Image;
However the excelPicture variable become null. How can I create image file from ExcelDrawing??
It seems that this can't be done via EPPlus API. There is the opened issue in the GitHub project repository how export the drawings to a file. But the provided solution in the question does not work (it seems #Onchomngebul himself wrote the the comment)
Alternative solution is to use Workbook class in Spire.XLS nuget-package (or via free version FreeSpire.XLS).
var workbook = new Workbook();
workbook.LoadFromFile(workbookFileName, ExcelVersion.Version2010);
var sheet = workbook.Worksheets[0]; // index or name of your worksheet
var image = workbook.SaveChartAsImage(sheet, 0); // chart index
img.Save(chartFileName, ImageFormat.Png);
For more details please see this comment in the issue.
Another solution is to try to use Excel.ChartObject. I think this question Exporting Excel Charts as Images may help you.
hopefully you guys can help me here. I have this excel interop picture code that seems to be only working on my end. The picture is in a folder in the mapped network drive. When I run the code and receive the excel file, the picture is on the file.
Microsoft.Office.Interop.Excel.Range picRange = xlWorkSheet.get_Range("A1:G1");
picRange.Merge(Type.Missing);
Microsoft.Office.Interop.Excel.Pictures p = xlWorkSheet.Pictures(misValue) as Microsoft.Office.Interop.Excel.Pictures;
Microsoft.Office.Interop.Excel.Picture pic = null;
pic = p.Insert(Server.MapPath("~/images/letter.gif"), misValue);
pic.Left = 87;
pic.Top = Convert.ToDouble(picRange.Top);
pic.Height = 80.25;
pic.Width = 320;
pic.Placement = Microsoft.Office.Interop.Excel.XlPlacement.xlFreeFloating;
However, if I run the code on a different computer, which also has access to that mapped network drive, it the excel file comes with an error on the image that says:
the linked image cannot be displayed. The file may have been moved
renamed or deleted
I've checked three times and made sure that the image file is the right name and the right place. But it only seems to work locally on my computer.
Is there a function in the excel interop library where I can create an instance of the image instead of linking to the image file? Any help will do.
I'm writing a piece of software for visualization of measurement data. For this I use System.Windows.Forms.DataVisualization.Charting.Chart and I do know that I can get the shown image by chartObj.SaveImage to store it to a file.
My software shall have a PDF export in which the picture should be included. For this, I'm using iTextSharp. Again, I do know how to put a picture which I have stored in a file into the PDF by iTextSharp.text.Image.GetInstance.
So by now I am able to take the picture of the chart, put it to a file (e.g. a .jpg file) and load this file again to put it in my PDF. Now I'm looking for a nice solution to get the picture into the PDF without storing it into a file, maybe through a Stream or something like that. I've tried quite some time, but until now I didn't succeed. I've thought of something like
Stream imageStream = image of chartObj;
iTextSharp.text.Image picture = iTextSharp.text.Image.GetInstance(imageStream);
As far as I understand, I fail in putting the picture from the chartObj into a Stream instead of a file. If I had this, I guess I could load the Stream via iTextSharp.text.Image.GetInstance.
Has anyone some help you could offer? Guess it's not that difficult, but I'm new to C# and also to iText, so I'm just a bit stucked here.
Thanks in advance for every thought you have about this!
Anna
SaveImage to a MemoryStream:
using (var chartimage = new MemoryStream())
{
chart.SaveImage(chartimage, ChartImageFormat.Png);
return chartimage.GetBuffer();
}
From:
Microsoft Chart Controls to PDF with iTextSharp and ASP.NET MVC
I have code which works in all sorts of different situations, including when copying images into the body of the document.
The code works when copying (adding) headers and footers from one document to the other, as long as the headers/footers being copied do not contain images.
When I copy a header which has an image in it, then the resulting file is corrupt, and when I try to open it with the OpenXML SDK it throws an exception saying "Compressed part has inconsistent data length".
I do know that the image has to be created in the HeaderPart (as against the MainDocumentPart when copying into the body).
The code which does the merging of the image looks something like:
private void AddSourceImagesToDestination(XElement sourceXml, OpenXmlPart sourcePart, OpenXmlPart destPart) {
foreach(XElement drawingElement in sourceXml.Descendants(_mswDrawingElementName)) {
XAttribute aBlipEmbedAttribute = drawingElement.Descendants(_ablipElementName).First().Attribute(_embedAttributeName);
string relationshipId = aBlipEmbedAttribute.Value;
ImagePart sourceImagePart = (ImagePart)sourcePart.GetPartById(relationshipId);
ImagePart destinationImagePart = ((HeaderPart)destPart).AddImagePart(sourceImagePart.ContentType);
string newRelationshipId = destPart.GetIdOfPart(destinationImagePart);
aBlipEmbedAttribute.SetValue(newRelationshipId);
destinationImagePart.FeedData(sourceImagePart.GetStream(FileMode.Open, FileAccess.Read));
}
}
The above is called passing the source and destination HeaderParts, and the XML of the source header which will after this be copied into the destination document. After calling the above procedure, destinationHeaderPart.Header.Save() is called.
As I said above, if there are no images in the source header, then the resulting document is fine (i.e. when the foreach doesn't find any drawing elements in the source XML).
I wonder, though, whether this symptom of the images in the header is perhaps a red herring and the real problem is somewhere else.
As I said in the comment on the question, the code to include the images into the header and footer was fine - it did the trick.
How I solved the problem of the corrupt file that my code (elsewhere) was creating was by a bit of trial and error. As other contributors have said, the documentation around OpenXML is, to put it mildly, not very good. So there might be another resolution to this problem, and maybe my "solution" just works because of some other side effects.
Anyway, I have some code which looks like this:
private MemoryStream _memoryStream;
private WordprocessingDocument _wordDocument;
...
_wordDocument = WordprocessingDocument.Open(_memoryStream, true);
...
private void ReopenDocument() {
_wordDocument.Package.Flush();
_wordDocument.Close();
MemoryStream newStream = new MemoryStream();
_memoryStream.WriteTo(newStream);
_memoryStream.Close();
_memoryStream = newStream;
_memoryStream.Position = 0L;
_wordDocument = WordprocessingDocument.Open(_memoryStream, true);
}
If I call the ReopenDocument method immediately prior to writing the _memoryStream to a FileStream, then the corruption is avoided.
I'm currently doing the below to add an image to an excel file I'm creating via "interop"
private Excel.Workbook _xlWorkBook;
_xlWorkSheet.Shapes.AddPicture(appPath + #"\ImageFile.png", Microsoft.Office.Core.MsoTriState.msoFalse, Microsoft.Office.Core.MsoTriState.msoCTrue, 5, 5, 60, 60);
I have a couple of questions if I may.
How can I access the picture once it's added - e.g. to draw a border on it.
Doing the above for my app means that I have to distribute the image file as well so I thought I would put it in the application resources. How do I add the image from the resources to the excel file? Again once added, how do I access it to add border etc?
_xlWorkSheet.Shapes.AddPicture(Properties.Resources.ImageFile); //dosn't work
Many thanks
1.) I believe you can access the picture by using
// after adding the picture
Picture pic = (Picture) ActiveSheet.Pictures(ActiveSheet.Pictures.Count - 1);
pic.Border.LineStyle = XlLineStyle.xlContinuous;
pic.Border.Weight = XlBorderWeight.xlMedium;
Or
// add the picture using Pictures.Insert
// this should return a Picture cast-able object
Picture pic = (Picture) ActiveSheet.Pictures.Insert(FileName);
// etc...
2.) The simplest way would be to pull the file from resources write it to a temp file, add it into excel and then remove the temp file.
This code is very much untested. Excel interop is a head-ache.
Sorry or the archeology.
For the second question, adding a picture from a ressource, I may have found a solution using the clipboard:
System.Drawing.Bitmap pic = Properties.Resources.my_ressource;
System.Windows.Forms.Clipboard.SetImage(pic);
Range position = (Range)myWorksheet.Cells[Y, X];
myWorksheet.Paste(position); //copy the clipboard to the given position
RE: 2. I did this:
S = Shapes.AddPicture(filename,MsoTriState.msoFalse,MsoTriState.msoTrue,0,0,50,50);
S.Name = "Picture";
S.Placement = XlPlacement.xlMoveAndSize;