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
}