iotgateway/WalkingTec.Mvvm/WalkingTec.Mvvm.Core/Support/ExcelPropety.cs
2021-12-14 14:10:44 +08:00

498 lines
21 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
/// <summary>
/// 列名
/// </summary>
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;
///// <summary>
///// 背景色
///// </summary>
//public string BackgroudColor
//{
// get { return _backgroudColor; }
// set { _backgroudColor = value; }
//}
/// <summary>
/// 背景色
/// </summary>
public BackgroudColorEnum BackgroudColor { get; set; }
private Type _resourceType;
/// <summary>
/// 多语言
/// </summary>
public Type ResourceType
{
get { return _resourceType; }
set { _resourceType = value; }
}
private ColumnDataType _dataType;
/// <summary>
/// 数据类型
/// </summary>
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;
/// <summary>
/// 最小长度
/// </summary>
public string MinValueOrLength
{
get { return _minValueOrLength; }
set { _minValueOrLength = value; }
}
private string _maxValuseOrLength;
/// <summary>
/// 最大长度
/// </summary>
public string MaxValuseOrLength
{
get { return _maxValuseOrLength; }
set { _maxValuseOrLength = value; }
}
private bool _isNullAble;
/// <summary>
/// 是否可以为空
/// </summary>
public bool IsNullAble
{
get { return _isNullAble; }
set { _isNullAble = value; }
}
private IEnumerable<ComboSelectListItem> _listItems;
/// <summary>
/// 类表中数据
/// </summary>
public IEnumerable<ComboSelectListItem> ListItems
{
get { return _listItems; }
set { _listItems = value; }
}
private object _value;
/// <summary>
/// Value
/// </summary>
public object Value
{
get { return _value; }
set { _value = value; }
}
private List<ExcelPropety> _dynamicColumns;
/// <summary>
/// 动态列
/// </summary>
public List<ExcelPropety> DynamicColumns
{
get { return _dynamicColumns == null ? new List<ExcelPropety>() : _dynamicColumns; }
set { _dynamicColumns = value; }
}
public Type SubTableType { get; set; }
public bool ReadOnly { get; set; }
/// <summary>
/// 字符数量
/// </summary>
public int CharCount { get; set; }
#endregion
#region Excel数据验证
/// <summary>
/// 设置Excel单元格样式标题数据格式
/// </summary>
/// <param name="dateType">数据类型</param>
/// <param name="porpetyIndex">单元格索引</param>
/// <param name="sheet">Sheet页</param>
/// <param name="dataSheet">数据Sheet页</param>
/// <param name="dataStyle">样式</param>
/// <param name="dataFormat">格式</param>
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数据
/// <summary>
/// 验证Value 并生成错误信息(edit by dufei 2014-06-12,修改了当列设置为不验证时候,下拉列表获取不到值的问题)
/// </summary>
/// <param name="value"></param>
/// <param name="errorMessage"></param>
/// <param name="rowIndex"></param>
public void ValueValidity(string value, List<ErrorMessage> 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数据
/// <summary>
/// 处理为多列数据
/// </summary>
public CopyData FormatData;
/// <summary>
/// 处理为单列数据
/// </summary>
public CopySingleData FormatSingleData;
#endregion
public static ExcelPropety CreateProperty<T>(Expression<Func<T, object>> 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<RequiredAttribute>().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<RangeAttribute>().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<StringLengthAttribute>().FirstOrDefault();
var req = field.GetPropertyInfo().GetCustomAttributes(typeof(RequiredAttribute), false).Cast<RequiredAttribute>().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
/// <summary>
/// 定义处理excel为单个字段的委托
/// </summary>
/// <param name="excelValue">excel中的值</param>
/// <param name="excelTemplate">excel中的值</param>
/// <param name="entityValue">实体的值</param>
/// <param name="errorMsg">错误消息,没有错误为空</param>
public delegate void CopySingleData(object excelValue, BaseTemplateVM excelTemplate, out string entityValue, out string errorMsg);
/// <summary>
/// 定义处理excel为多个字段的委托
/// </summary>
/// <param name="excelValue">excel中的值</param>
/// <param name="excelTemplate">excel中的值</param>
/// <returns>返回的处理结果</returns>
public delegate ProcessResult CopyData(object excelValue, BaseTemplateVM excelTemplate);
/// <summary>
/// 处理结果
/// </summary>
public class ProcessResult
{
public List<EntityValue> EntityValues { get; set; }
public ProcessResult()
{
EntityValues = new List<EntityValue>();
}
}
/// <summary>
/// 单字段类
/// </summary>
public class EntityValue
{
/// <summary>
/// 字段名称
/// </summary>
public string FieldName { get; set; }
/// <summary>
/// 字段值
/// </summary>
public string FieldValue { get; set; }
/// <summary>
/// 错误消息
/// </summary>
public string ErrorMsg { get; set; }
}
public enum ColumnDataType { Text, Number, Date, Float, Bool, ComboBox, Enum, Dynamic, DateTime }
#endregion
}