using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Data; using System.IO; using System.Linq; using NPOI.HSSF.UserModel; using NPOI.HSSF.Util; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; namespace WalkingTec.Mvvm.Core { public class BaseTemplateVM : BaseVM { #region 属性 /// /// 下载模板显示名称 /// public string FileDisplayName { get; set; } /// /// 是否验证模板类型(当其他系统模板导入到某模块时可设置为False) /// public bool ValidityTemplateType { get; set; } /// /// 需要导出的数据 /// public DataTable TemplateDataTable { get; set; } /// /// 下载模版页面参数 /// public Dictionary Parms { get; set; } /// /// Excel索引 /// public long ExcelIndex { get; set; } #endregion #region 构造函数 public BaseTemplateVM() { ValidityTemplateType = true; Parms = new Dictionary(); var propetys = this.GetType().GetFields().Where(x => x.FieldType == typeof(ExcelPropety)).ToList(); for (int porpetyIndex = 0; porpetyIndex < propetys.Count(); porpetyIndex++) { ExcelPropety excelPropety = (ExcelPropety)propetys[porpetyIndex].GetValue(this); if (propetys[porpetyIndex].GetCustomAttributes(typeof(DisplayAttribute), false).Length == 0) { excelPropety.ColumnName = excelPropety.FieldDisplayName; } else { excelPropety.ColumnName = propetys[porpetyIndex].GetPropertyDisplayName(); } } } #endregion #region 初始化Excel属性数据 /// /// 初始化Excel属性数据 包括动态列,列表中的下拉选项 /// public virtual void InitExcelData() { } public virtual void InitCustomFormat() { } #endregion #region 初始化模版数据 /// /// 初始化模版数据 /// public virtual void SetTemplateDataValus() { } #endregion #region 生成模板 /// /// 生成模板 /// /// 文件名 /// 生成的模版文件 public byte[] GenerateTemplate(out string displayName) { //设置导出的文件名称 string SheetName = !string.IsNullOrEmpty(FileDisplayName) ? FileDisplayName : this.GetType().Name; displayName = SheetName + "_" + DateTime.Now.ToString("yyyy-MM-dd") + "_" + DateTime.Now.ToString("hh^mm^ss") + ".xlsx"; //1.声明Excel文档 IWorkbook workbook = new XSSFWorkbook(); //加载初始化数据和下拉菜单数据,可重载 InitExcelData(); //设置TemplateDataTable的各列的类型 CreateDataTable(); //设置初始化数据到DataTable中 SetTemplateDataValus(); //2.设置workbook的sheet页 ISheet sheet = workbook.CreateSheet(); workbook.SetSheetName(0, SheetName); //3.设置Sheet页的Row IRow row = sheet.CreateRow(0); row.HeightInPoints = 20; ISheet enumSheet = workbook.CreateSheet(); IRow enumSheetRow1 = enumSheet.CreateRow(0); enumSheetRow1.CreateCell(0).SetCellValue(CoreProgram._localizer?["Sys.Yes"]); enumSheetRow1.CreateCell(1).SetCellValue(CoreProgram._localizer?["Sys.No"]); enumSheetRow1.CreateCell(2).SetCellValue(this.GetType().Name); //为模板添加标记,必要时可添加版本号 ISheet dataSheet = workbook.CreateSheet(); #region 设置excel模板列头 //默认灰色 var headerStyle = GetCellStyle(workbook); headerStyle.IsLocked = true; //黄色 var yellowStyle = GetCellStyle(workbook, BackgroudColorEnum.Yellow); yellowStyle.IsLocked = true; //红色 var redStyle = GetCellStyle(workbook, BackgroudColorEnum.Red); redStyle.IsLocked = true; //取得所有ExcelPropety var propetys = this.GetType().GetFields().Where(x => x.FieldType == typeof(ExcelPropety)).ToList(); //设置列的索引 int _currentColunmIndex = 0; //设置Excel是否需要保护,默认不保护 bool IsProtect = false; //循环类的属性,赋值给列 for (int porpetyIndex = 0; porpetyIndex < propetys.Count(); porpetyIndex++) { //依次获取属性字段 ExcelPropety excelPropety = (ExcelPropety)propetys[porpetyIndex].GetValue(this); ColumnDataType dateType = (excelPropety.DataType == ColumnDataType.DateTime || excelPropety.DataType == ColumnDataType.Date) ? ColumnDataType.Text : excelPropety.DataType; //日期类型默认设置成Text类型,在赋值时会进行日期验证 //设置是否保护Excel if (excelPropety.ReadOnly) { IsProtect = true; } //给必填项加星号 string colName = excelPropety.IsNullAble ? excelPropety.ColumnName : excelPropety.ColumnName + "*"; row.CreateCell(_currentColunmIndex).SetCellValue(colName); //修改列头样式 switch (excelPropety.BackgroudColor) { case BackgroudColorEnum.Yellow: row.Cells[_currentColunmIndex].CellStyle = yellowStyle; break; case BackgroudColorEnum.Red: row.Cells[_currentColunmIndex].CellStyle = redStyle; break; default: row.Cells[_currentColunmIndex].CellStyle = headerStyle; break; } var dataStyle = workbook.CreateCellStyle(); var dataFormat = workbook.CreateDataFormat(); if (dateType == ColumnDataType.Dynamic) { int dynamicColCount = excelPropety.DynamicColumns.Count(); for (int dynamicColIndex = 0; dynamicColIndex < dynamicColCount; dynamicColIndex++) { var dynamicCol = excelPropety.DynamicColumns.ToList()[dynamicColIndex]; string dynamicColName = excelPropety.IsNullAble ? dynamicCol.ColumnName : dynamicCol.ColumnName + "*"; row.CreateCell(_currentColunmIndex).SetCellValue(dynamicColName); row.Cells[_currentColunmIndex].CellStyle = headerStyle; if (dynamicCol.ReadOnly) { IsProtect = true; } //设定列宽 if (excelPropety.CharCount > 0) { sheet.SetColumnWidth(_currentColunmIndex, excelPropety.CharCount * 256); dataStyle.WrapText = true; } else { sheet.AutoSizeColumn(_currentColunmIndex); } //设置单元格样式及数据类型 dataStyle.IsLocked = excelPropety.ReadOnly; dynamicCol.SetColumnFormat(dynamicCol.DataType, _currentColunmIndex, sheet, dataSheet, dataStyle, dataFormat); _currentColunmIndex++; } } else { //设定列宽 if (excelPropety.CharCount > 0) { sheet.SetColumnWidth(_currentColunmIndex, excelPropety.CharCount * 256); dataStyle.WrapText = true; } else { sheet.AutoSizeColumn(_currentColunmIndex); } //设置是否锁定 dataStyle.IsLocked = excelPropety.ReadOnly; //设置单元格样式及数据类型 excelPropety.SetColumnFormat(dateType, _currentColunmIndex, sheet, dataSheet, dataStyle, dataFormat); _currentColunmIndex++; } } #endregion #region 添加模版数据 if (TemplateDataTable.Rows.Count > 0) { for (int i = 0; i < TemplateDataTable.Rows.Count; i++) { DataRow tableRow = TemplateDataTable.Rows[i]; IRow dataRow = sheet.CreateRow(1 + i); for (int porpetyIndex = 0; porpetyIndex < propetys.Count(); porpetyIndex++) { string colName = propetys[porpetyIndex].Name; tableRow[colName].ToString(); dataRow.CreateCell(porpetyIndex).SetCellValue(tableRow[colName].ToString()); } } } #endregion //冻结行 sheet.CreateFreezePane(0, 1, 0, 1); //锁定excel if (IsProtect) { sheet.ProtectSheet("password"); } //隐藏前2个Sheet workbook.SetSheetHidden(1, SheetState.Hidden); workbook.SetSheetHidden(2, SheetState.Hidden); //返回byte数组 MemoryStream ms = new MemoryStream(); workbook.Write(ms); return ms.ToArray(); } #endregion #region 取得表头的样式 private static ICellStyle GetCellStyle(IWorkbook workbook, BackgroudColorEnum backgroudColor = BackgroudColorEnum.Grey) { var headerStyle = workbook.CreateCellStyle(); //设定表头样式 headerStyle.BorderBottom = BorderStyle.Thin; headerStyle.BorderLeft = BorderStyle.Thin; headerStyle.BorderRight = BorderStyle.Thin; headerStyle.BorderTop = BorderStyle.Thin; //用灰色填充背景 short headerbg; switch (backgroudColor) { case BackgroudColorEnum.Grey: headerbg = HSSFColor.LightBlue.Index; break; case BackgroudColorEnum.Yellow: headerbg = HSSFColor.LightYellow.Index; break; case BackgroudColorEnum.Red: headerbg = HSSFColor.Pink.Index; break; default: headerbg = HSSFColor.Pink.Index; break; } headerStyle.FillForegroundColor = headerbg; headerStyle.FillPattern = FillPattern.SolidForeground; headerStyle.FillBackgroundColor = headerbg; headerStyle.Alignment = HorizontalAlignment.Center; return headerStyle; } #endregion #region 初始化DataTable(不含动态列) private void CreateDataTable() { TemplateDataTable = new DataTable(); var propetys = this.GetType().GetFields().Where(x => x.FieldType == typeof(ExcelPropety)).ToList(); foreach (var p in propetys) { ExcelPropety excelPropety = (ExcelPropety)p.GetValue(this); ColumnDataType dateType = excelPropety.DataType; switch (dateType) { case ColumnDataType.Bool: TemplateDataTable.Columns.Add(p.Name, typeof(bool)); break; case ColumnDataType.Date: TemplateDataTable.Columns.Add(p.Name, typeof(string)); break; case ColumnDataType.Number: TemplateDataTable.Columns.Add(p.Name, typeof(int)); break; case ColumnDataType.Text: TemplateDataTable.Columns.Add(p.Name, typeof(string)); break; case ColumnDataType.Float: TemplateDataTable.Columns.Add(p.Name, typeof(decimal)); break; default: TemplateDataTable.Columns.Add(p.Name, typeof(string)); break; } } } #endregion } }