426 lines
15 KiB
C#
426 lines
15 KiB
C#
using CsvHelper;
|
||
using CsvHelper.Configuration;
|
||
using CsvHelper.TypeConversion;
|
||
|
||
namespace YLErp.Helpers
|
||
{
|
||
/// <summary>
|
||
/// csv值转换器
|
||
/// </summary>
|
||
static class CsvTypeConverts
|
||
{
|
||
/// <summary>
|
||
/// 文本转换器(自带trim功能)
|
||
/// </summary>
|
||
public class StringConverter : CsvHelper.TypeConversion.StringConverter
|
||
{
|
||
readonly ICsvReaderValidator _readerValidator;
|
||
|
||
public StringConverter(ICsvReaderValidator readValidator = null)
|
||
{
|
||
_readerValidator = readValidator;
|
||
}
|
||
|
||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
if (_readerValidator != null && !_readerValidator.Validate(text, out string errorMsg))
|
||
{
|
||
var line = row.Context.Parser.Row;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:{errorMsg},值:{text}");
|
||
}
|
||
|
||
return text?.Trim();
|
||
}
|
||
|
||
public static readonly StringConverter Required;
|
||
public static readonly StringConverter NoValidator;
|
||
|
||
static StringConverter()
|
||
{
|
||
NoValidator = new StringConverter();
|
||
Required = new StringConverter(CsvRequiredValidator.Default);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 日期转换器
|
||
/// </summary>
|
||
public class DateConverter : CsvHelper.TypeConversion.DateTimeConverter
|
||
{
|
||
readonly ICsvReaderValidator _readerValidator;
|
||
|
||
public DateConverter(ICsvReaderValidator readValidator = null)
|
||
{
|
||
_readerValidator = readValidator;
|
||
}
|
||
|
||
public override string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
|
||
{
|
||
if (value is DateTime dt)
|
||
{
|
||
return dt.ToString("yyyy-MM-dd");
|
||
}
|
||
return base.ConvertToString(value, row, memberMapData);
|
||
}
|
||
|
||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
int line;
|
||
string colName;
|
||
if (_readerValidator != null && !_readerValidator.Validate(text, out string errorMsg))
|
||
{
|
||
line = row.Context.Parser.RawRow;
|
||
colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:{errorMsg},值:{text}");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
return DateTime.MinValue;
|
||
}
|
||
|
||
if (text.Length == 8 && text.All(n => n >= '0' && n <= '9') && DateTime.TryParseExact(text, "yyyyMMdd",
|
||
System.Globalization.CultureInfo.InvariantCulture,
|
||
System.Globalization.DateTimeStyles.None, out DateTime date))
|
||
{
|
||
return date.Date;
|
||
}
|
||
|
||
if (text.Length >= 8 && DateTime.TryParse(text, out date))
|
||
{
|
||
return date.Date;
|
||
}
|
||
|
||
line = row.Context.Parser.RawRow;
|
||
colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',转换为日期失败,值:{text}");
|
||
}
|
||
|
||
public static readonly DateConverter Required;
|
||
public static readonly DateConverter NoValidator;
|
||
|
||
static DateConverter()
|
||
{
|
||
NoValidator = new DateConverter();
|
||
Required = new DateConverter(CsvRequiredValidator.Default);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 数字转换器
|
||
/// </summary>
|
||
public class DoubleConverter : CsvHelper.TypeConversion.DoubleConverter
|
||
{
|
||
readonly ICsvReaderValidator _readerValidator;
|
||
|
||
public DoubleConverter(ICsvReaderValidator readValidator = null)
|
||
{
|
||
_readerValidator = readValidator;
|
||
}
|
||
|
||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
if (_readerValidator != null && !_readerValidator.Validate(text, out string errorMsg))
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:{errorMsg},值:{text}");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
return 0d;
|
||
}
|
||
|
||
if (double.TryParse(text, out double dd))
|
||
{
|
||
return dd;
|
||
}
|
||
else
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',转换为数字失败,值:{text}");
|
||
}
|
||
}
|
||
|
||
public static readonly DoubleConverter Required;
|
||
public static readonly DoubleConverter NoValidator;
|
||
|
||
static DoubleConverter()
|
||
{
|
||
NoValidator = new DoubleConverter();
|
||
Required = new DoubleConverter(CsvRequiredValidator.Default);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 百分比转换器
|
||
/// </summary>
|
||
public class PercentConverter : CsvHelper.TypeConversion.ITypeConverter
|
||
{
|
||
readonly ICsvReaderValidator _readerValidator;
|
||
|
||
public PercentConverter(ICsvReaderValidator readValidator = null)
|
||
{
|
||
_readerValidator = readValidator;
|
||
}
|
||
|
||
public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
if (_readerValidator != null && !_readerValidator.Validate(text, out string errorMsg))
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:{errorMsg},值:{text}");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
return 0d;
|
||
}
|
||
|
||
text = text.Trim();
|
||
|
||
if (!text.EndsWith("%"))
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:值未以'%'结尾,值:{text}");
|
||
}
|
||
|
||
if (double.TryParse(text.TrimEnd('%'), out double dd))
|
||
{
|
||
return dd / 100;
|
||
}
|
||
else
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',转换为数字失败,值:{text}");
|
||
}
|
||
}
|
||
|
||
public string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
|
||
public static readonly PercentConverter Required;
|
||
public static readonly PercentConverter NoValidator;
|
||
|
||
static PercentConverter()
|
||
{
|
||
NoValidator = new PercentConverter();
|
||
Required = new PercentConverter(CsvRequiredValidator.Default);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 短整数转换器
|
||
/// </summary>
|
||
public class Int16Converter : CsvHelper.TypeConversion.Int16Converter
|
||
{
|
||
readonly ICsvReaderValidator _readerValidator;
|
||
|
||
public Int16Converter(ICsvReaderValidator readValidator = null)
|
||
{
|
||
_readerValidator = readValidator;
|
||
}
|
||
|
||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
if (_readerValidator != null && !_readerValidator.Validate(text, out string errorMsg))
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:{errorMsg},值:{text}");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
return (short)0;
|
||
}
|
||
|
||
if (short.TryParse(text, out short dd))
|
||
{
|
||
return dd;
|
||
}
|
||
else
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',转换为整数失败,值:{text}");
|
||
}
|
||
}
|
||
|
||
public static readonly Int16Converter Required;
|
||
public static readonly Int16Converter NoValidator;
|
||
|
||
static Int16Converter()
|
||
{
|
||
NoValidator = new Int16Converter();
|
||
Required = new Int16Converter(CsvRequiredValidator.Default);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 短整数转换器
|
||
/// </summary>
|
||
public class Int32Converter : CsvHelper.TypeConversion.Int32Converter
|
||
{
|
||
readonly ICsvReaderValidator _readerValidator;
|
||
|
||
public Int32Converter(ICsvReaderValidator readValidator = null)
|
||
{
|
||
_readerValidator = readValidator;
|
||
}
|
||
|
||
public override object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
if (_readerValidator != null && !_readerValidator.Validate(text, out string errorMsg))
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',验证失败:{errorMsg},值:{text}");
|
||
}
|
||
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
if (int.TryParse(text, out int dd))
|
||
{
|
||
return dd;
|
||
}
|
||
else
|
||
{
|
||
var line = row.Context.Parser.RawRow;
|
||
var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
throw new ServiceException($"第{line}行,列'{colName}',转换为整数失败,值:{text}");
|
||
}
|
||
}
|
||
|
||
public static readonly Int32Converter Required;
|
||
public static readonly Int32Converter NoValidator;
|
||
|
||
static Int32Converter()
|
||
{
|
||
NoValidator = new Int32Converter();
|
||
Required = new Int32Converter(CsvRequiredValidator.Default);
|
||
}
|
||
}
|
||
|
||
public class BoolTypeConverter : ITypeConverter
|
||
{
|
||
private bool DefaultValue;
|
||
public BoolTypeConverter(bool defaultValue)
|
||
{
|
||
DefaultValue = defaultValue;
|
||
}
|
||
public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
return DefaultValue;
|
||
}
|
||
string[] bStringY = { "是", "Y", "YES", "√" };
|
||
string[] bStringN = { "否", "N", "NO", "×" };
|
||
if (bStringY.Contains(text.ToUpper()))
|
||
{
|
||
return true;
|
||
}
|
||
else if (bStringN.Contains(text.ToUpper()))
|
||
{
|
||
return false;
|
||
}
|
||
else
|
||
{
|
||
return DefaultValue;
|
||
}
|
||
}
|
||
|
||
public string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
}
|
||
|
||
public class EnumTypeConverter<T> : ITypeConverter where T : struct
|
||
{
|
||
private T? _defaultValue;
|
||
private string[] _enumArray;
|
||
private string _colName;
|
||
public EnumTypeConverter(string colName, T? defaultValue = null)
|
||
{
|
||
if (typeof(Enum) != typeof(T).BaseType)
|
||
{
|
||
throw new Exception("类型参数不合法,当前泛型类的类型参数必须为枚举类型");
|
||
}
|
||
|
||
_enumArray = Enum.GetNames(typeof(T));
|
||
_defaultValue = defaultValue;
|
||
_colName = colName;
|
||
}
|
||
public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
|
||
{
|
||
var isEnum = Enum.TryParse(text, out T _type);
|
||
if (isEnum)
|
||
{
|
||
return _type;
|
||
}
|
||
var line = row.Context.Parser.RawRow;
|
||
//var colName = memberMapData.Names[memberMapData.NameIndex];
|
||
|
||
if (_defaultValue == null)
|
||
{
|
||
throw new Exception($"第{line}行,列'{_colName}',验证失败, 值必须在【{string.Join(",", _enumArray)}】之中");
|
||
}
|
||
else
|
||
{
|
||
return _defaultValue;
|
||
}
|
||
}
|
||
|
||
public string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
|
||
{
|
||
throw new NotImplementedException();
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// CSV文件读取验证器
|
||
/// </summary>
|
||
interface ICsvReaderValidator
|
||
{
|
||
bool Validate(string text, out string errorMessage);
|
||
}
|
||
|
||
/// <summary>
|
||
/// CSV cell值必需验证
|
||
/// </summary>
|
||
class CsvRequiredValidator : ICsvReaderValidator
|
||
{
|
||
public bool Validate(string text, out string errorMessage)
|
||
{
|
||
if (string.IsNullOrWhiteSpace(text))
|
||
{
|
||
errorMessage = "值不能为空";
|
||
return false;
|
||
}
|
||
errorMessage = null;
|
||
return true;
|
||
}
|
||
|
||
public static readonly CsvRequiredValidator Default;
|
||
|
||
static CsvRequiredValidator()
|
||
{
|
||
Default = new CsvRequiredValidator();
|
||
}
|
||
}
|
||
}
|