using CsvHelper; using CsvHelper.Configuration; using CsvHelper.TypeConversion; namespace YLErp.Helpers { /// /// csv值转换器 /// static class CsvTypeConverts { /// /// 文本转换器(自带trim功能) /// 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); } } /// /// 日期转换器 /// 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); } } /// /// 数字转换器 /// 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); } } /// /// 百分比转换器 /// 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); } } /// /// 短整数转换器 /// 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); } } /// /// 短整数转换器 /// 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 : 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(); } } } /// /// CSV文件读取验证器 /// interface ICsvReaderValidator { bool Validate(string text, out string errorMessage); } /// /// CSV cell值必需验证 /// 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(); } } }