/// <summary> /// 解析配置 /// </summary> public void ResolveConfig() { // 重置填充单元格的行号 Fill.ForEach(t => { t.RowIndex--; t.ColumnIndex = PowerExcelConfigCell.ToIndex(t.Col); }); //设置整体属性 Prop.StartColumnIndex = PowerExcelConfigCell.ToIndex(Prop.StartCol); Prop.DemoRow--; Prop.StartRow = Prop.DemoRow + 1; //设置循环列的 列索引号 var i = 0; Row.ForEach(field => { field.ColumnIndex = Prop.StartColumnIndex + i++; field.Col = field.GetColumnChar(); }); //设置列的公式信息 将$Field转换成 D{i} Row.Where(t => string.IsNullOrEmpty(t.Formula) == false).ToList().ForEach(field => { field.Formula = Regex.Replace(field.Formula, @"\$(?<name>\w+)", (match) => { var name = match.Groups["name"]?.Value; if (string.IsNullOrEmpty(name)) { return(match.Value); } //查找源字段 得到公式信息 var index = Row.FirstOrDefault(t => t.Field == name); if (index == null) { throw new Exception($"行字段中未找到{name}"); } return(index.GetColumnChar() + "{i}"); }); }); }
/// <summary> /// 应用规则 /// </summary> private void ApplyRule() { //单独存放一个工作簿存放所有的数据 var sheetName = $"ref_rule"; var sheetRef = _workbook.CreateSheet(sheetName);//名为ref的工作表 //循环 i 作为数据存储的列 // 第一组数据 存储在第一列 // 第二组数据 存储在第二列 // 以此类推 for (int i = 0; i < _rules.Count; i++) { var rule = _rules[i]; var options = rule.Source; if (options.Count == 0) { continue; } //在当前列 保存所有数据, 所有数据是存储在行上 for (var j = 0; j < options.Count; j++) { var row = sheetRef.GetRow(j) ?? sheetRef.CreateRow(j); row.CreateCell(i).SetCellValue(options[j]); } //在Excel工作簿中增加此数据范围 IName range = _workbook.CreateName();//创建一个命名公式 //获取当前列的字符串列信息,如 1=>A , 2=>B var colChar = PowerExcelConfigCell.ToColumnChar(i + 1); //公式范围格式应为:A1-A50 B1:B25 range.RefersToFormula = $"{sheetName}!${colChar}$1:${colChar}${options.Count}"; //公式内容,就是上面的区域 range.NameName = $"rule_{i}"; //公式名称,可以在"公式"-->"名称管理器"中看到 //规则也保存该名称,留着后面使用 rule.RuleName = range.NameName; //if (rule.RowField != null && _dtList.Rows.Count > 0) //应用到行级字段 if (rule.RowField != null) { foreach (var field in rule.RowField) { SetField2Select(range.NameName, field); } } //应用到填充字段 if (rule.FillField != null) { foreach (var field in rule.FillField) { SetField2Select(range.NameName, field); } } } var index = _workbook.GetSheetIndex(sheetRef); _workbook.SetSheetHidden(index, _config.Prop.Debug ? false : true); }
/// <summary> /// 校验单元格是否通过验证 /// </summary> /// <param name="rowIndex">行号</param> /// <param name="field">字段列信息</param> /// <param name="cellVal"></param> private void ValidateCellValue(int rowIndex, PowerExcelConfigCell field, object cellVal) { var attr = field.Attribute; var isEmptyCell = cellVal == null || string.IsNullOrEmpty(cellVal.ToString()); //没有配置校验规则 就放弃校验 if (attr != null) { //校验不能为空 if (attr.Required && isEmptyCell == true) { _errors.Add(new ErrorDTO($"{field.Title} ", $"{field.Title}为必填项") { ColName = field.Col, RowIndex = rowIndex + 1 }); return; } //校验邮箱 if (attr.Validate == nameof(ValidateRule.mail) && isEmptyCell == false) { Regex _mail = new Regex(@"^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$"); if (_mail.IsMatch(cellVal.ToString()) == false) { _errors.Add(new ErrorDTO($"{field.Title} ", $"邮箱:{cellVal} 格式不正确") { ColName = field.Col, RowIndex = rowIndex + 1 }); } } } //空数据就没有必要做其他类型的校验 if (isEmptyCell) { return; } //存在数据在做校验 金额列校验最大值和最小值 if (field.CellType == "number") { double val; if (cellVal is double) { val = (double)cellVal; } else if (double.TryParse(cellVal.ToString(), out val) == false) { _errors.Add(new ErrorDTO($"{field.Title} ", $"无效数值{cellVal}") { ColName = field.Col, RowIndex = rowIndex + 1 }); } if (attr != null) { if (val < attr.Min) { _errors.Add(new ErrorDTO($"{field.Title} 超过最小值", $"{val} 小于 {attr.Min}") { ColName = field.Col, RowIndex = rowIndex + 1 }); } else if (val > attr.Max) { _errors.Add(new ErrorDTO($"{field.Title} 超过最大值", $"{val} 大于 {attr.Max}") { ColName = field.Col, RowIndex = rowIndex + 1 }); } } } else if (field.CellType == "text") { } else if (field.CellType == "date") { //单元格如果是日期格式,在非空前提下,必须校验时间格式 if (isEmptyCell == false) { DateTime val; if (cellVal is DateTime) { val = (DateTime)cellVal; } else if (DateTime.TryParse(cellVal.ToString(), out val) == false) { _errors.Add(new ErrorDTO($"{field.Title} ", $"时间值,{cellVal} 格式不正确") { ColName = field.Col, RowIndex = rowIndex + 1 }); } } } }
/// <summary> /// 设置单元格的值 /// </summary> /// <param name="cell">单元格</param> /// <param name="filed">字段</param> /// <param name="dataRowIndex">行号 用于设置公式</param> /// <param name="cellVal">单元格值</param> private void SetCellValue(ICell cell, PowerExcelConfigCell filed, int dataRowIndex, string cellVal) { //设置单元格类型 //如果没有公式,且指定了单元格类型,直接设置类型 var cellType = filed.GetCellType(); if (string.IsNullOrEmpty(filed.Formula) && cellType != CellType.Unknown) { cell.SetCellType(cellType); } else { cell.SetCellType(CellType.Formula); } //数值列,尝试将数据转换为数值 if (cell.CellType == CellType.Numeric) { //获取格式信息 string formatCode = _df.GetFormat(cell.CellStyle.DataFormat); //是否是日期列 if (DateUtil.IsCellDateFormatted(cell)) { var val = cellVal.AsDateTime(); if (val != DateTime.MinValue) { cell.SetCellValue(val); } } else { // 否则就是其他数值列类型 double num = cellVal.AsDouble(double.MinValue); if (num == double.MinValue) { //转换失败,直接赋值 cell.SetCellValue(cellVal); } else { //检测是否是百分比 是的话,手动除以100,因为程序里通常存的是50,表示50% if (formatCode.EndsWith("%")) { cell.SetCellValue(num / 100); } else { cell.SetCellValue(num); } } } } else if (cell.CellType == CellType.Formula) { //公式列信息, {i} 标示当前行 cell.CellFormula = filed.Formula.Replace("{i}", (dataRowIndex + 1).ToString()); } else { cell.SetCellValue(cellVal); } }