using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; namespace YBEE.EQM.Application; /// /// EXCEL导出服务 /// public class ExportExcelService : IExportExcelService, ISingleton { /// /// 导出 Excel 文件 /// /// /// /// public byte[] ExportExcel(ExportExcelDto input) { IWorkbook wb; if (input.IsXlsx) { wb = new XSSFWorkbook(); } else { wb = new HSSFWorkbook(); } ISheet sheet = wb.CreateSheet(input.SheetName); sheet.DisplayGridlines = false; input.SetSheet?.Invoke(sheet); var cellStyle = GetCellStyle(wb, input.FontSize, input.TitleFontSize); // 行索引号 int rowNum = 0; int freezeRowCount = 0; #region 标题 if (!(string.IsNullOrEmpty(input.Title?.Trim()) || string.IsNullOrWhiteSpace(input.Title?.Trim()))) { IRow titleRow = sheet.CreateRow(rowNum++); titleRow.Height = input.TitleHeight ?? ExportExcelCellStyle.DefaultTitleHeight; AddCell(input.Title.Trim(), titleRow, 0, cellStyle.TitleStyle, sheet); sheet.AddMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 0, input.Columns.Count - 1)); freezeRowCount++; } #endregion #region 摘要 if (input.BuildSummary == null) { string summary = ""; if (input.IncludeExportTime) { summary = $"导出时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss} "; }; if (!(string.IsNullOrEmpty(input.Summary) || string.IsNullOrWhiteSpace(input.Summary))) { summary = $"{summary}{input.Summary}"; } if (summary != "") { IRow summaryRow = sheet.CreateRow(rowNum++); summaryRow.Height = ExportExcelCellStyle.DefaultRowHeight; AddCell(summary, summaryRow, 0, cellStyle.SummaryStyle, sheet); sheet.AddMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 0, input.Columns.Count - 1)); freezeRowCount++; } } else { int rc = input.BuildSummary(sheet, cellStyle, rowNum); freezeRowCount += rc; rowNum += rc; } #endregion #region 列头 IRow headerRow = sheet.CreateRow(rowNum++); headerRow.Height = input.HeaderHeight; for (int i = 0; i < input.Columns.Count; i++) { var col = input.Columns[i]; AddCell(col.Name, headerRow, i, cellStyle.ColumnHeaderStyle, sheet, col.Width); } sheet.CreateFreezePane(0, ++freezeRowCount); #endregion #region 数据 foreach (var item in input.Items) { IRow row = sheet.CreateRow(rowNum++); row.Height = input.RowHeight ?? ExportExcelCellStyle.DefaultRowHeight; for (int i = 0; i < input.Columns.Count; i++) { var col = input.Columns[i]; ICellStyle cstyle = cellStyle.CenterCellStyle; switch (col.Align) { case ExportExcelCellAlign.LEFT: cstyle = cellStyle.LeftCellStyle; break; case ExportExcelCellAlign.RIGHT: cstyle = cellStyle.RightCellStyle; break; } AddCell(col.GetCellValue(item), row, i, cstyle, sheet, col.Width); } } #endregion MemoryStream ms = new(); wb.Write(ms, false); ms.Flush(); return ms.ToArray(); } #region EXCEL公共方法 /// /// 获取单元格表头和单元格样式 /// /// /// 正文字体大小 /// 标题字体大小 /// public ExportExcelCellStyle GetCellStyle(IWorkbook wb, double fontSize = 10, double titleFontSize = 16) { IDataFormat dataformat = wb.CreateDataFormat(); ExportExcelCellStyle cellStyle = new() { DataFormat = dataformat, TitleStyle = wb.CreateCellStyle(), SummaryStyle = wb.CreateCellStyle(), ColumnHeaderStyle = wb.CreateCellStyle(), ColumnFillHeaderStyle = wb.CreateCellStyle(), CenterCellStyle = wb.CreateCellStyle(), LeftCellStyle = wb.CreateCellStyle(), RightCellStyle = wb.CreateCellStyle(), FillCellStyle = wb.CreateCellStyle(), PercentCellStyleP2 = wb.CreateCellStyle(), NumberCellStyleP2 = wb.CreateCellStyle(), NumberCellStyleP4 = wb.CreateCellStyle(), }; // 标题样式 cellStyle.TitleStyle.WrapText = true; cellStyle.TitleStyle.Alignment = HorizontalAlignment.Center; cellStyle.TitleStyle.VerticalAlignment = VerticalAlignment.Center; IFont titleFont = wb.CreateFont(); titleFont.IsBold = true; titleFont.FontName = cellStyle.TitleFontName; titleFont.FontHeightInPoints = titleFontSize; cellStyle.TitleStyle.SetFont(titleFont); // 摘要样式 cellStyle.SummaryStyle.Alignment = HorizontalAlignment.Left; cellStyle.SummaryStyle.VerticalAlignment = VerticalAlignment.Center; IFont summaryFont = wb.CreateFont(); summaryFont.FontName = cellStyle.FontName; summaryFont.FontHeightInPoints = fontSize; cellStyle.SummaryStyle.SetFont(summaryFont); // 列头样式 cellStyle.ColumnHeaderStyle.Alignment = HorizontalAlignment.Center; cellStyle.ColumnHeaderStyle.VerticalAlignment = VerticalAlignment.Center; cellStyle.ColumnHeaderStyle.BorderTop = BorderStyle.Thin; cellStyle.ColumnHeaderStyle.BorderLeft = BorderStyle.Thin; cellStyle.ColumnHeaderStyle.BorderRight = BorderStyle.Thin; cellStyle.ColumnHeaderStyle.BorderBottom = BorderStyle.Thin; cellStyle.ColumnHeaderStyle.WrapText = true; IFont headerFont = wb.CreateFont(); headerFont.IsBold = true; headerFont.FontName = cellStyle.TitleFontName; headerFont.FontHeightInPoints = fontSize; cellStyle.ColumnHeaderStyle.SetFont(headerFont); // 带背景列头样式 cellStyle.ColumnFillHeaderStyle.CloneStyleFrom(cellStyle.ColumnHeaderStyle); if (wb.SpreadsheetVersion.DefaultExtension == "xls") { HSSFPalette palette = ((HSSFWorkbook)wb).GetCustomPalette(); palette.SetColorAtIndex(48, 237, 237, 237); cellStyle.ColumnFillHeaderStyle.FillForegroundColor = palette.FindColor(237, 237, 237).Indexed; } else { cellStyle.ColumnFillHeaderStyle.FillForegroundColor = 0; cellStyle.ColumnFillHeaderStyle.FillPattern = FillPattern.SolidForeground; ((XSSFColor)cellStyle.ColumnFillHeaderStyle.FillForegroundColorColor).SetRgb(new byte[] { 237, 237, 237 }); } // 默认居中样式 cellStyle.CenterCellStyle.Alignment = HorizontalAlignment.Center; cellStyle.CenterCellStyle.VerticalAlignment = VerticalAlignment.Center; cellStyle.CenterCellStyle.BorderTop = BorderStyle.Thin; cellStyle.CenterCellStyle.BorderLeft = BorderStyle.Thin; cellStyle.CenterCellStyle.BorderRight = BorderStyle.Thin; cellStyle.CenterCellStyle.BorderBottom = BorderStyle.Thin; cellStyle.CenterCellStyle.WrapText = true; IFont cellFont = wb.CreateFont(); cellFont.FontName = cellStyle.FontName; cellFont.FontHeightInPoints = fontSize; cellStyle.CenterCellStyle.SetFont(cellFont); // 居左样式 cellStyle.LeftCellStyle.CloneStyleFrom(cellStyle.CenterCellStyle); cellStyle.LeftCellStyle.Alignment = HorizontalAlignment.Left; // 居右样式 cellStyle.RightCellStyle.CloneStyleFrom(cellStyle.CenterCellStyle); cellStyle.RightCellStyle.Alignment = HorizontalAlignment.Right; // 背景样式 cellStyle.FillCellStyle.CloneStyleFrom(cellStyle.CenterCellStyle); if (wb.SpreadsheetVersion.DefaultExtension == "xls") { HSSFPalette palette = ((HSSFWorkbook)wb).GetCustomPalette(); palette.SetColorAtIndex(48, 245, 245, 245); cellStyle.FillCellStyle.FillForegroundColor = palette.FindColor(245, 245, 245).Indexed; } else { cellStyle.FillCellStyle.FillForegroundColor = 0; cellStyle.FillCellStyle.FillPattern = FillPattern.SolidForeground; ((XSSFColor)cellStyle.FillCellStyle.FillForegroundColorColor).SetRgb(new byte[] { 245, 245, 245 }); } cellStyle.PercentCellStyleP2.CloneStyleFrom(cellStyle.CenterCellStyle); cellStyle.PercentCellStyleP2.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00%"); cellStyle.NumberCellStyleP2.CloneStyleFrom(cellStyle.CenterCellStyle); cellStyle.NumberCellStyleP2.DataFormat = dataformat.GetFormat("0.00"); cellStyle.NumberCellStyleP4.CloneStyleFrom(cellStyle.CenterCellStyle); cellStyle.NumberCellStyleP4.DataFormat = dataformat.GetFormat("0.0000"); return cellStyle; } /// /// 添加单元格 /// /// /// /// /// /// /// /// 0转为空白 /// public ICell AddCell(object value, IRow row, int columnIndex, ICellStyle cellStyle, ISheet sheet = null, int? width = null, bool? zeroToBlank = false, CellType? cellType = null) { bool isSetBlank = false; if (zeroToBlank == true) { if (double.TryParse(value.ToString(), out double v)) { isSetBlank = v == 0; } } ICell cell = row.CreateCell(columnIndex); cell.CellStyle = cellStyle; if (value != null && isSetBlank == false) { var valueTypeName = value.GetType().Name; if (cellType.HasValue) { cell.SetCellType(cellType.Value); } if (cellType.HasValue && cellType == CellType.Formula) { cell.CellFormula = value.ToString(); } else if (valueTypeName.Contains("Int") || valueTypeName == "Double" || valueTypeName == "Decimal") { cell.SetCellValue(Convert.ToDouble(value)); } else if (valueTypeName == "String") { cell.SetCellValue(value.ToString()); } else if (valueTypeName == "Boolean") { cell.SetCellValue((bool)value); } } if (sheet != null && width.HasValue) { sheet.SetColumnWidth(columnIndex, width.Value * 256); } return cell; } #endregion }