ExportExcelService.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. using NPOI.HSSF.UserModel;
  2. using NPOI.SS.UserModel;
  3. using NPOI.SS.Util;
  4. using NPOI.XSSF.UserModel;
  5. namespace YBEE.EQM.Application;
  6. /// <summary>
  7. /// EXCEL导出服务
  8. /// </summary>
  9. public class ExportExcelService : IExportExcelService, ISingleton
  10. {
  11. /// <summary>
  12. /// 导出 Excel 文件
  13. /// </summary>
  14. /// <typeparam name="T"></typeparam>
  15. /// <param name="input"></param>
  16. /// <returns></returns>
  17. public byte[] ExportExcel<T>(ExportExcelDto<T> input)
  18. {
  19. IWorkbook wb;
  20. if (input.IsXlsx)
  21. {
  22. wb = new XSSFWorkbook();
  23. }
  24. else
  25. {
  26. wb = new HSSFWorkbook();
  27. }
  28. ISheet sheet = wb.CreateSheet(input.SheetName);
  29. sheet.DisplayGridlines = false;
  30. input.SetSheet?.Invoke(sheet);
  31. var cellStyle = GetCellStyle(wb, input.FontSize, input.TitleFontSize);
  32. // 行索引号
  33. int rowNum = 0;
  34. int freezeRowCount = 0;
  35. #region 标题
  36. if (!(string.IsNullOrEmpty(input.Title?.Trim()) || string.IsNullOrWhiteSpace(input.Title?.Trim())))
  37. {
  38. IRow titleRow = sheet.CreateRow(rowNum++);
  39. titleRow.Height = input.TitleHeight ?? ExportExcelCellStyle.DefaultTitleHeight;
  40. AddCell(input.Title.Trim(), titleRow, 0, cellStyle.TitleStyle, sheet);
  41. sheet.AddMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 0, input.Columns.Count - 1));
  42. freezeRowCount++;
  43. }
  44. #endregion
  45. #region 摘要
  46. if (input.BuildSummary == null)
  47. {
  48. string summary = "";
  49. if (input.IncludeExportTime)
  50. {
  51. summary = $"导出时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss} ";
  52. };
  53. if (!(string.IsNullOrEmpty(input.Summary) || string.IsNullOrWhiteSpace(input.Summary)))
  54. {
  55. summary = $"{summary}{input.Summary}";
  56. }
  57. if (summary != "")
  58. {
  59. IRow summaryRow = sheet.CreateRow(rowNum++);
  60. summaryRow.Height = ExportExcelCellStyle.DefaultRowHeight;
  61. AddCell(summary, summaryRow, 0, cellStyle.SummaryStyle, sheet);
  62. sheet.AddMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 0, input.Columns.Count - 1));
  63. freezeRowCount++;
  64. }
  65. }
  66. else
  67. {
  68. int rc = input.BuildSummary(sheet, cellStyle, rowNum);
  69. freezeRowCount += rc;
  70. rowNum += rc;
  71. }
  72. #endregion
  73. #region 列头
  74. IRow headerRow = sheet.CreateRow(rowNum++);
  75. headerRow.Height = input.HeaderHeight;
  76. for (int i = 0; i < input.Columns.Count; i++)
  77. {
  78. var col = input.Columns[i];
  79. AddCell(col.Name, headerRow, i, cellStyle.ColumnHeaderStyle, sheet, col.Width);
  80. }
  81. sheet.CreateFreezePane(0, ++freezeRowCount);
  82. #endregion
  83. #region 数据
  84. foreach (var item in input.Items)
  85. {
  86. IRow row = sheet.CreateRow(rowNum++);
  87. row.Height = input.RowHeight ?? ExportExcelCellStyle.DefaultRowHeight;
  88. for (int i = 0; i < input.Columns.Count; i++)
  89. {
  90. var col = input.Columns[i];
  91. ICellStyle cstyle = cellStyle.CenterCellStyle;
  92. switch (col.Align)
  93. {
  94. case ExportExcelCellAlign.LEFT:
  95. cstyle = cellStyle.LeftCellStyle;
  96. break;
  97. case ExportExcelCellAlign.RIGHT:
  98. cstyle = cellStyle.RightCellStyle;
  99. break;
  100. }
  101. AddCell(col.GetCellValue(item), row, i, cstyle, sheet, col.Width);
  102. }
  103. }
  104. #endregion
  105. MemoryStream ms = new();
  106. wb.Write(ms, false);
  107. ms.Flush();
  108. return ms.ToArray();
  109. }
  110. #region EXCEL公共方法
  111. /// <summary>
  112. /// 获取单元格表头和单元格样式
  113. /// </summary>
  114. /// <param name="wb"></param>
  115. /// <param name="fontSize">正文字体大小</param>
  116. /// <param name="titleFontSize">标题字体大小</param>
  117. /// <returns></returns>
  118. public ExportExcelCellStyle GetCellStyle(IWorkbook wb, double fontSize = 10, double titleFontSize = 16)
  119. {
  120. IDataFormat dataformat = wb.CreateDataFormat();
  121. ExportExcelCellStyle cellStyle = new()
  122. {
  123. DataFormat = dataformat,
  124. TitleStyle = wb.CreateCellStyle(),
  125. SummaryStyle = wb.CreateCellStyle(),
  126. ColumnHeaderStyle = wb.CreateCellStyle(),
  127. ColumnFillHeaderStyle = wb.CreateCellStyle(),
  128. CenterCellStyle = wb.CreateCellStyle(),
  129. LeftCellStyle = wb.CreateCellStyle(),
  130. RightCellStyle = wb.CreateCellStyle(),
  131. FillCellStyle = wb.CreateCellStyle(),
  132. PercentCellStyleP2 = wb.CreateCellStyle(),
  133. NumberCellStyleP2 = wb.CreateCellStyle(),
  134. NumberCellStyleP4 = wb.CreateCellStyle(),
  135. };
  136. // 标题样式
  137. cellStyle.TitleStyle.WrapText = true;
  138. cellStyle.TitleStyle.Alignment = HorizontalAlignment.Center;
  139. cellStyle.TitleStyle.VerticalAlignment = VerticalAlignment.Center;
  140. IFont titleFont = wb.CreateFont();
  141. titleFont.IsBold = true;
  142. titleFont.FontName = cellStyle.TitleFontName;
  143. titleFont.FontHeightInPoints = titleFontSize;
  144. cellStyle.TitleStyle.SetFont(titleFont);
  145. // 摘要样式
  146. cellStyle.SummaryStyle.Alignment = HorizontalAlignment.Left;
  147. cellStyle.SummaryStyle.VerticalAlignment = VerticalAlignment.Center;
  148. IFont summaryFont = wb.CreateFont();
  149. summaryFont.FontName = cellStyle.FontName;
  150. summaryFont.FontHeightInPoints = fontSize;
  151. cellStyle.SummaryStyle.SetFont(summaryFont);
  152. // 列头样式
  153. cellStyle.ColumnHeaderStyle.Alignment = HorizontalAlignment.Center;
  154. cellStyle.ColumnHeaderStyle.VerticalAlignment = VerticalAlignment.Center;
  155. cellStyle.ColumnHeaderStyle.BorderTop = BorderStyle.Thin;
  156. cellStyle.ColumnHeaderStyle.BorderLeft = BorderStyle.Thin;
  157. cellStyle.ColumnHeaderStyle.BorderRight = BorderStyle.Thin;
  158. cellStyle.ColumnHeaderStyle.BorderBottom = BorderStyle.Thin;
  159. cellStyle.ColumnHeaderStyle.WrapText = true;
  160. IFont headerFont = wb.CreateFont();
  161. headerFont.IsBold = true;
  162. headerFont.FontName = cellStyle.TitleFontName;
  163. headerFont.FontHeightInPoints = fontSize;
  164. cellStyle.ColumnHeaderStyle.SetFont(headerFont);
  165. // 带背景列头样式
  166. cellStyle.ColumnFillHeaderStyle.CloneStyleFrom(cellStyle.ColumnHeaderStyle);
  167. if (wb.SpreadsheetVersion.DefaultExtension == "xls")
  168. {
  169. HSSFPalette palette = ((HSSFWorkbook)wb).GetCustomPalette();
  170. palette.SetColorAtIndex(48, 237, 237, 237);
  171. cellStyle.ColumnFillHeaderStyle.FillForegroundColor = palette.FindColor(237, 237, 237).Indexed;
  172. }
  173. else
  174. {
  175. cellStyle.ColumnFillHeaderStyle.FillForegroundColor = 0;
  176. cellStyle.ColumnFillHeaderStyle.FillPattern = FillPattern.SolidForeground;
  177. ((XSSFColor)cellStyle.ColumnFillHeaderStyle.FillForegroundColorColor).SetRgb(new byte[] { 237, 237, 237 });
  178. }
  179. // 默认居中样式
  180. cellStyle.CenterCellStyle.Alignment = HorizontalAlignment.Center;
  181. cellStyle.CenterCellStyle.VerticalAlignment = VerticalAlignment.Center;
  182. cellStyle.CenterCellStyle.BorderTop = BorderStyle.Thin;
  183. cellStyle.CenterCellStyle.BorderLeft = BorderStyle.Thin;
  184. cellStyle.CenterCellStyle.BorderRight = BorderStyle.Thin;
  185. cellStyle.CenterCellStyle.BorderBottom = BorderStyle.Thin;
  186. cellStyle.CenterCellStyle.WrapText = true;
  187. IFont cellFont = wb.CreateFont();
  188. cellFont.FontName = cellStyle.FontName;
  189. cellFont.FontHeightInPoints = fontSize;
  190. cellStyle.CenterCellStyle.SetFont(cellFont);
  191. // 居左样式
  192. cellStyle.LeftCellStyle.CloneStyleFrom(cellStyle.CenterCellStyle);
  193. cellStyle.LeftCellStyle.Alignment = HorizontalAlignment.Left;
  194. // 居右样式
  195. cellStyle.RightCellStyle.CloneStyleFrom(cellStyle.CenterCellStyle);
  196. cellStyle.RightCellStyle.Alignment = HorizontalAlignment.Right;
  197. // 背景样式
  198. cellStyle.FillCellStyle.CloneStyleFrom(cellStyle.CenterCellStyle);
  199. if (wb.SpreadsheetVersion.DefaultExtension == "xls")
  200. {
  201. HSSFPalette palette = ((HSSFWorkbook)wb).GetCustomPalette();
  202. palette.SetColorAtIndex(48, 245, 245, 245);
  203. cellStyle.FillCellStyle.FillForegroundColor = palette.FindColor(245, 245, 245).Indexed;
  204. }
  205. else
  206. {
  207. cellStyle.FillCellStyle.FillForegroundColor = 0;
  208. cellStyle.FillCellStyle.FillPattern = FillPattern.SolidForeground;
  209. ((XSSFColor)cellStyle.FillCellStyle.FillForegroundColorColor).SetRgb(new byte[] { 245, 245, 245 });
  210. }
  211. cellStyle.PercentCellStyleP2.CloneStyleFrom(cellStyle.CenterCellStyle);
  212. cellStyle.PercentCellStyleP2.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00%");
  213. cellStyle.NumberCellStyleP2.CloneStyleFrom(cellStyle.CenterCellStyle);
  214. cellStyle.NumberCellStyleP2.DataFormat = dataformat.GetFormat("0.00");
  215. cellStyle.NumberCellStyleP4.CloneStyleFrom(cellStyle.CenterCellStyle);
  216. cellStyle.NumberCellStyleP4.DataFormat = dataformat.GetFormat("0.0000");
  217. return cellStyle;
  218. }
  219. /// <summary>
  220. /// 添加单元格
  221. /// </summary>
  222. /// <param name="value"></param>
  223. /// <param name="row"></param>
  224. /// <param name="columnIndex"></param>
  225. /// <param name="cellStyle"></param>
  226. /// <param name="sheet"></param>
  227. /// <param name="width"></param>
  228. /// <param name="zeroToBlank">0转为空白</param>
  229. /// <param name="cellType"></param>
  230. public ICell AddCell(object value, IRow row, int columnIndex, ICellStyle cellStyle, ISheet sheet = null, int? width = null, bool? zeroToBlank = false, CellType? cellType = null)
  231. {
  232. bool isSetBlank = false;
  233. if (zeroToBlank == true)
  234. {
  235. if (double.TryParse(value.ToString(), out double v))
  236. {
  237. isSetBlank = v == 0;
  238. }
  239. }
  240. ICell cell = row.CreateCell(columnIndex);
  241. cell.CellStyle = cellStyle;
  242. if (value != null && isSetBlank == false)
  243. {
  244. var valueTypeName = value.GetType().Name;
  245. if (cellType.HasValue)
  246. {
  247. cell.SetCellType(cellType.Value);
  248. }
  249. if (cellType.HasValue && cellType == CellType.Formula)
  250. {
  251. cell.CellFormula = value.ToString();
  252. }
  253. else if (valueTypeName.Contains("Int") || valueTypeName == "Double" || valueTypeName == "Decimal")
  254. {
  255. cell.SetCellValue(Convert.ToDouble(value));
  256. }
  257. else if (valueTypeName == "String")
  258. {
  259. cell.SetCellValue(value.ToString());
  260. }
  261. else if (valueTypeName == "Boolean")
  262. {
  263. cell.SetCellValue((bool)value);
  264. }
  265. }
  266. if (sheet != null && width.HasValue)
  267. {
  268. sheet.SetColumnWidth(columnIndex, width.Value * 256);
  269. }
  270. return cell;
  271. }
  272. #endregion
  273. }