使用Open XML SDK读取Excel

前端之家收集整理的这篇文章主要介绍了使用Open XML SDK读取Excel前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

先贴代码后简单解释:

  1. public static object[,] BuildTable(Stream inputStream)
  2. {
  3. object[,] table = null;
  4. using (var doc =
  5. SpreadsheetDocument.Open(
  6. inputStream,false))
  7. {
  8. Sheet sheet = doc.WorkbookPart.Workbook.Descendants<Sheet>().FirstOrDefault();
  9.  
  10. var worksheetPart = (WorksheetPart) doc.WorkbookPart.GetPartById(sheet.Id);
  11.  
  12. var headers = worksheetPart.Worksheet.Descendants<Row>()
  13. .FirstOrDefault(x => x.RowIndex == 1);
  14. SheetData sheetData = worksheetPart.Worksheet.GetFirstChild<SheetData>();
  15. var allRows = sheetData.Elements<Row>()
  16. .Where(x => x.RowIndex > 1 && !string.IsNullOrEmpty(x.InnerText)).ToList();
  17. var headerCells = headers.Descendants<Cell>().ToList();
  18. var headerCellReferences =
  19. headerCells.Select(c => Regex.Replace(c.CellReference,@"\d+",string.Empty)).ToArray();
  20. SharedStringTablePart sstPart = doc.WorkbookPart.GetPartsOfType<SharedStringTablePart>().First();
  21. SharedStringTable ssTable = sstPart.SharedStringTable;
  22.  
  23. WorkbookStylesPart workbookStylesPart = doc.WorkbookPart.GetPartsOfType<WorkbookStylesPart>().First();
  24.  
  25. CellFormats cellFormats = workbookStylesPart.Stylesheet.CellFormats;
  26. var headerStrings = headerCells.Select(c => ProcessCellValue(c,ssTable,cellFormats)).ToArray();
  27. table = new object[allRows.Count + 1,headerStrings.Length];
  28. //assign column title to the table
  29. for (int i = 0; i < headerStrings.Length; i++)
  30. {
  31. table[0,i] = headerStrings[i];
  32. }
  33.  
  34. //assign all cell values to the table
  35. for (int i = 0; i < allRows.Count; i++)
  36. {
  37. var cells = allRows[i].Elements<Cell>().Select(c =>
  38. {
  39. c.CellReference = Regex.Replace(c.CellReference,string.Empty);
  40. return c;
  41. });
  42. for (int j = 0; j < headerCells.Count; j++)
  43. {
  44. table[i + 1,j] =
  45. ProcessCellValue(
  46. cells.FirstOrDefault(
  47. c =>
  48. c.CellReference == headerCellReferences[j]),cellFormats);
  49. }
  50. }
  51. }
  52. return table;
  53. }
  54. /// <summary>
  55. /// Process the valus of a cell and return a .NET value
  56. /// </summary>
  57. private static object ProcessCellValue(Cell c,SharedStringTable ssTable,CellFormats cellFormats)
  58. {
  59. if (c == null) return null;
  60. // If there is no data type,this must be a string that has been formatted as a number
  61. if (c.DataType == null)
  62. {
  63. if (c.CellValue == null) return string.Empty;
  64. if (c.StyleIndex == null) return c.CellValue.Text;
  65. CellFormat cf =
  66. cellFormats.Descendants<CellFormat>()
  67. .ElementAt<CellFormat>(Convert.ToInt32(c.StyleIndex.Value));
  68. if (cf.NumberFormatId >= 0 && cf.NumberFormatId <= 13) // This is a number
  69. {
  70. return Convert.ToDecimal(c.CellValue.Text);
  71. }
  72. if (cf.NumberFormatId >= 14 && cf.NumberFormatId <= 22) // This is a date
  73. {
  74. return DateTime.FromOADate(Convert.ToDouble(c.CellValue.Text));
  75. }
  76. return c.CellValue.Text;
  77. }
  78.  
  79. switch (c.DataType.Value)
  80. {
  81. case CellValues.SharedString:
  82. return ssTable.ChildElements[Convert.ToInt32(c.CellValue.Text)].InnerText;
  83. case CellValues.Boolean:
  84. return c.CellValue.Text == "1";
  85. case CellValues.Date:
  86. return DateTime.FromOADate(Convert.ToDouble(c.CellValue.Text));
  87. case CellValues.Number:
  88. return Convert.ToDecimal(c.CellValue.Text);
  89. default:
  90. return c.CellValue != null ? c.CellValue.Text : string.Empty;
  91. }
  92. }

主要值得提的是为什么要使用EXCEL的列头(如A,B,C,D)来取数据而不是用索引。如下面代码片断:

  1. var headerCellReferences =
  2. headerCells.Select(c => Regex.Replace(c.CellReference,string.Empty)).ToArray();

上面是把EXCEL中所有行的单元格的列头由A1,A2,B1,B2全部变成A,A,B,用于后期单元格定位。


如果当你某一列或多列EXCEL单元格是空值,那么取出来的单元格集合将不包含此列,因此集合的长度不确定, 我们不能用索引来取每一行特定单元格的值。


使用:

  1. BuildTable(Request.Files["filename"].InputStream)

如果Exce所有列名和类所有属性列名对应,反射生成集合:
  1. public static IEnumerable<T> BuildList<T>(object[,] table)
  2. {
  3. var list = new List<T>();
  4. Type t = typeof(T);
  5. PropertyInfo[] props = t.GetProperties();
  6. for (int i = 1; i < table.GetLength(0); i++)
  7. {
  8. var item = Activator.CreateInstance<T>();
  9. for (int j = 0; j < table.GetLength(1); j++)
  10. {
  11. var title = Regex.Replace(table[0,j].ToString(),@"\s+",string.Empty);
  12.  
  13. var prop =
  14. props.FirstOrDefault(p => p.Name.Equals(title,StringComparison.InvariantCultureIgnoreCase));
  15. if (prop != null && table[i,j] != null && !string.IsNullOrEmpty(table[i,j].ToString().Trim()))
  16. {
  17. prop.SetValue(item,ConvertHelper.ChangeType(table[i,j],prop.PropertyType),null);
  18. }
  19. }
  20. list.Add(item);
  21. }
  22. return list;
  23. }

使用:
  1. var table = ExcelHelper.BuildTable(file.InputStream);
  2. var students = ExcelHelper.BuildList<Student>(table);
片断代码不严谨,请谨慎使用。

猜你在找的XML相关文章