在我的一个项目中,需要分析客户提供的Excel, 读出其中的图片信息(显示在Excel的第几行,第几列,以及图片本身)。
网络上有许多使用Open Xml插入图片到Word,Excel的文章, 但是却没有读取分析其中图片的。经过多次分析及试验,终于达成了这个目标,本文将简要描述如何读取Excel中的图片。
下图所示为一个包含图片的Excel文件的范例, 在这个Excel中,第4列,第10列都插入了图片。
我们把这个excel(.xlsx)文件另存为.zip文件,并解压,得到下图的目录结构,从中我们可以看出文件都是保留在media文件夹下的
而下图所示Drawing文件夹里则定义了Excel每个工作表中图片如何显示(即把某个图片显示在Excel 某个工作表中的第几行,第几列)
因此我们要做的就是读取Drawing 中的图片定义,并从Media中读取对应的图片出来。 在我的应用中,我使用如下数据结构来定义匹配关系
public class PictureInfo { public int FromRow { get; set; } public int FromCol { get; set; } public Image Image { get; set; } }
读取匹配关系的代码如下:
Listpictures = null;using (SpreadsheetDocument document = SpreadsheetDocument.Open(@txtFile.Text, true)) { WorkbookPart wbPart = document.WorkbookPart; var sheets = wbPart.Workbook.Sheets.Take(1); foreach (Sheet sheet in sheets) { WorksheetPart wsPart = (WorksheetPart)wbPart.GetPartById(sheet.Id); DrawingsPart drawingPart = wsPart.GetPartsOfType ().ToList().FirstOrDefault();pictures = new List (); if(drawingPart != null) { foreach (var part in drawingPart.Parts) { PictureInfo pic = new PictureInfo(); ImagePart imgPart = (ImagePart)part.OpenXmlPart ; Image img1 = Image.FromStream(imgPart.GetStream()); pic.Image = img1; pictures.Add(pic); } var worksheetDrawings = drawingPart.WorksheetDrawing.Where(c => c.ChildElements.Any ( a=>a.GetType().FullName == "DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture")).ToList(); foreach (var worksheetDrawing in worksheetDrawings) { if (worksheetDrawing.GetType().FullName == "DocumentFormat.OpenXml.Drawing.Spreadsheet.TwoCellAnchor") { TwoCellAnchor anchor = (TwoCellAnchor)worksheetDrawing; DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture picDef = (DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture) anchor.ChildElements.FirstOrDefault(c => c.GetType().FullName == "DocumentFormat.OpenXml.Drawing.Spreadsheet.Picture"); if (picDef != null) { var embed = picDef.BlipFill.Blip.Embed; if (embed != null) { var picMapping = pictures.FirstOrDefault(c => c.RefId == embed.InnerText); picMapping.FromCol = int.Parse(anchor.FromMarker.ColumnId.InnerText); picMapping.FromRow = int.Parse(anchor.FromMarker.RowId.InnerText); } } // anchor.FromMarker.RowId + anchor.FromMarker.ColumnId } } } } }//把图片信息显示在DataGridView中 var pic1 = pictures.OrderBy(c => c.FromCol).OrderBy(c=>c.FromRow).ToList(); dataGridView1.AutoGenerateColumns = true; dataGridView1.DataSource = pic1;