using NPOI.HSSF.UserModel; using NPOI.OpenXmlFormats.Spreadsheet; using NPOI.SS.UserModel; using NPOI.SS.Util; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Linq.Expressions; using WalkingTec.Mvvm.Core.Extensions; namespace WalkingTec.Mvvm.Core { public class ExcelPropety { #region 属性 private string _columnName; /// /// 列名 /// public string ColumnName { get { string col = _columnName; return col; } set { _columnName = value; } } public string FieldDisplayName { get; set; } public string FieldName { get; set; } //private string _backgroudColor; ///// ///// 背景色 ///// //public string BackgroudColor //{ // get { return _backgroudColor; } // set { _backgroudColor = value; } //} /// /// 背景色 /// public BackgroudColorEnum BackgroudColor { get; set; } private Type _resourceType; /// /// 多语言 /// public Type ResourceType { get { return _resourceType; } set { _resourceType = value; } } private ColumnDataType _dataType; /// /// 数据类型 /// public ColumnDataType DataType { get { return _dataType; } set { _dataType = value; } } private Type _enumType; public Type EnumType { get { return _enumType; } set { _enumType = value; this.ListItems = _enumType.ToListItems(); } } private string _minValueOrLength; /// /// 最小长度 /// public string MinValueOrLength { get { return _minValueOrLength; } set { _minValueOrLength = value; } } private string _maxValuseOrLength; /// /// 最大长度 /// public string MaxValuseOrLength { get { return _maxValuseOrLength; } set { _maxValuseOrLength = value; } } private bool _isNullAble; /// /// 是否可以为空 /// public bool IsNullAble { get { return _isNullAble; } set { _isNullAble = value; } } private IEnumerable _listItems; /// /// 类表中数据 /// public IEnumerable ListItems { get { return _listItems; } set { _listItems = value; } } private object _value; /// /// Value /// public object Value { get { return _value; } set { _value = value; } } private List _dynamicColumns; /// /// 动态列 /// public List DynamicColumns { get { return _dynamicColumns == null ? new List() : _dynamicColumns; } set { _dynamicColumns = value; } } public Type SubTableType { get; set; } public bool ReadOnly { get; set; } /// /// 字符数量 /// public int CharCount { get; set; } #endregion #region 设定Excel数据验证 /// /// 设置Excel单元格样式(标题),数据格式 /// /// 数据类型 /// 单元格索引 /// Sheet页 /// 数据Sheet页 /// 样式 /// 格式 public void SetColumnFormat(ColumnDataType dateType, int porpetyIndex, ISheet sheet, ISheet dataSheet, ICellStyle dataStyle, IDataFormat dataFormat) { XSSFDataValidationHelper dvHelper = new XSSFDataValidationHelper((XSSFSheet)sheet); CellRangeAddressList CellRangeList = new CellRangeAddressList(1, 1048576 - 1, porpetyIndex, porpetyIndex); //超过1048576最大行数,打开Excel会报错 XSSFDataValidationConstraint dvConstraint = null; XSSFDataValidation dataValidation = null; switch (dateType) { case ColumnDataType.Date: case ColumnDataType.DateTime: //因为DateTime类型,添加Validation报错,所以去掉 dataStyle.DataFormat = dataFormat.GetFormat("yyyy-MM-dd HH:mm:ss"); break; case ColumnDataType.Number: this.MinValueOrLength = string.IsNullOrEmpty(this.MinValueOrLength) ? long.MinValue.ToString() : this.MinValueOrLength; this.MaxValuseOrLength = string.IsNullOrEmpty(this.MaxValuseOrLength) ? long.MaxValue.ToString() : this.MaxValuseOrLength; dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateNumericConstraint(ValidationType.INTEGER, OperatorType.BETWEEN, this.MinValueOrLength, this.MaxValuseOrLength); dataValidation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, CellRangeList); dataValidation.CreateErrorBox(CoreProgram._localizer?["Sys.Error"], CoreProgram._localizer?["Sys.PleaseInputNumber"]); dataStyle.DataFormat = dataFormat.GetFormat("0"); dataValidation.CreatePromptBox(CoreProgram._localizer?["Sys.PleaseInputNumberFormat"], CoreProgram._localizer?["Sys.DataRange", MinValueOrLength, MaxValuseOrLength]); break; case ColumnDataType.Float: this.MinValueOrLength = string.IsNullOrEmpty(this.MinValueOrLength) ? decimal.MinValue.ToString() : this.MinValueOrLength; this.MaxValuseOrLength = string.IsNullOrEmpty(this.MaxValuseOrLength) ? decimal.MaxValue.ToString() : this.MaxValuseOrLength; dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateNumericConstraint(ValidationType.DECIMAL, OperatorType.BETWEEN, this.MinValueOrLength, this.MaxValuseOrLength); dataValidation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, CellRangeList); dataValidation.CreateErrorBox(CoreProgram._localizer?["Sys.Error"], CoreProgram._localizer?["Sys.PleaseInputDecimal"]); dataStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("0.00"); dataValidation.CreatePromptBox(CoreProgram._localizer?["Sys.PleaseInputDecimalFormat"], CoreProgram._localizer?["Sys.DataRange", MinValueOrLength, MaxValuseOrLength]); break; case ColumnDataType.Bool: dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateFormulaListConstraint("Sheet1!$A$1:$B$1"); dataValidation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, CellRangeList); dataValidation.CreateErrorBox(CoreProgram._localizer?["Sys.Error"], CoreProgram._localizer?["Sys.PleaseInputExistData"]); dataValidation.CreatePromptBox(CoreProgram._localizer?["Sys.ComboBox"], CoreProgram._localizer?["Sys.PleaseInputExistData"]); break; case ColumnDataType.Text: this.MinValueOrLength = string.IsNullOrEmpty(this.MinValueOrLength) ? "0" : this.MinValueOrLength; this.MaxValuseOrLength = string.IsNullOrEmpty(this.MaxValuseOrLength) ? "2000" : this.MaxValuseOrLength; dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateNumericConstraint(ValidationType.TEXT_LENGTH, OperatorType.BETWEEN, this.MinValueOrLength, this.MaxValuseOrLength); dataValidation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, CellRangeList); dataValidation.CreateErrorBox(CoreProgram._localizer?["Sys.Error"], CoreProgram._localizer?["Sys.WrongTextLength"]); dataStyle.DataFormat = dataFormat.GetFormat("@"); dataValidation.CreatePromptBox(CoreProgram._localizer?["Sys.PleaseInputText"], CoreProgram._localizer?["Sys.DataRange", MinValueOrLength, MaxValuseOrLength]); break; case ColumnDataType.ComboBox: case ColumnDataType.Enum: int count = this.ListItems.Count() == 0 ? 1 : this.ListItems.Count(); string cloIndex = ""; if (porpetyIndex > 25) { cloIndex += Convert.ToChar((int)(Math.Floor(porpetyIndex / 26d)) - 1 + 65); } cloIndex += Convert.ToChar(65 + porpetyIndex % 26).ToString(); IName range = sheet.Workbook.CreateName(); range.RefersToFormula = "Sheet2!$" + cloIndex + "$1:$" + cloIndex + "$" + count; range.NameName = "dicRange" + porpetyIndex; dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateFormulaListConstraint("dicRange" + porpetyIndex); dataValidation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, CellRangeList); dataValidation.CreateErrorBox(CoreProgram._localizer?["Sys.Error"], CoreProgram._localizer?["Sys.PleaseInputExistData"]); var listItemsTemp = this.ListItems.ToList(); for (int rowIndex = 0; rowIndex < this.ListItems.Count(); rowIndex++) { IRow dataSheetRow = dataSheet.GetRow(rowIndex); if (dataSheetRow == null) { dataSheetRow = dataSheet.CreateRow(rowIndex); } dataSheetRow.CreateCell(porpetyIndex).SetCellValue(listItemsTemp[rowIndex].Text); dataStyle.DataFormat = dataFormat.GetFormat("@"); dataSheetRow.Cells.Where(x => x.ColumnIndex == porpetyIndex).FirstOrDefault().CellStyle = dataStyle; } dataValidation.CreatePromptBox(CoreProgram._localizer?["Sys.ComboBox"], CoreProgram._localizer?["Sys.PleaseInputExistData"]); break; default: dvConstraint = (XSSFDataValidationConstraint)dvHelper.CreateNumericConstraint(ValidationType.TEXT_LENGTH, OperatorType.BETWEEN, this.MinValueOrLength, this.MaxValuseOrLength); dataValidation = (XSSFDataValidation)dvHelper.CreateValidation(dvConstraint, CellRangeList); dataValidation.CreateErrorBox(CoreProgram._localizer?["Sys.Error"], CoreProgram._localizer?["Sys.WrongTextLength"]); dataStyle.DataFormat = HSSFDataFormat.GetBuiltinFormat("@"); break; } if (dataValidation == null) { return; } if (!this.IsNullAble) { dataValidation.EmptyCellAllowed = false; } sheet.SetDefaultColumnStyle(porpetyIndex, dataStyle); dataValidation.ShowErrorBox = true; sheet.AddValidationData(dataValidation); } #endregion #region 验证Excel数据 /// /// 验证Value 并生成错误信息(edit by dufei 2014-06-12,修改了当列设置为不验证时候,下拉列表获取不到值的问题) /// /// /// /// public void ValueValidity(string value, List errorMessage, int rowIndex) { if (this.IsNullAble && string.IsNullOrEmpty(value)) { this.Value = value; } else { ErrorMessage err = null; switch (this.DataType) { case ColumnDataType.Date: case ColumnDataType.DateTime: DateTime tryDateTimeResult; if (!DateTime.TryParse(value, out tryDateTimeResult)) { err = new ErrorMessage { Index = rowIndex, Message = CoreProgram._localizer?["Sys.{0}formaterror", this.ColumnName] }; } this.Value = tryDateTimeResult; break; case ColumnDataType.Number: int tryIntResult; if (!int.TryParse(value, out tryIntResult)) { err = new ErrorMessage { Index = rowIndex, Message = CoreProgram._localizer?["Sys.{0}formaterror", this.ColumnName] }; } this.Value = tryIntResult; break; case ColumnDataType.Float: decimal tryDecimalResult; if (!decimal.TryParse(value, out tryDecimalResult)) { err = new ErrorMessage { Index = rowIndex, Message = CoreProgram._localizer?["Sys.{0}formaterror", this.ColumnName] }; } this.Value = tryDecimalResult; break; case ColumnDataType.Bool: if (value == CoreProgram._localizer?["Sys.Yes"]) { this.Value = true; } else if (value == CoreProgram._localizer?["Sys.No"]) { this.Value = false; } else { err = new ErrorMessage { Index = rowIndex, Message = CoreProgram._localizer?["Sys.{0}formaterror", this.ColumnName] }; } break; case ColumnDataType.Text: this.Value = value; break; case ColumnDataType.ComboBox: case ColumnDataType.Enum: if (!this.ListItems.Any(x => x.Text == value)) { err = new ErrorMessage { Index = rowIndex, Message = CoreProgram._localizer?["Sys.{0}ValueNotExist", this.ColumnName] }; } else { this.Value = this.ListItems.Where(x => x.Text == value).FirstOrDefault().Value; } break; default: err = new ErrorMessage { Index = rowIndex, Message = CoreProgram._localizer?["Sys.{0}ValueTypeNotAllowed", this.ColumnName] }; break; } if (err != null && this.SubTableType == null) { errorMessage.Add(err); } } } #endregion #region 自定义委托处理excel数据 /// /// 处理为多列数据 /// public CopyData FormatData; /// /// 处理为单列数据 /// public CopySingleData FormatSingleData; #endregion public static ExcelPropety CreateProperty(Expression> field, bool isDateTime = false) { ExcelPropety cp = new ExcelPropety(); cp.FieldDisplayName = field.GetPropertyDisplayName(); var fname = field.GetPropertyName(); Type t = field.GetPropertyInfo().PropertyType; if (fname.Contains('.')) { int index = fname.LastIndexOf('.'); cp.FieldName = fname.Substring(index + 1); cp.SubTableType = field.GetPropertyInfo().DeclaringType; } else { cp.FieldName = fname; } if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) { var req = field.GetPropertyInfo().GetCustomAttributes(typeof(RequiredAttribute), false).Cast().FirstOrDefault(); if (req == null) { cp.IsNullAble = true; } t = t.GenericTypeArguments[0]; } if (t == typeof(int) || t == typeof(long) || t == typeof(short)) { var sl = t.GetCustomAttributes(typeof(RangeAttribute), false).Cast().FirstOrDefault(); cp.DataType = ColumnDataType.Number; if (sl != null) { if (sl.Maximum != null) { cp.MaxValuseOrLength = sl.Maximum.ToString(); } if (sl.Minimum != null) { cp.MinValueOrLength = sl.Minimum.ToString(); } } } else if (t == typeof(float) || t == typeof(double) || t == typeof(decimal)) { cp.DataType = ColumnDataType.Float; } else if (t == typeof(bool)) { cp.DataType = ColumnDataType.Bool; } else if (t.IsEnum) { cp.DataType = ColumnDataType.Enum; cp.EnumType = t; } else if (t == typeof(DateTime)) { cp.DataType = ColumnDataType.Date; if (isDateTime) cp.DataType = ColumnDataType.DateTime; } else { var sl = field.GetPropertyInfo().GetCustomAttributes(typeof(StringLengthAttribute), false).Cast().FirstOrDefault(); var req = field.GetPropertyInfo().GetCustomAttributes(typeof(RequiredAttribute), false).Cast().FirstOrDefault(); cp.DataType = ColumnDataType.Text; if (req == null) { cp.IsNullAble = true; } if (sl != null) { if (sl.MaximumLength != 0) { cp.MaxValuseOrLength = sl.MaximumLength + ""; } if (sl.MinimumLength != 0) { cp.MinValueOrLength = sl.MinimumLength + ""; } } } cp.CharCount = 20; return cp; } } #region 辅助类型 /// /// 定义处理excel为单个字段的委托 /// /// excel中的值 /// excel中的值 /// 实体的值 /// 错误消息,没有错误为空 public delegate void CopySingleData(object excelValue, BaseTemplateVM excelTemplate, out string entityValue, out string errorMsg); /// /// 定义处理excel为多个字段的委托 /// /// excel中的值 /// excel中的值 /// 返回的处理结果 public delegate ProcessResult CopyData(object excelValue, BaseTemplateVM excelTemplate); /// /// 处理结果 /// public class ProcessResult { public List EntityValues { get; set; } public ProcessResult() { EntityValues = new List(); } } /// /// 单字段类 /// public class EntityValue { /// /// 字段名称 /// public string FieldName { get; set; } /// /// 字段值 /// public string FieldValue { get; set; } /// /// 错误消息 /// public string ErrorMsg { get; set; } } public enum ColumnDataType { Text, Number, Date, Float, Bool, ComboBox, Enum, Dynamic, DateTime } #endregion }