using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using IwbZero.ToolCommon.LogHelpers; using NPOI.HSSF.UserModel; using NPOI.HSSF.Util; using NPOI.OpenXmlFormats.Spreadsheet; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; namespace IwbZero.ToolCommon.FileHelpers { public static class ExcelHelper { #region Excel导入 /// /// 从Excel取数据并记录到List集合里 /// /// 单元头的值和名称:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 保存文件绝对路径 /// 错误信息 /// 数据行开始序列,默认为1(即第二列,从0开始) /// 转换后的List对象集合 public static List ExcelToEntityList(this Dictionary cellHeader, string filePath, out string errMsg, int startIndex = 1) where T : new() { List enlist = new List(); var errorMsg = new StringBuilder(); try { if (Regex.IsMatch(filePath, ".xls$")) // 2003 { enlist = Excel2003ToEntityList(cellHeader, filePath, out errorMsg, startIndex); } else if (Regex.IsMatch(filePath, ".xlsx$")) // 2007 { enlist = Excel2007ToEntityList(cellHeader, filePath, out errorMsg, startIndex); } } catch (Exception ex) { errMsg = ex.Message; typeof(ExcelHelper).LogError(ex); return default(List); } errMsg = errorMsg.ToString(); return enlist; } /// /// 从Excel2003取数据并记录到List集合里 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 保存文件绝对路径 /// 错误信息 /// /// 转换好的List对象集合 private static List Excel2003ToEntityList(this Dictionary cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1) where T : new() { errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时,会有格式的错误信息 List enlist = new List(); // 转换后的集合 try { using (FileStream fs = File.OpenRead(filePath)) { HSSFWorkbook workbook = new HSSFWorkbook(fs); HSSFSheet sheet = (HSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页 for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++) { // 1.判断当前行是否空行,若空行就不在进行读取下一行操作,结束Excel读取操作 IRow row = sheet.GetRow(rowIndex); if (row == null) { break; } // 2.每一个Excel row转换为一个实体对象 T en = new T(); ExcelRowToEntity(cellHeader, row, rowIndex, en, ref errorMsg); enlist.Add(en); } } return enlist; } catch (Exception ex) { typeof(ExcelHelper).LogError(ex); return default(List); } } /// /// 从Excel2007取数据并记录到List集合里 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 保存文件绝对路径 /// 错误信息 /// 数据行开始序列,默认为1(即第二列,从0开始) /// 转换好的List对象集合 private static List Excel2007ToEntityList(this Dictionary cellHeader, string filePath, out StringBuilder errorMsg, int startIndex = 1) where T : new() { errorMsg = new StringBuilder(); // 错误信息,Excel转换到实体对象时,会有格式的错误信息 List enlist = new List(); // 转换后的集合 try { using (FileStream fs = File.OpenRead(filePath)) { XSSFWorkbook workbook = new XSSFWorkbook(fs); XSSFSheet sheet = (XSSFSheet)workbook.GetSheetAt(0); // 获取此文件第一个Sheet页 for (int rowIndex = startIndex; rowIndex <= sheet.LastRowNum; rowIndex++) { // 1.判断当前行是否空行,若空行就不在进行读取下一行操作,结束Excel读取操作 IRow row = sheet.GetRow(rowIndex); if (row == null) { break; } // 2.每一个Excel row转换为一个实体对象 T en = new T(); ExcelRowToEntity(cellHeader, row, rowIndex, en, ref errorMsg); enlist.Add(en); } } return enlist; } catch (Exception ex) { typeof(ExcelHelper).LogError(ex); return default(List); } } #endregion Excel导入 #region Excel导出 /// /// 实体类集合导出到EXCEL2003 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 数据源 /// 工作表名称 /// 文件的下载地址 /// public static string EntityListToExcel2003(this Dictionary cellHeader, IList enList, string sheetName, string filePath) { var lcRetVal = "error@"; try { string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xls"; // 文件名称 filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath); filePath = filePath.EndsWith("/") ? filePath : (filePath + "/"); string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); // 2.解析单元格头部,设置单元头的中文名称 HSSFWorkbook workbook = new HSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(sheetName); // 工作表 IRow row = sheet.CreateRow(0); List keys = cellHeader.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值 } // 3.List对象的值赋值到Excel的单元格里 int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头) object propertyValue = null; foreach (var en in enList) { IRow rowTmp = sheet.CreateRow(rowIndex); for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值 { string cellValue = ""; PropertyInfo propertyInfo = null; // 属性的信息 // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理) string subClassName = propertyArray[0]; // '.'前面的为子类的名称 string subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 3.1.2 获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3.1.3 根据属性名称获取子类里的属性类型 propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值 } } } else { // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性 propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(en, null); } } // 3.3 属性值经过转换赋值给单元格值 if (propertyValue != null) { if (propertyInfo?.PropertyType.Name == "int" || propertyInfo?.PropertyType.Name == "float" || propertyInfo?.PropertyType.Name == "double" || propertyInfo?.PropertyType.Name == "decimal") { var value = Convert.ToDouble(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo?.PropertyType.Name == "bool") { var value = Convert.ToBoolean(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } else { // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } rowIndex++; } // 4.生成文件 FileStream file = new FileStream($"{path}{fileName}", FileMode.Create); workbook.Write(file); file.Close(); lcRetVal = $"{filePath}{fileName}"; } catch (Exception ex) { lcRetVal += ex.Message; typeof(ExcelHelper).LogError(ex); } return lcRetVal; } public static string EntityListToExcel2003(this HSSFWorkbook workbook, string sheetName, string filePath) { var lcRetVal = "error@"; try { string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xls"; // 文件名称 filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath); filePath = filePath.EndsWith("/") ? filePath : (filePath + "/"); string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); FileStream file = new FileStream($"{path}{fileName}", FileMode.Create); workbook.Write(file); file.Close(); lcRetVal = $"{filePath}{fileName}"; } catch (Exception ex) { lcRetVal += ex.Message; typeof(ExcelHelper).LogError(ex); } return lcRetVal; } public static HSSFWorkbook EntityListToExcel2003Book(this Dictionary cellHeader, IList enList, string sheetName) { HSSFWorkbook workbook = new HSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(sheetName); // 工作表 IRow row = sheet.CreateRow(0); List keys = cellHeader.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值 } // 3.List对象的值赋值到Excel的单元格里 int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头) foreach (var en in enList) { IRow rowTmp = sheet.CreateRow(rowIndex); for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值 { string cellValue = ""; // 单元格的值 object propertyValue = null; // 属性的值 PropertyInfo propertyInfo; // 属性的信息 // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理) string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); string subClassName = propertyArray[0]; // '.'前面的为子类的名称 string subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 3.1.2 获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3.1.3 根据属性名称获取子类里的属性类型 propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值 } } } else { // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性 propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(en, null); } } // 3.3 属性值经过转换赋值给单元格值 if (propertyValue != null) { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } } // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } rowIndex++; } return workbook; } /// /// 实体类集合导出到EXCEL2007 /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// 数据源 /// 工作表名称 /// 文件的下载地址 /// public static string EntityListToExcel2007(this Dictionary cellHeader, IList enList, string sheetName, string filePath) { var lcRetVal = "error@"; try { string fileName = $"D-{sheetName}-{DateTime.Now:yyyyMMddHHmmssfff}.xlsx"; // 文件名称 filePath = filePath.StartsWith("/") ? filePath : ("/" + filePath); filePath = filePath.EndsWith("/") ? filePath : (filePath + "/"); string path = $"{AppDomain.CurrentDomain.BaseDirectory}{filePath}"; if (!Directory.Exists(path)) Directory.CreateDirectory(path); // 2.解析单元格头部,设置单元头的中文名称 XSSFWorkbook workbook = new XSSFWorkbook(); // 工作簿 ISheet sheet = workbook.CreateSheet(sheetName); // 工作表 IRow row = sheet.CreateRow(0); List keys = cellHeader.Keys.ToList(); for (int i = 0; i < keys.Count; i++) { row.CreateCell(i).SetCellValue(cellHeader[keys[i]]); // 列名为Key的值 } // 3.List对象的值赋值到Excel的单元格里 int rowIndex = 1; // 从第二行开始赋值(第一行已设置为单元头) foreach (var en in enList) { IRow rowTmp = sheet.CreateRow(rowIndex); for (int i = 0; i < keys.Count; i++) // 根据指定的属性名称,获取对象指定属性的值 { string cellValue = ""; // 单元格的值 object propertyValue = null; // 属性的值 PropertyInfo propertyInfo = null; // 属性的信息 // 3.1 若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.UserName if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 3.1.1 解析子类属性(这里只解析1层子类,多层子类未处理) string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); string subClassName = propertyArray[0]; // '.'前面的为子类的名称 var subClassPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 3.1.2 获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3.1.3 根据属性名称获取子类里的属性类型 propertyInfo = subClassInfo.PropertyType.GetProperty(subClassPropertyName); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(subClassEn, null); // 获取子类属性的值 } } } else { // 3.2 若不是子类的属性,直接根据属性名称获取对象对应的属性 propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { propertyValue = propertyInfo.GetValue(en, null); } } // 3.3 属性值经过转换赋值给单元格值 if (propertyValue != null) { if (propertyInfo.PropertyType.Name.ToLower() == "int" || propertyInfo.PropertyType.Name.ToLower() == "int16" || propertyInfo.PropertyType.Name.ToLower() == "int32" || propertyInfo.PropertyType.Name.ToLower() == "int64" || propertyInfo.PropertyType.Name.ToLower() == "double" || propertyInfo.PropertyType.Name.ToLower() == "decimal") { var value = Convert.ToDouble(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.Name.ToLower() == "bool") { var value = Convert.ToBoolean(propertyValue); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.Name.ToLower() == "nullable`1") { if (propertyInfo.PropertyType.FullName == null) { } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("datetime")) { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } rowTmp.CreateCell(i).SetCellValue(cellValue); } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("int")) { var value = (int)Convert.ChangeType(propertyValue, typeof(int)); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("float") || propertyInfo.PropertyType.FullName.ToLower().Contains("double") || propertyInfo.PropertyType.FullName.ToLower().Contains("decimal") || propertyInfo.PropertyType.FullName.ToLower().Contains("single")) { var value = (float)Convert.ChangeType(propertyValue, typeof(float)); rowTmp.CreateCell(i).SetCellValue(value); } else if (propertyInfo.PropertyType.FullName.ToLower().Contains("bool")) { var value = (bool)Convert.ChangeType(propertyValue, typeof(bool)); rowTmp.CreateCell(i).SetCellValue(value); } } else { cellValue = propertyValue.ToString(); // 3.3.1 对时间初始值赋值为空 if (cellValue.Trim() == "0001/1/1 0:00:00" || cellValue.Trim() == "0001/1/1 23:59:59") { cellValue = ""; } // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } else { // 3.4 填充到Excel的单元格里 rowTmp.CreateCell(i).SetCellValue(cellValue); } } rowIndex++; } // 4.生成文件 FileStream file = new FileStream($"{path}{fileName}", FileMode.Create); workbook.Write(file); file.Close(); lcRetVal = $"{filePath}{fileName}"; } catch (Exception ex) { lcRetVal += ex.Message; typeof(ExcelHelper).LogError(ex); } return lcRetVal; } #endregion Excel导出 #region Common /// /// Excel row转换为实体对象 /// /// /// 单元头的Key和Value:{ { "UserName", "姓名" }, { "Age", "年龄" } }; /// Excel row /// row index /// 实体 /// 错误信息 private static void ExcelRowToEntity(Dictionary cellHeader, IRow row, int rowIndex, T en, ref StringBuilder errorMsg) { List keys = cellHeader.Keys.ToList(); // 要赋值的实体对象属性名称 string errStr = ""; // 当前行转换时,是否有错误信息,格式为:第1行数据转换异常:XXX列; for (int i = 0; i < keys.Count; i++) { // 1.若属性头的名称包含'.',就表示是子类里的属性,那么就要遍历子类,eg:UserEn.TrueName if (keys[i].IndexOf(".", StringComparison.Ordinal) >= 0) { // 1)解析子类属性 string[] propertyArray = keys[i].Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries); string subClassName = propertyArray[0]; // '.'前面的为子类的名称 string classPropertyName = propertyArray[1]; // '.'后面的为子类的属性名称 PropertyInfo subClassInfo = en.GetType().GetProperty(subClassName); // 获取子类的类型 if (subClassInfo != null) { // 2)获取子类的实例 var subClassEn = en.GetType().GetProperty(subClassName)?.GetValue(en, null); // 3)根据属性名称获取子类里的属性信息 PropertyInfo propertyInfo = subClassInfo.PropertyType.GetProperty(classPropertyName); if (propertyInfo != null) { try { // Excel单元格的值转换为对象属性的值,若类型不对,记录出错信息 propertyInfo.SetValue(subClassEn, GetExcelCellToProperty(propertyInfo.PropertyType, row.GetCell(i)), null); } catch (Exception e) { typeof(ExcelHelper).LogError(e); if (errStr.Length == 0) { errStr = "第" + rowIndex + "行数据转换异常:"; } errStr += cellHeader[keys[i]] + "列;"; } } } } else { // 2.给指定的属性赋值 PropertyInfo propertyInfo = en.GetType().GetProperty(keys[i]); if (propertyInfo != null) { try { // Excel单元格的值转换为对象属性的值,若类型不对,记录出错信息 propertyInfo.SetValue(en, GetExcelCellToProperty(propertyInfo.PropertyType, row.GetCell(i)), null); } catch (Exception e) { typeof(ExcelHelper).LogError(e); if (errStr.Length == 0) { errStr = "第" + rowIndex + "行数据转换异常:"; } errStr += cellHeader[keys[i]] + "列;"; } } } } // 若有错误信息,就添加到错误信息里 if (errStr.Length > 0) { errorMsg.AppendLine(errStr); } } /// /// Excel Cell转换为实体的属性值 /// /// 目标对象类型 /// 对象属性的值 private static object GetExcelCellToProperty(Type distanceType, ICell sourceCell) { object rs = distanceType.IsValueType ? Activator.CreateInstance(distanceType) : null; // 1.判断传递的单元格是否为空 if (sourceCell == null || string.IsNullOrEmpty(sourceCell.ToString())) { return rs; } // 2.Excel文本和数字单元格转换,在Excel里文本和数字是不能进行转换,所以这里预先存值 object sourceValue = null; switch (sourceCell.CellType) { case CellType.Blank: break; case CellType.Boolean: sourceValue = sourceCell.BooleanCellValue; break; case CellType.Error: break; case CellType.Formula: break; case CellType.Numeric: sourceValue = sourceCell.NumericCellValue; break; case CellType.String: sourceValue = sourceCell.StringCellValue; break; case CellType.Unknown: break; default: sourceValue = sourceCell.StringCellValue; break; } string valueDataType = distanceType.Name; // 在这里进行特定类型的处理 switch (valueDataType.ToLower()) // 以防出错,全部小写 { case "string": rs = sourceValue?.ToString(); break; case "int": case "int32": rs = (int)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "int16": rs = (short)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "int64": rs = (long)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "float": case "single": rs = (float)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "double": rs = (double)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "decimal": rs = (decimal)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "datetime": rs = (DateTime)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "guid": rs = (Guid)Convert.ChangeType(sourceValue?.ToString() ?? "", distanceType); break; case "nullable`1": if (distanceType.FullName == null) { rs = ""; } else if (distanceType.FullName.ToLower().Contains("datetime")) { rs = (DateTime)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(DateTime)); } else if ((bool)distanceType.FullName?.ToLower().Contains("int")) { rs = (int)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(int)); } else if ((bool)distanceType.FullName?.ToLower().Contains("float") || (bool)distanceType.FullName?.ToLower().Contains("double") || (bool)distanceType.FullName?.ToLower().Contains("decimal") || (bool)distanceType.FullName?.ToLower().Contains("single")) { rs = (float)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(float)); } else if ((bool)distanceType.FullName?.ToLower().Contains("bool")) { rs = (bool)Convert.ChangeType(sourceValue?.ToString() ?? "", typeof(bool)); } break; } return rs; } #endregion Common public static IWorkbook CreateWorkBook(string filePath = "") { return filePath.ToLower().EndsWith(".xlsx") ? CreateWorkBook07(filePath) : filePath.ToLower().EndsWith(".xls") ? (IWorkbook)CreateWorkBook03(filePath) : new XSSFWorkbook(); } public static HSSFWorkbook CreateWorkBook03(string filePath = null) { if (string.IsNullOrEmpty(filePath)) { return new HSSFWorkbook(); } FileStream file = new FileStream(filePath, FileMode.Open); return new HSSFWorkbook(file); } public static XSSFWorkbook CreateWorkBook07(string filePath = null) { if (string.IsNullOrEmpty(filePath)) { return new XSSFWorkbook(); } return new XSSFWorkbook(filePath); } /// /// 创建Sheet /// /// /// /// /// /// /// public static ISheet GenerateSheet(this string sheetName, int defaultWidth = 20, int defaultHeight = 20, bool is07 = true, IWorkbook workbook = null) { workbook = is07 ? workbook ?? CreateWorkBook07() : workbook ?? CreateWorkBook03(); var sheet = workbook.CreateSheet(sheetName); sheet.DefaultColumnWidth = defaultWidth; sheet.DefaultRowHeight = (short)(defaultHeight * 20); return sheet; } /// /// 创建行 /// /// 表 /// 第几行(从1开始计数) /// public static IRow GenerateRow(this ISheet sheet, int rowIndex) { rowIndex = rowIndex <= 0 ? 1 : rowIndex; var row = sheet.GetRow(rowIndex - 1) ?? sheet.CreateRow(rowIndex - 1); return row; } /// /// 插入行 /// /// 表 /// 第几行后开始插入(源行) /// 插入的行数 /// public static void InsertRows(this ISheet sheet, int startRow, int count) { var rowSource = sheet.GenerateRow(startRow); sheet.ShiftRows(startRow, sheet.LastRowNum, count, true, false); if (rowSource == null) return; var rowStyle = rowSource.RowStyle; for (int i = startRow + 1; i <= startRow + count; i++) { var rowInsert = sheet.GenerateRow(i); rowInsert.RowStyle = rowStyle; rowInsert.Height = rowSource.Height; for (int col = 1; col <= rowSource.LastCellNum; col++) { var cellSource = rowSource.GenerateCell(col); var cellInsert = rowInsert.GenerateCell(col); var cellStyle = cellSource.CellStyle; //设置单元格样式     if (cellStyle != null) cellInsert.CellStyle = cellSource.CellStyle; } } } /// /// 创建单元格 /// /// 表 /// 第几行(从1开始计数) /// 第几列(从1开始计数) /// 值 /// 单元格类型 /// public static ICell GenerateCell(this ISheet sheet, int rowIndex, int columnIndex, string val = null, CellType cellType = CellType.String) { var row = sheet.GenerateRow(rowIndex); var cell = GenerateCell(row, columnIndex, val, cellType); return cell; } /// /// 创建单元格 /// /// 行 /// 第几列(从1开始计数) /// 值 /// 单元格类型 /// public static ICell GenerateCell(this IRow row, int columnIndex, string val = null, CellType cellType = CellType.String) { columnIndex = columnIndex <= 0 ? 1 : columnIndex; var cell = row.GetCell(columnIndex - 1) ?? row.CreateCell(columnIndex - 1); if (!string.IsNullOrEmpty(val)) { cell.SetCellValue(val); cell.SetCellType(cellType); } return cell; } /// /// 设置列宽度 /// /// 表 /// 第几列(从1开始计数) /// 宽度 /// public static ISheet SetCellWidth(this ISheet sheet, int columnIndex, int width) { sheet.SetColumnWidth(columnIndex - 1, width * 256); return sheet; } /// /// 设置列宽度 /// /// 行 /// 第几列(从1开始计数) /// 宽度 /// public static IRow SetCellWidth(this IRow row, int columnIndex, int width) { row.Sheet.SetColumnWidth(columnIndex - 1, width * 256); return row; } /// /// 设置列宽度 /// /// 单元格 /// 第几列(从1开始计数) /// 宽度 /// public static ICell SetCellWidth(this ICell cell, int columnIndex, int width) { cell.Sheet.SetColumnWidth(columnIndex - 1, width * 256); return cell; } /// /// 设置行高度 /// /// 表 /// 第几行(从1开始计数) /// 宽度 /// public static ISheet SetRowHeight(this ISheet sheet, int rowIndex, int height) { sheet.GetRow(rowIndex - 1).SetRowHeight(height); return sheet; } /// /// 设置行高度 /// /// 行 /// 宽度 /// public static IRow SetRowHeight(this IRow row, int height) { row.Height = (short)(height * 20); return row; } /// /// 设置行高度 /// /// 单元格 /// 宽度 /// public static ICell SetRowHeight(this ICell cell, int height) { cell.Row.SetRowHeight(height); return cell; } /// /// 设置单元格样式 /// /// /// 样式字符串 /// 样式转换器 /// public static ICell SetCellCss(this ICell cell, CellStyleCss instants = null, string styleStr = null) { instants = instants ?? CellStyleCss.Instants; return instants.Css(cell, styleStr); } /// /// 设置单元格的值 /// /// /// /// public static ICell SetValue(this ICell cell, string obj) { return SetValue(cell, obj); } /// /// 设置单元格的值 /// /// 值类型(sting,bool,double,DateTime) /// /// /// public static ICell SetValue(this ICell cell, object obj) { if (obj == null) { return cell; } Type type = typeof(T); if (type == typeof(string)) { cell.SetCellValue(obj.ToString()); } else if (type == typeof(bool) && bool.TryParse(obj.ToString(), out var bValue)) { cell.SetCellValue(bValue); } else if ((type == typeof(int) || type == typeof(double) || type == typeof(decimal)) && double.TryParse(obj.ToString(), out var iValue)) { cell.SetCellValue(iValue); } else if (type == typeof(DateTime) && DateTime.TryParse(obj.ToString(), out var dValue)) { cell.SetCellValue(dValue); } return cell; } #region 设置下拉框 public static void SetCellDropdownList03(this ISheet sheet, ICell cell, string[] val, string str = "", int startRow=1, string title = "提示") { //设置生成下拉框的行和列 SetCellDropdownList03(sheet, cell.ColumnIndex+1, cell.ColumnIndex+1, val, str, startRow,title); } public static void SetCellDropdownList03(this ISheet sheet, int firstCol, int lastCol, string[] val, string str = "", int startRow = 1, string title = "提示") { //设置生成下拉框的行和列 var cellRegions = new CellRangeAddressList(startRow, 65535, firstCol-1, lastCol-1); //设置 下拉框内容 DVConstraint constraint = DVConstraint.CreateExplicitListConstraint(val); //绑定下拉框和作用区域,并设置错误提示信息 HSSFDataValidation dataValidate = new HSSFDataValidation(cellRegions, constraint); dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); dataValidate.ShowPromptBox = true; if (!string.IsNullOrEmpty(str)) { dataValidate.CreatePromptBox(title, str); } sheet.AddValidationData(dataValidate); } public static void SetCellDropdownList07(this ISheet sheet, ICell cell, string[] val, string str = "", int startRow = 1, string title = "提示") { //设置生成下拉框的行和列 SetCellDropdownList07(sheet, cell.ColumnIndex+1, cell.ColumnIndex+1, val, str,startRow,title); } public static void SetCellDropdownList07(this ISheet sheet, int firstCol, int lastCol, string[] val,string str="", int startRow = 1, string title = "提示") { //设置生成下拉框的行和列 var cellRegions = new CellRangeAddressList(startRow, 65535, firstCol-1, lastCol-1); XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet); //设置 下拉框内容 XSSFDataValidationConstraint constraint = (XSSFDataValidationConstraint)dvHelper.CreateExplicitListConstraint(val); //绑定下拉框和作用区域,并设置错误提示信息 XSSFDataValidation dataValidate = (XSSFDataValidation)dvHelper.CreateValidation(constraint, cellRegions); dataValidate.ShowErrorBox = true; dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); if (!string.IsNullOrEmpty(str)) { dataValidate.CreatePromptBox(title,str); } dataValidate.ShowPromptBox = true; sheet.AddValidationData(dataValidate); } public static void SetCellDropdownList03(this ISheet sheet, HSSFWorkbook workbook, ICell cell, string[] val, string str = "", int startRow = 1, string title = "提示") { //设置生成下拉框的行和列 SetCellDropdownList03(sheet, workbook, cell.ColumnIndex+1, cell.ColumnIndex+1, val, str, startRow,title); } public static void SetCellDropdownList03(this ISheet sheet, HSSFWorkbook workbook, int firstCol, int lastCol, string[] val, string str = "", int startRow = 1, string title = "提示") { //先创建一个Sheet专门用于存储下拉项的值 var name = $"Dropdown{DateTime.Now:HHmmssffff}List"; ISheet sheet2 = workbook.CreateSheet(name); //隐藏 workbook.SetSheetHidden(workbook.GetSheetIndex(name), true); int index = 0; foreach (var item in val) { sheet2.CreateRow(index).CreateCell(0).SetCellValue(item); index++; } //创建的下拉项的区域: var rangeName = name + "Range"; IName range = workbook.CreateName(); range.RefersToFormula = name + "!$A$1:$A$" + index; range.NameName = rangeName; CellRangeAddressList regions = new CellRangeAddressList(startRow, 65535, firstCol-1, lastCol-1); DVConstraint constraint = DVConstraint.CreateFormulaListConstraint(rangeName); HSSFDataValidation dataValidate = new HSSFDataValidation(regions, constraint); dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); dataValidate.ShowPromptBox = true; if (!string.IsNullOrEmpty(str)) { dataValidate.CreatePromptBox(title, str); } sheet.AddValidationData(dataValidate); } public static void SetCellDropdownList07(this ISheet sheet, XSSFWorkbook workbook, ICell cell, string[] val, string str = "", int startRow = 1, string title = "提示") { //设置生成下拉框的行和列 SetCellDropdownList07(sheet, workbook, cell.ColumnIndex+1, cell.ColumnIndex+1, val, str,startRow,title); } public static void SetCellDropdownList07(this ISheet sheet, XSSFWorkbook workbook, int firstCol, int lastCol, string[] val, string str = "", int startRow = 1, string title = "提示") { //先创建一个Sheet专门用于存储下拉项的值 var name = $"Dropdown{DateTime.Now:HHmmssffff}List"; ISheet sheet2 = workbook.CreateSheet(name); //隐藏 workbook.SetSheetHidden(workbook.GetSheetIndex(name), true); int index = 0; foreach (var item in val) { sheet2.CreateRow(index).CreateCell(0).SetCellValue(item); index++; } //创建的下拉项的区域: var rangeName = name + "Range"; IName range = workbook.CreateName(); range.RefersToFormula = $"'{name}'!$A$1:$A${index}"; range.NameName = rangeName; CellRangeAddressList addressList = new CellRangeAddressList(startRow, 65535, firstCol-1, lastCol-1); var dvHelper= sheet.GetDataValidationHelper(); //设置 下拉框内容 var constraint = (XSSFDataValidationConstraint)dvHelper.CreateFormulaListConstraint(rangeName); XSSFDataValidation dataValidate = (XSSFDataValidation)dvHelper.CreateValidation( constraint, addressList); dataValidate.ShowErrorBox = true; dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); if (!string.IsNullOrEmpty(str)) { dataValidate.CreatePromptBox(title, str); } dataValidate.ShowPromptBox = true; sheet.AddValidationData(dataValidate); } public static void BuildListData(this ISheet dataSheet, DropdownListData listData,ref int rowIndex) { int columnIndex=0; var row = dataSheet.CreateRow(rowIndex); var rowIndex2 = rowIndex + 1; foreach (var l in listData.Children) { var cell = row.CreateCell(columnIndex); cell.SetCellValue(l.Value); columnIndex++; if (l.Children.Count > 0) { rowIndex++; BuildListData(dataSheet, l, ref rowIndex); } } if (columnIndex > 0) { IName name = dataSheet.Workbook.CreateName(); name.RefersToFormula = $"'{dataSheet.SheetName}'!$A${rowIndex2}:${ConvertColumnName(columnIndex-1)}${rowIndex2}"; name.NameName = listData.Name; } } public static string ConvertColumnName(this int index) { char[] chars = "ABCDEFGHIGKLMNOPQRSTUVWXYZ".ToCharArray(); var last = index % 25; var lastStr = chars[last] + ""; var first = index / 25; string str = (first > 26 ? ConvertColumnName(first) : first > 0 ? chars[first] + "" : "") + lastStr; return str; } public static IDataValidationConstraint CreateValidationConstraint(this ISheet sheet,string formula) { var dvHelper = sheet.GetDataValidationHelper(); var constraint = dvHelper.CreateFormulaListConstraint(formula); return constraint; } public static IDataValidationConstraint CreateLinkValidationConstraint(this ISheet sheet,string formula) { var dvHelper = sheet.GetDataValidationHelper(); var constraint = dvHelper.CreateFormulaListConstraint($"INDIRECT(UPPER({formula}))"); return constraint; } public static IDataValidationConstraint CreateLinkValidationConstraint(this ISheet sheet,ICell cell) { var dvHelper = sheet.GetDataValidationHelper(); var constraint = dvHelper.CreateFormulaListConstraint($"INDIRECT(UPPER(${ConvertColumnName(cell.ColumnIndex)}${cell.RowIndex+1}))"); return constraint; } public static void SetCellDropdownList07(this ISheet sheet, IDataValidationConstraint constraint, CellRangeAddress range, string str = "", string title = "提示") { var dvHelper= sheet.GetDataValidationHelper(); CellRangeAddressList addressList = new CellRangeAddressList(); addressList.AddCellRangeAddress(range); XSSFDataValidation dataValidate = (XSSFDataValidation)dvHelper.CreateValidation(constraint, addressList); dataValidate.ShowErrorBox = true; dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); if (!string.IsNullOrEmpty(str)) { dataValidate.CreatePromptBox(title, str); } dataValidate.ShowPromptBox = true; sheet.AddValidationData(dataValidate); } public static void SetCellDropdownList07(this ISheet sheet, IDataValidationConstraint constraint1, CellRangeAddress range1, IDataValidationConstraint constraint2, CellRangeAddress range2, string str1 = "",string str2 = "", string title1 = "提示", string title2 = "提示") { var dvHelper= sheet.GetDataValidationHelper(); CellRangeAddressList addressList = new CellRangeAddressList(); addressList.AddCellRangeAddress(range1); XSSFDataValidation dataValidate = (XSSFDataValidation)dvHelper.CreateValidation(constraint1, addressList); dataValidate.ShowErrorBox = true; dataValidate.ShowPromptBox = true; dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); if (!string.IsNullOrEmpty(str1)) { dataValidate.CreatePromptBox(title1, str1); } sheet.AddValidationData(dataValidate); addressList = new CellRangeAddressList(); addressList.AddCellRangeAddress(range2); dataValidate = (XSSFDataValidation)dvHelper.CreateValidation(constraint2, addressList); dataValidate.ShowErrorBox = true; dataValidate.ShowPromptBox = true; dataValidate.CreateErrorBox("输入不合法", "请输入或选择下拉列表中的值。"); if (!string.IsNullOrEmpty(str2)) { dataValidate.CreatePromptBox(title2, str2); } sheet.AddValidationData(dataValidate); } #endregion #region 列提示信息 public static void SetColumnMsg03(this ISheet sheet, string str, int firstCol, int lastCol, int startRow = 1) { var cellRegions = new CellRangeAddressList(startRow, 65535, firstCol - 1, lastCol - 1); DVConstraint constraint = DVConstraint.CreateCustomFormulaConstraint("A65535"); //绑定下拉框和作用区域,并设置提示信息 HSSFDataValidation dataValidate = new HSSFDataValidation(cellRegions, constraint); dataValidate.CreatePromptBox("提示", str); dataValidate.ShowPromptBox = true; sheet.AddValidationData(dataValidate); } public static void SetColumnMsg07(this ISheet sheet, string str, int firstCol, int lastCol, int startRow = 1, string title = "提示") { var cellRegions = new CellRangeAddressList(startRow, 65535, firstCol - 1, lastCol - 1); XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet); //var constraint =(XSSFDataValidationConstraint)dvHelper.CreateTextLengthConstraint((int)ST_DataValidationOperator.greaterThanOrEqual,"0",""); var constraint = new XSSFDataValidationConstraint(ValidationType.ANY, ""); //绑定下拉框和作用区域,并设置提示信息 XSSFDataValidation dataValidate = (XSSFDataValidation)dvHelper.CreateValidation(constraint, cellRegions); dataValidate.CreatePromptBox(title, str); dataValidate.ShowPromptBox = true; sheet.AddValidationData(dataValidate); } #endregion #region 批注 public static void SetCellPatriarch03(this ISheet sheet, ICell cell, string str) { IDrawing patriarch = (HSSFPatriarch)sheet.CreateDrawingPatriarch(); int row = cell.RowIndex, col = cell.ColumnIndex; HSSFComment comment = (HSSFComment)patriarch.CreateCellComment(new HSSFClientAnchor(0, 0, 0, 0, col + 1, row - 1, col + 3, row + 4)); comment.SetFillColor(204, 236, 255); comment.String = new HSSFRichTextString(str); cell.CellComment = comment; } public static void SetCellPatriarch07(this ISheet sheet, ICell cell, string str) { IDrawing patriarch = (XSSFDrawing)sheet.CreateDrawingPatriarch(); int row = cell.RowIndex, col = cell.ColumnIndex; XSSFComment comment = (XSSFComment)patriarch.CreateCellComment(new XSSFClientAnchor(0, 0, 0, 0, col + 1, row - 1, col + 2, row + 4)); comment.SetString(str); cell.CellComment = comment; } public static void SetColPatriarch07(this ISheet sheet, ICell cell, string str) { IDrawing patriarch = (XSSFDrawing)sheet.CreateDrawingPatriarch(); int row = cell.RowIndex, col = cell.ColumnIndex; XSSFComment comment = (XSSFComment)patriarch.CreateCellComment(new XSSFClientAnchor(0, 0, 0, 0, col + 1, row - 1, col + 2, row + 3)); comment.SetString(str); cell.CellComment = comment; } #endregion public static void SetCellMinNumeric07(this ISheet sheet, int firstCol,int minValue, string str = "", int startRow = 1, string title = "提示", int? lastCol = null) { lastCol = lastCol ?? firstCol; CellRangeAddressList regions = new CellRangeAddressList(startRow, 65535, firstCol - 1, (int)lastCol - 1); var dvHelper = sheet.GetDataValidationHelper(); //设置 下拉框内容 var constraint = (XSSFDataValidationConstraint)dvHelper.CreateNumericConstraint(ValidationType.DECIMAL,OperatorType.GREATER_OR_EQUAL, $"{minValue}", ""); XSSFDataValidation dataValidate = (XSSFDataValidation)dvHelper.CreateValidation(constraint, regions); dataValidate.ShowErrorBox = true; dataValidate.CreateErrorBox("输入不合法", "请输入大于0的数值。"); if (!string.IsNullOrEmpty(str)) { dataValidate.CreatePromptBox(title, str); } dataValidate.ShowPromptBox = true; sheet.AddValidationData(dataValidate); } #region DATA-FORMAT public static ICellStyle SetCellDateTime(this ICell cell, DateTime value, string formatStr = "yyyy-MM-dd HH:mm:ss") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellString(this ICell cell, double value, string formatStr = "@") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellDouble(this ICell cell, double value, string formatStr = "0.00") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellCurrency(this ICell cell, double value, string formatStr = "¥#,###.##") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static ICellStyle SetCellPercent(this ICell cell, double value, string formatStr = "0.00%") { cell.SetCellValue(value); cell.SetDataFormat(formatStr); return cell.CellStyle; } public static void SetDataFormat(this ICell cell, string formatStr = "¥#,##0.00") { var cellStyle = cell.CellStyle ?? GetCellStyle(cell); var format = cell.Sheet.Workbook.CreateDataFormat(); cellStyle.DataFormat = format.GetFormat(formatStr); cell.SetCellStyle(cellStyle); } #endregion DATA-FORMAT #region 合并单元格 /// /// 合并单元格 /// /// /// 开始行数(从1开始计数) /// 结束行数(从1开始计数) /// 开始列数(从1开始计数) /// 结束列数(从1开始计数) /// public static ISheet MergedRegion(this ISheet sheet, int firstRow, int lastRow, int firstColumn, int lastColumn) { var region = GetCellRegion(firstRow, lastRow, firstColumn, lastColumn); sheet.MergedRegion(region); return sheet; } public static ISheet MergedRegion(this ISheet sheet, CellRangeAddress region) { sheet.AddMergedRegion(region); //SetRegionBorder(sheet, region, borderTypeStr, borderColorStr); return sheet; } public static CellRangeAddress GetCellRegion(this int firstRow, int lastRow, int firstColumn, int lastColumn) { firstRow = firstRow <= 0 ? 1 : firstRow; firstColumn = firstColumn <= 0 ? 1 : firstColumn; lastRow = lastRow <= 0 ? 1 : lastRow; lastColumn = lastColumn <= 0 ? 1 : lastColumn; return new CellRangeAddress(firstRow - 1, lastRow - 1, firstColumn - 1, lastColumn - 1); } public static ISheet SetRegionBorder(this CellRangeAddress region, ISheet sheet, string borderTypeStr, string borderColorStr) { ICellStyle style = sheet.Workbook.CreateCellStyle(); borderTypeStr = borderTypeStr ?? "Thin"; borderColorStr = borderColorStr ?? "Black"; style.BorderColors(borderColorStr); style.BorderTypes(borderTypeStr); for (int i = region.FirstRow; i <= region.LastRow; i++) { IRow row = sheet.GenerateRow(i + 1); if (i == region.FirstRow) { } else if (i == region.LastRow) { } var leftCell = row.GenerateCell(region.FirstColumn + 1); leftCell.CellStyle.BorderLeft = style.BorderLeft; leftCell.CellStyle.LeftBorderColor = style.LeftBorderColor; var rightCell = row.GenerateCell(region.LastColumn + 1); rightCell.CellStyle.BorderRight = style.BorderRight; rightCell.CellStyle.RightBorderColor = style.RightBorderColor; //for (int j = region.FirstColumn; j <= region.LastColumn; j++) //{ // ICell singleCell = row.GenerateCell((short)j); //} } return sheet; } #endregion 合并单元格 public static ICellStyle GetCellStyle(this ICell cell) { return cell.CellStyle ?? cell.Sheet.Workbook.CreateCellStyle(); } public static void SetCellStyle(this ICell cell, ICellStyle cellStyle) { cell.CellStyle = cellStyle; } /// /// 保存工作簿 /// /// /// /// /// public static string SaveWorkBook(this ISheet sheet, string filePath, string fileName) { try { if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } filePath = filePath.EndsWith("\\") ? filePath : filePath + "\\"; FileStream file = new FileStream(filePath + fileName, FileMode.Create); sheet.Workbook.Write(file); file.Close(); return ""; } catch (Exception e) { return e.Message; } } /// /// 保存工作簿 /// /// /// /// /// public static string SaveWorkBook(this IWorkbook workbook, string filePath, string fileName) { try { if (!Directory.Exists(filePath)) { Directory.CreateDirectory(filePath); } filePath = filePath.EndsWith("\\") ? filePath : filePath + "\\"; FileStream file = new FileStream(filePath + fileName, FileMode.Create); workbook.Write(file); file.Close(); return ""; } catch (Exception e) { return e.Message; } } } public class DropdownListData { public DropdownListData() { Children = new List(); } public DropdownListData(string name):this() { Name = name; Value = name; } public DropdownListData(string name,string value):this(name) { Value = value; } public void AddList(DropdownListData data) { Children.Add(data); } public string Name { get; set; } public string Value { get; set; } public List Children { get; set; } } /// /// 表示单元格的维度,通常用于表达合并单元格的维度 /// public struct Dimension { /// /// 含有数据的单元格(通常表示合并单元格的第一个跨度行第一个跨度列),该字段可能为null /// public ICell DataCell; /// /// 行跨度(跨越了多少行) /// public int RowSpan; /// /// 列跨度(跨越了多少列) /// public int ColumnSpan; /// /// 合并单元格的起始行索引 /// public int FirstRowIndex; /// /// 合并单元格的结束行索引 /// public int LastRowIndex; /// /// 合并单元格的起始列索引 /// public int FirstColumnIndex; /// /// 合并单元格的结束列索引 /// public int LastColumnIndex; } public static class ExcelExtension { /// /// 判断指定行列所在的单元格是否为合并单元格,并且输出该单元格的维度 /// /// Excel工作表 /// 行索引,从0开始 /// 列索引,从0开始 /// 单元格维度 /// 返回是否为合并单元格的布尔(Boolean)值 public static bool IsMergeCell(this ISheet sheet, int rowIndex, int columnIndex, out Dimension dimension) { dimension = new Dimension { DataCell = null, RowSpan = 1, ColumnSpan = 1, FirstRowIndex = rowIndex, LastRowIndex = rowIndex, FirstColumnIndex = columnIndex, LastColumnIndex = columnIndex }; for (int i = 0; i < sheet.NumMergedRegions; i++) { CellRangeAddress range = sheet.GetMergedRegion(i); sheet.IsMergedRegion(range); //这种算法只有当指定行列索引刚好是合并单元格的第一个跨度行第一个跨度列时才能取得合并单元格的跨度 //if (range.FirstRow == rowIndex && range.FirstColumn == columnIndex) //{ // dimension.DataCell = sheet.GetRow(range.FirstRow).GetCell(range.FirstColumn); // dimension.RowSpan = range.LastRow - range.FirstRow + 1; // dimension.ColumnSpan = range.LastColumn - range.FirstColumn + 1; // dimension.FirstRowIndex = range.FirstRow; // dimension.LastRowIndex = range.LastRow; // dimension.FirstColumnIndex = range.FirstColumn; // dimension.LastColumnIndex = range.LastColumn; // break; //} if ((rowIndex >= range.FirstRow && range.LastRow >= rowIndex) && (columnIndex >= range.FirstColumn && range.LastColumn >= columnIndex)) { dimension.DataCell = sheet.GetRow(range.FirstRow).GetCell(range.FirstColumn); dimension.RowSpan = range.LastRow - range.FirstRow + 1; dimension.ColumnSpan = range.LastColumn - range.FirstColumn + 1; dimension.FirstRowIndex = range.FirstRow; dimension.LastRowIndex = range.LastRow; dimension.FirstColumnIndex = range.FirstColumn; dimension.LastColumnIndex = range.LastColumn; break; } } bool result; if (rowIndex >= 0 && sheet.LastRowNum > rowIndex) { IRow row = sheet.GetRow(rowIndex); if (columnIndex >= 0 && row.LastCellNum > columnIndex) { ICell cell = row.GetCell(columnIndex); result = cell.IsMergedCell; if (dimension.DataCell == null) { dimension.DataCell = cell; } } else { result = false; } } else { result = false; } return result; } /// /// 判断指定行列所在的单元格是否为合并单元格,并且输出该单元格的行列跨度 /// /// Excel工作表 /// 行索引,从0开始 /// 列索引,从0开始 /// 行跨度,返回值最小为1,同时表示没有行合并 /// 列跨度,返回值最小为1,同时表示没有列合并 /// 返回是否为合并单元格的布尔(Boolean)值 public static bool IsMergeCell(this ISheet sheet, int rowIndex, int columnIndex, out int rowSpan, out int columnSpan) { Dimension dimension; bool result = sheet.IsMergeCell(rowIndex, columnIndex, out dimension); rowSpan = dimension.RowSpan; columnSpan = dimension.ColumnSpan; return result; } /// /// 判断指定单元格是否为合并单元格,并且输出该单元格的维度 /// /// 单元格 /// 单元格维度 /// 返回是否为合并单元格的布尔(Boolean)值 public static bool IsMergeCell(this ICell cell, out Dimension dimension) { return cell.Sheet.IsMergeCell(cell.RowIndex, cell.ColumnIndex, out dimension); } /// /// 判断指定单元格是否为合并单元格,并且输出该单元格的行列跨度 /// /// 单元格 /// 行跨度,返回值最小为1,同时表示没有行合并 /// 列跨度,返回值最小为1,同时表示没有列合并 /// 返回是否为合并单元格的布尔(Boolean)值 public static bool IsMergeCell(this ICell cell, out int rowSpan, out int columnSpan) { return cell.Sheet.IsMergeCell(cell.RowIndex, cell.ColumnIndex, out rowSpan, out columnSpan); } /// /// 返回上一个跨度行,如果rowIndex为第一行,则返回null /// /// Excel工作表 /// 行索引,从0开始 /// 列索引,从0开始 /// 返回上一个跨度行 public static IRow PrevSpanRow(this ISheet sheet, int rowIndex, int columnIndex) { return sheet.FuncSheet(rowIndex, columnIndex, (currentDimension, isMerge) => { //上一个单元格维度 Dimension prevDimension; sheet.IsMergeCell(currentDimension.FirstRowIndex - 1, columnIndex, out prevDimension); return prevDimension.DataCell.Row; }); } /// /// 返回下一个跨度行,如果rowIndex为最后一行,则返回null /// /// Excel工作表 /// 行索引,从0开始 /// 列索引,从0开始 /// 返回下一个跨度行 public static IRow NextSpanRow(this ISheet sheet, int rowIndex, int columnIndex) { return sheet.FuncSheet(rowIndex, columnIndex, (currentDimension, isMerge) => isMerge ? sheet.GetRow(currentDimension.FirstRowIndex + currentDimension.RowSpan) : sheet.GetRow(rowIndex)); } /// /// 返回上一个跨度行,如果row为第一行,则返回null /// /// 行 /// 返回上一个跨度行 public static IRow PrevSpanRow(this IRow row) { return row.Sheet.PrevSpanRow(row.RowNum, row.FirstCellNum); } /// /// 返回下一个跨度行,如果row为最后一行,则返回null /// /// 行 /// 返回下一个跨度行 public static IRow NextSpanRow(this IRow row) { return row.Sheet.NextSpanRow(row.RowNum, row.FirstCellNum); } /// /// 返回上一个跨度列,如果columnIndex为第一列,则返回null /// /// 行 /// 列索引,从0开始 /// 返回上一个跨度列 public static ICell PrevSpanCell(this IRow row, int columnIndex) { return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) => { //上一个单元格维度 Dimension prevDimension; row.Sheet.IsMergeCell(row.RowNum, currentDimension.FirstColumnIndex - 1, out prevDimension); return prevDimension.DataCell; }); } /// /// 返回下一个跨度列,如果columnIndex为最后一列,则返回null /// /// 行 /// 列索引,从0开始 /// 返回下一个跨度列 public static ICell NextSpanCell(this IRow row, int columnIndex) { return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) => row.GetCell(currentDimension.FirstColumnIndex + currentDimension.ColumnSpan)); } /// /// 返回上一个跨度列,如果cell为第一列,则返回null /// /// 单元格 /// 返回上一个跨度列 public static ICell PrevSpanCell(this ICell cell) { return cell.Row.PrevSpanCell(cell.ColumnIndex); } /// /// 返回下一个跨度列,如果columnIndex为最后一列,则返回null /// /// 单元格 /// 返回下一个跨度列 public static ICell NextSpanCell(this ICell cell) { return cell.Row.NextSpanCell(cell.ColumnIndex); } /// /// 返回指定行索引所在的合并单元格(区域)中的第一行(通常是含有数据的行) /// /// Excel工作表 /// 行索引,从0开始 /// 返回指定列索引所在的合并单元格(区域)中的第一行 public static IRow GetDataRow(this ISheet sheet, int rowIndex) { return sheet.FuncSheet(rowIndex, 0, (currentDimension, isMerge) => sheet.GetRow(currentDimension.FirstRowIndex)); } /// /// 返回指定列索引所在的合并单元格(区域)中的第一行第一列(通常是含有数据的单元格) /// /// 行 /// 列索引 /// 返回指定列索引所在的合并单元格(区域)中的第一行第一列 public static ICell GetDataCell(this IRow row, int columnIndex) { return row.Sheet.FuncSheet(row.RowNum, columnIndex, (currentDimension, isMerge) => currentDimension.DataCell); } private static T FuncSheet(this ISheet sheet, int rowIndex, int columnIndex, Func func) { //当前单元格维度 Dimension currentDimension; //是否为合并单元格 bool isMerge = sheet.IsMergeCell(rowIndex, columnIndex, out currentDimension); return func(currentDimension, isMerge); } } public class CellStyleCss { public static CellStyleCss Instants => new CellStyleCss() { //缩写 DefaultStyle = $"bgc:{ColorType.White.ToString()};" + $"warp:{HorizontalAlignment.Left.ToString()};" + $"align:{HorizontalAlignment.Left.ToString()};" + $"v-align:{VerticalAlignment.Center.ToString()};" + //$"b:{BorderStyle.None.ToString()};" + //$"bc:{ColorType.Black.ToString()};" + "inden:0;" + "df:@;" }; public void SetDefaultStyle(string styleStr) { var dic = new SortedDictionary(); DefaultStyle = dic.GetCleanStyle(""); DefaultStyle = dic.GetCleanStyle(styleStr); } /// /// 默认样式css /// private string DefaultStyle { get; set; } //标准写法 //private static readonly string DefaultFontStyle = "font-color:black;" + // "font-name:Arial;" + // "font-size:10;" + // "font-weight:normal;" + // "font-underline:none;" + // "font-italic:false;" + // "font-strikeout:false;" + // "font-superscript:none;"+ // "background-color:white;"+ // "text-align:none;"+ // "vertical-align:none;"+ // "data-format:none;border-type:Thin"; /// /// 把css样式设置给单元格 /// /// /// /// public ICell Css(ICell cell, string styleStr = null) { var dic = new SortedDictionary(); var sortedCss = dic.GetCleanStyle(DefaultStyle); if (!string.IsNullOrEmpty(styleStr)) sortedCss = dic.GetCleanStyle(styleStr); var cssKey = $"CellStyle_{sortedCss.Md5()}"; var workbook = cell.Sheet.Workbook; ICellStyle cellStyle = workbook.GetCellStyle(cssKey); if (cellStyle == null) { cellStyle = workbook.GetCellStyle(dic, cell); workbook.AttachedCellStyle(cssKey, cellStyle); } cell.CellStyle = cellStyle; //cell.CellStyle = workbook.GetCellStyle(dic, cell); return cell;//返回单元格方便流水式编程 } public ICellStyle GetCssStyle(IWorkbook workbook, string styleStr) { var dic = new SortedDictionary(); var sortedCss = dic.GetCleanStyle(DefaultStyle); if (!string.IsNullOrEmpty(styleStr)) sortedCss = dic.GetCleanStyle(styleStr); var cssKey = $"CellStyle_{sortedCss.Md5()}"; var cellStyle = workbook.GetCellStyle(cssKey); if (cellStyle == null) { cellStyle = workbook.GetCellStyle(dic); workbook.AttachedCellStyle(cssKey, cellStyle); } return cellStyle; } } internal static class CellStyleRender { #region 解析css样式 /// /// 默认字体样式 /// private static string DefaultFontStyle { get; } = $"fc:{ColorType.Black.ToString()};" +//font-color "fn:宋体;" +//font-name "fs:12;" +//font-size "fw:normal;" +//font-weight "fu:none;" +//font-underline "fi:false;" +//font-italic "fst:false;" +//font-strikeout "fss:none;";//font-superscript #region 设置样式 /// /// 缓存 /// private static readonly ConditionalWeakTable> Table = new ConditionalWeakTable>(); /// /// 获取CellStyle /// /// /// /// /// public static ICellStyle GetCellStyle(this IWorkbook workbook, SortedDictionary dic, ICell cell = null) { ICellStyle cellStyle = workbook.CreateCellStyle(); //if (cell != null) //{ // cellStyle.CloneStyleFrom(cell.CellStyle); //} var fontStyles = dic.Where(w => w.Key.StartsWith("font-")).ToArray(); var fontDic = new SortedDictionary(); foreach (var kv in fontStyles) { fontDic.Add(kv.Key, kv.Value); } var font = workbook.GetFont(fontDic); cellStyle.SetFont(font);//TODO 在基于style.xls基础的样式上增加css时,会造成原字体设置的丢失 var xdic = dic.Where(w => !w.Key.StartsWith("font-")).ToArray(); foreach (var kvp in xdic) { FireCssAccess(cellStyle, workbook, kvp); } return cellStyle; } /// /// 从缓存读取CellStyle /// /// /// /// public static ICellStyle GetCellStyle(this IWorkbook workbook, string propertyName) { if (!Table.TryGetValue(workbook, out var values)) return null; if (values.TryGetValue(propertyName, out var temp)) return temp; return null; } /// /// 缓存CellStyle /// /// /// /// public static void AttachedCellStyle(this IWorkbook workbook, string propertyName, ICellStyle value) { if (!Table.TryGetValue(workbook, out var values)) { values = new Dictionary(); Table.Add(workbook, values); } values[propertyName] = value; } /// /// Md5 key /// /// /// public static string Md5(this string input) { if (input == null) input = string.Empty; byte[] data = Encoding.UTF8.GetBytes(input.Trim().ToLowerInvariant()); using (var md5 = new MD5CryptoServiceProvider()) { data = md5.ComputeHash(data); } var ret = new StringBuilder(); foreach (byte b in data) { ret.Append(b.ToString("x2").ToLowerInvariant()); } return ret.ToString(); } /// /// 设置不是字体的样式 /// /// /// /// private static void FireCssAccess(ICellStyle style, IWorkbook workbook, KeyValuePair kvp) { switch (kvp.Key) { case "WrapText": style.TextWrap(kvp.Value); break; case "Indention": style.TextIndention(kvp.Value); break; case "text-align": style.TextAlign(kvp.Value); break; case "vertical-align": style.VerticalAlign(kvp.Value); break; case "background-color": style.BackgroundColor(kvp.Value); break; case "border-type": style.BorderTypes(kvp.Value); break; case "top-border-type": style.BorderTopTypes(kvp.Value); break; case "right-border-type": style.BorderRightTypes(kvp.Value); break; case "bottom-border-type": style.BorderBottomTypes(kvp.Value); break; case "left-border-type": style.BorderLeftTypes(kvp.Value); break; case "border-color": style.BorderColors(kvp.Value); break; case "top-border-color": style.BorderTopColors(kvp.Value); break; case "right-border-color": style.BorderRightColors(kvp.Value); break; case "bottom-border-color": style.BorderBottomColors(kvp.Value); break; case "left-border-color": style.BorderLeftColors(kvp.Value); break; case "data-format": style.DataFormat(workbook, kvp.Value); break; } } /// /// 获取字体样式 /// /// /// /// private static IFont GetFont(this IWorkbook workbook, SortedDictionary fontdic) { var weight = fontdic.FontWeight(); var color = fontdic.FontColor(); var size = fontdic.FontSize(); var name = fontdic.FontName(); var underline = fontdic.FontUnderline(); var italic = fontdic.FontItalic(); var strikeout = fontdic.FontStrikeout(); var offset = fontdic.ConvertToSuperScript(); var findHeight = (short)(size * 20); var font = workbook.FindFont(weight, color, findHeight, name, italic, strikeout, offset, underline); if (font == null) { font = workbook.CreateFont(); font.Boldweight = weight; font.Color = color; font.FontHeightInPoints = size; font.FontName = name; font.Underline = underline; font.IsItalic = italic; font.IsStrikeout = strikeout; font.TypeOffset = offset; } return font; } #endregion 设置样式 #region 获取样式 /// /// 默认设置 /// /// public static void InitStyleDic(this SortedDictionary dic) { var cssItems = GetCssItems(DefaultFontStyle); foreach (var cssitem in cssItems) { var kvp = GetCssKeyValue(cssitem); if (dic.ContainsKey(kvp.Key)) dic[kvp.Key] = kvp.Value; //覆盖相同key的值 else dic.Add(kvp.Key, kvp.Value); } } /// /// 获取样式简洁字符串 /// /// /// /// public static string GetCleanStyle(this SortedDictionary dic, string style) { style = Regex.Replace(style.Trim(), "\\s+", " "); style = Regex.Replace(style, "\\s;\\s", ";"); style = Regex.Replace(style, "\\s:\\s", ":"); InitStyleDic(dic); var cssItems = GetCssItems(style.TrimEnd(';')); foreach (var cssitem in cssItems) { var kvp = GetCssKeyValue(cssitem); if (dic.ContainsKey(kvp.Key)) dic[kvp.Key] = kvp.Value; //覆盖相同key的值 else dic.Add(kvp.Key, kvp.Value); } var sortedCss = string.Join(";", dic.Select(s => $"{s.Key}:{s.Value}").ToArray()); return sortedCss; } /// /// 获取样式数组 /// /// /// private static string[] GetCssItems(string style) { var cssItems = Regex.Split(style, ";"); cssItems = cssItems.Where(w => !string.IsNullOrWhiteSpace(w)).ToArray(); return cssItems; } /// /// 获取css样式 /// /// /// private static KeyValuePair GetCssKeyValue(string css) { var cssKeyValueArray = Regex.Split(css, ":").ToArray(); var cssKey = cssKeyValueArray[0].StandardCssKey(); var cssValue = cssKey == "font-name" ? cssKeyValueArray[1] : cssKeyValueArray[1].ToUpper(); //字体不应变大写 var kv = new KeyValuePair(cssKey, cssValue); return kv; } #endregion 获取样式 #region 转换Css的 Key /// /// 缩写Key 转换成标准Key /// /// /// private static string StandardCssKey(this string csskey) { if (CssKeyDic.ContainsKey(csskey)) { var sKey = CssKeyDic[csskey]; return sKey; } return csskey; } /// /// key 转换字典 /// private static Dictionary CssKeyDic => new Dictionary { {"color", "font-color"}, {"fc", "font-color"}, {"fw", "font-weight"}, {"fn", "font-name"}, {"fs", "font-size"}, {"italic", "font-italic"}, {"fi", "font-italic"}, {"underline", "font-underline"}, {"fu", "font-underline"}, {"u", "font-underline"}, {"deleteline", "font-strikeout"}, {"d-line", "font-strikeout"}, {"strikeout", "font-strikeout"}, {"fst", "font-strikeout"}, {"d", "font-strikeout"}, {"font-offset", "font-superscript"}, {"superscript", "font-superscript"}, {"fss", "font-superscript"}, {"ss", "font-superscript"}, {"bg-color", "background-color"}, {"bg-c", "background-color"}, {"bgc", "background-color"}, {"align", "text-align"}, {"wrap", "WrapText"}, {"inden", "Indention"}, {"in", "Indention"}, {"v-align", "vertical-align"}, {"b-t", "border-type"}, {"b", "border-type"}, {"bt", "top-border-type"}, {"br", "right-border-type"}, {"bb", "bottom-border-type"}, {"bl", "left-border-type"}, {"b-c", "border-color"}, {"bc", "border-color"}, {"btc", "top-border-color"}, {"brc", "right-border-color"}, {"bbc", "bottom-border-color"}, {"blc", "left-border-color"}, {"format", "data-format"}, {"df", "data-format"} }; #endregion 转换Css的 Key #region 样式转换 #region font-weight private static short FontWeight(this SortedDictionary fontdic) { switch (fontdic["font-weight"]) { case "NORMAL": return 400; case "BOLD": return 700; default: return 0; } } #endregion font-weight #region font-name private static string FontName(this SortedDictionary fontdic) { return fontdic["font-name"]; } #endregion font-name #region font-size private static short FontSize(this SortedDictionary fontdic) { return short.TryParse(fontdic["font-size"], out var value) ? value : (short)10; } #endregion font-size #region font-color private static short FontColor(this SortedDictionary fontdic) { var color = fontdic["font-color"].ConvertToColor(); return color; } #endregion font-color #region font-italic private static bool FontItalic(this SortedDictionary fontdic) { return fontdic["font-italic"] == "TRUE"; } #endregion font-italic #region font-strikeout /// /// 删除线 /// /// /// private static bool FontStrikeout(this SortedDictionary fontdic) { return fontdic["font-strikeout"] == "TRUE"; } #endregion font-strikeout #region WrapText private static void TextWrap(this ICellStyle style, string v) { style.WrapText = v.ToUpper() == "TRUE"; } #endregion WrapText #region TextIndention /// /// 缩进 /// /// /// private static void TextIndention(this ICellStyle style, string v) { if (short.TryParse(v, out var value)) { style.Indention = value; } } #endregion TextIndention #region text-align private static void TextAlign(this ICellStyle style, string v) { style.Alignment = v.ConvertToHorizontalAlignment(); } #endregion text-align #region vertical-align private static void VerticalAlign(this ICellStyle style, string v) { style.VerticalAlignment = v.ConvertToVerticalAlignment(); } #endregion vertical-align #region boder-type / boder-color internal static void BorderTypes(this ICellStyle style, string v) { if (string.IsNullOrEmpty(v)) return; string[] borderTypeNames = { string.Empty, string.Empty, string.Empty, string.Empty }; v = v.ToUpper(); var vs = v.Split(' '); switch (vs.Length) { case 1: borderTypeNames[0] = borderTypeNames[1] = borderTypeNames[2] = borderTypeNames[3] = vs[0]; break; case 2: borderTypeNames[0] = borderTypeNames[2] = vs[0]; borderTypeNames[1] = borderTypeNames[3] = vs[1]; break; case 3: borderTypeNames[0] = vs[0]; borderTypeNames[1] = borderTypeNames[3] = vs[1]; borderTypeNames[2] = vs[2]; break; case 4: borderTypeNames[0] = vs[0]; borderTypeNames[1] = vs[1]; borderTypeNames[2] = vs[2]; borderTypeNames[3] = vs[3]; break; } var borderTopTypeName = borderTypeNames[0]; var borderRightTypeName = borderTypeNames[1]; var borderBottomTypeName = borderTypeNames[2]; var borderLeftTypeName = borderTypeNames[3]; if (!string.IsNullOrWhiteSpace(borderTopTypeName)) style.BorderTop = borderTopTypeName.ConvertToBorderStyle(); if (!string.IsNullOrWhiteSpace(borderRightTypeName)) style.BorderRight = borderRightTypeName.ConvertToBorderStyle(); if (!string.IsNullOrWhiteSpace(borderBottomTypeName)) style.BorderBottom = borderBottomTypeName.ConvertToBorderStyle(); if (!string.IsNullOrWhiteSpace(borderLeftTypeName)) style.BorderLeft = borderLeftTypeName.ConvertToBorderStyle(); } private static void BorderTopTypes(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.BorderTop = v.ConvertToBorderStyle(); } private static void BorderBottomTypes(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.BorderBottom = v.ConvertToBorderStyle(); } private static void BorderLeftTypes(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.BorderLeft = v.ConvertToBorderStyle(); } private static void BorderRightTypes(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.BorderRight = v.ConvertToBorderStyle(); } internal static void BorderColors(this ICellStyle style, string v) { if (string.IsNullOrEmpty(v)) return; string[] borderColors = { string.Empty, string.Empty, string.Empty, string.Empty }; v = v.ToUpper(); var vs = v.Split(' '); switch (vs.Length) { case 1: borderColors[0] = borderColors[1] = borderColors[2] = borderColors[3] = vs[0]; break; case 2: borderColors[0] = borderColors[2] = vs[0]; borderColors[1] = borderColors[3] = vs[1]; break; case 3: borderColors[0] = vs[0]; borderColors[1] = borderColors[3] = vs[1]; borderColors[2] = vs[2]; break; case 4: borderColors[0] = vs[0]; borderColors[1] = vs[1]; borderColors[2] = vs[2]; borderColors[3] = vs[3]; break; } var borderTopColor = borderColors[0]; var borderRightColor = borderColors[1]; var borderBottomColor = borderColors[2]; var borderLeftColor = borderColors[3]; if (!string.IsNullOrWhiteSpace(borderTopColor)) style.TopBorderColor = borderTopColor.ConvertToColor(); if (!string.IsNullOrWhiteSpace(borderRightColor)) style.RightBorderColor = borderRightColor.ConvertToColor(); if (!string.IsNullOrWhiteSpace(borderBottomColor)) style.BottomBorderColor = borderBottomColor.ConvertToColor(); if (!string.IsNullOrWhiteSpace(borderLeftColor)) style.LeftBorderColor = borderLeftColor.ConvertToColor(); } private static void BorderTopColors(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.TopBorderColor = v.ConvertToColor(); } private static void BorderBottomColors(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.BottomBorderColor = v.ConvertToColor(); } private static void BorderLeftColors(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.LeftBorderColor = v.ConvertToColor(); } private static void BorderRightColors(this ICellStyle style, string v) { if (!string.IsNullOrWhiteSpace(v)) style.RightBorderColor = v.ConvertToColor(); } #endregion boder-type / boder-color #region data-format private static void DataFormat(this ICellStyle style, IWorkbook workbook, string v) { if (string.IsNullOrEmpty(v)) return; var df = workbook.CreateDataFormat(); style.DataFormat = df.GetFormat(v); } #endregion data-format #region BackgroundColor private static void BackgroundColor(this ICellStyle style, string v) { if (string.IsNullOrEmpty(v)) return; style.FillPattern = FillPattern.SolidForeground; style.FillForegroundColor = v.ConvertToColor(); } #endregion BackgroundColor private static FontSuperScript ConvertToSuperScript(this SortedDictionary fontdic) { var v = fontdic["font-superscript"]; switch (v) { case "SUPER": return FontSuperScript.Super; case "SUB": return FontSuperScript.Sub; default: return FontSuperScript.None; } } private static FontUnderlineType FontUnderline(this SortedDictionary fontdic) { var v = fontdic["font-underline"]; switch (v) { case "SINGLE": return FontUnderlineType.Single; case "DOUBLE": return FontUnderlineType.Double; case "SINGLEACCOUNTING": case "SINGLE_ACCOUNTING": return FontUnderlineType.SingleAccounting; case "DOUBLEACCOUNTING": case "DOUBLE_ACCOUNTING": return FontUnderlineType.DoubleAccounting; default: return FontUnderlineType.None; } } public static short ConvertToColor(this string v) { if (string.IsNullOrEmpty(v)) return 32767; switch (v.ToUpper()) { case "AQUA": return (short)ColorType.Aqua; case "AUTOMATIC": return (short)ColorType.Automatic; case "BLACK": return (short)ColorType.Black; case "BLUE": return (short)ColorType.Blue; case "BLUE_GREY": case "BLUEGREY": return (short)ColorType.BlueGrey; case "BRIGHT_GREEN": case "BRIGHTGREEN": return (short)ColorType.BrightGreen; case "BROWN": return (short)ColorType.Brown; case "CORAL": return (short)ColorType.Coral; case "CORNFLOWER_BLUE": case "CORNFLOWERBLUE": return (short)ColorType.CornflowerBlue; case "DARK_BLUE": case "DARKBLUE": return (short)ColorType.DarkBlue; case "DARK_GREEN": case "DARKGREEN": return (short)ColorType.DarkGreen; case "DARK_RED": case "DARKRED": return (short)ColorType.DarkRed; case "DARK_TEAL": case "DARKTEAL": return (short)ColorType.DarkTeal; case "DARK_YELLOW": case "DARKYELLOW": return (short)ColorType.DarkYellow; case "GOLD": return (short)ColorType.Gold; case "GREEN": return (short)ColorType.Green; case "GREY_25_PERCENT": case "GREY25PERCENT": return (short)ColorType.Grey25Percent; case "GREY_40_PERCENT": case "GREY40PERCENT": return (short)ColorType.Grey40Percent; case "GREY_50_PERCENT": case "GREY50PERCENT": return (short)ColorType.Grey50Percent; case "GREY_80_PERCENT": case "GREY80PERCENT": return (short)ColorType.Grey80Percent; case "INDIGO": return (short)ColorType.Indigo; case "LAVENDER": return (short)ColorType.Lavender; case "LEMON_CHIFFON": case "LEMONCHIFFON": return (short)ColorType.LemonChiffon; case "LIGHT_BLUE": case "LIGHTBLUE": return (short)ColorType.LightBlue; case "LIGHT_CORNFLOWERBLUE": case "LIGHTCORNFLOWERBLUE": return (short)ColorType.LightCornflowerBlue; case "LIGHT_GREEN": case "LIGHTGREEN": return (short)ColorType.LightGreen; case "LIGHT_ORANGE": case "LIGHTORANGE": return (short)ColorType.LightOrange; case "LIGHT_TURQUOISE": case "LIGHTTURQUOISE": return (short)ColorType.LightTurquoise; case "LIGHT_YELLOW": case "LIGHTYELLOW": return (short)ColorType.LightYellow; case "LIME": return (short)ColorType.Lime; case "MAROON": return (short)ColorType.Maroon; case "OLIVE_GREEN": case "OLIVEGREEN": return (short)ColorType.OliveGreen; case "ORANGE": return (short)ColorType.Orange; case "ORCHID": return (short)ColorType.Orchid; case "PALE_BLUE": case "PALEBLUE": return (short)ColorType.PaleBlue; case "PINK": return (short)ColorType.Pink; case "PLUM": return (short)ColorType.Plum; case "RED": return (short)ColorType.Red; case "ROSE": return (short)ColorType.Rose; case "ROYAL_BLUE": case "ROYALBLUE": return (short)ColorType.RoyalBlue; case "SEA_GREEN": case "SEAGREEN": return (short)ColorType.SeaGreen; case "SKY_BLUE": case "SKYBLUE": return (short)ColorType.SkyBlue; case "TAN": return (short)ColorType.Tan; case "TEAL": return (short)ColorType.Teal; case "TURQUOISE": return (short)ColorType.Turquoise; case "VIOLET": return (short)ColorType.Violet; case "WHITE": return (short)ColorType.White; case "YELLOW": return (short)ColorType.Yellow; default: return 32767; } } private static HorizontalAlignment ConvertToHorizontalAlignment(this string v) { if (string.IsNullOrEmpty(v)) return HorizontalAlignment.General; switch (v.ToUpper()) { case "LEFT": return HorizontalAlignment.Left; case "CENTER": return HorizontalAlignment.Center; case "CENTERSELECTION": case "CENTER_SELECTION": return HorizontalAlignment.CenterSelection; case "RIGHT": return HorizontalAlignment.Right; case "DISTRIBUTED": return HorizontalAlignment.Distributed; case "FILL": return HorizontalAlignment.Fill; case "JUSTIFY": return HorizontalAlignment.Justify; default: return HorizontalAlignment.General; } } private static VerticalAlignment ConvertToVerticalAlignment(this string v) { if (string.IsNullOrEmpty(v)) return VerticalAlignment.Justify; switch (v.ToUpper()) { case "TOP": return VerticalAlignment.Top; case "CENTER": return VerticalAlignment.Center; case "BOTTOM": return VerticalAlignment.Bottom; case "DISTRIBUTED": return VerticalAlignment.Distributed; default: return VerticalAlignment.Justify; } } public static BorderStyle ConvertToBorderStyle(this string v) { if (string.IsNullOrEmpty(v)) return BorderStyle.None; switch (v.ToUpper()) { case "THIN": return BorderStyle.Thin; case "MEDIUM": return BorderStyle.Medium; case "DASHED": return BorderStyle.Dashed; case "HAIR": return BorderStyle.Hair; case "THICK": return BorderStyle.Thick; case "DOUBLE": return BorderStyle.Double; case "DOTTED": return BorderStyle.Dotted; case "MEDIUMDASHED": case "MEDIUM_DASHED": return BorderStyle.MediumDashed; case "DASHDOT": case "DASH_DOT": return BorderStyle.DashDot; case "MEDIUMDASHDOT": case "MEDIUM_DASH_DOT": return BorderStyle.MediumDashDot; case "DASHDOTDOT": case "DASH_DOT_DOT": return BorderStyle.DashDotDot; case "MEDIUMDASHDOTDOT": case "MEDIUM_DASH_DOT_DOT": return BorderStyle.MediumDashDotDot; case "SLANTEDDASHDOT": case "SLANTED_DASH_DOT": return BorderStyle.SlantedDashDot; default: return BorderStyle.None; } } #endregion 样式转换 #endregion 解析css样式 } public enum ColorType { Black = HSSFColor.Black.Index, Brown = HSSFColor.Brown.Index, OliveGreen = HSSFColor.OliveGreen.Index, DarkGreen = HSSFColor.DarkGreen.Index, DarkTeal = HSSFColor.DarkTeal.Index, DarkBlue = HSSFColor.DarkBlue.Index, Indigo = HSSFColor.Indigo.Index, Grey80Percent = HSSFColor.Grey80Percent.Index, Orange = HSSFColor.Orange.Index, DarkYellow = HSSFColor.DarkYellow.Index, Green = HSSFColor.Green.Index, Teal = HSSFColor.Teal.Index, Blue = HSSFColor.Blue.Index, BlueGrey = HSSFColor.BlueGrey.Index, Grey50Percent = HSSFColor.Grey50Percent.Index, Red = HSSFColor.Red.Index, LightOrange = HSSFColor.LightOrange.Index, Lime = HSSFColor.Lime.Index, SeaGreen = HSSFColor.SeaGreen.Index, Aqua = HSSFColor.Aqua.Index, LightBlue = HSSFColor.LightBlue.Index, Violet = HSSFColor.Violet.Index, Grey40Percent = HSSFColor.Grey40Percent.Index, Pink = HSSFColor.Pink.Index, Gold = HSSFColor.Gold.Index, Yellow = HSSFColor.Yellow.Index, BrightGreen = HSSFColor.BrightGreen.Index, Turquoise = HSSFColor.Turquoise.Index, DarkRed = HSSFColor.DarkRed.Index, SkyBlue = HSSFColor.SkyBlue.Index, Plum = HSSFColor.Plum.Index, Grey25Percent = HSSFColor.Grey25Percent.Index, Rose = HSSFColor.Rose.Index, LightYellow = HSSFColor.LightYellow.Index, LightGreen = HSSFColor.LightGreen.Index, LightTurquoise = HSSFColor.LightTurquoise.Index, PaleBlue = HSSFColor.PaleBlue.Index, Lavender = HSSFColor.Lavender.Index, White = HSSFColor.White.Index, CornflowerBlue = HSSFColor.CornflowerBlue.Index, LemonChiffon = HSSFColor.LemonChiffon.Index, Maroon = HSSFColor.Maroon.Index, Orchid = HSSFColor.Orchid.Index, Coral = HSSFColor.Coral.Index, RoyalBlue = HSSFColor.RoyalBlue.Index, LightCornflowerBlue = HSSFColor.LightCornflowerBlue.Index, Tan = HSSFColor.Tan.Index, Automatic = HSSFColor.Automatic.Index } public static class TransExp { private static readonly Func Cache = GetFunc(); private static Func GetFunc() { ParameterExpression parameterExpression = Expression.Parameter(typeof(TIn), "p"); List memberBindingList = new List(); foreach (var item in typeof(TOut).GetProperties()) { if (!item.CanWrite) continue; MemberExpression property = Expression.Property(parameterExpression, typeof(TIn).GetProperty(item.Name) ?? throw new InvalidOperationException()); MemberBinding memberBinding = Expression.Bind(item, property); memberBindingList.Add(memberBinding); } MemberInitExpression memberInitExpression = Expression.MemberInit(Expression.New(typeof(TOut)), memberBindingList.ToArray()); Expression> lambda = Expression.Lambda>(memberInitExpression, new ParameterExpression[] { parameterExpression }); return lambda.Compile(); } public static TOut Trans(TIn tIn) { return Cache(tIn); } } }