using CsvHelper;
using CsvHelper.Configuration;
using NPOI.SS.UserModel;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
namespace XYY.Core.Standard.ExcelHelper
{
public class OPNPOIRow
{
public OPNPOIRow(IRow row)
{
Row = row;
}
public IRow Row
{
get;
}
public OPNPOIRow Cell(string value)
{
ICell cell = Row.CreateCell(Row.Cells.Count);
LastCell = cell;
cell.SetCellValue(value);
return this;
}
public ICell LastCell { get; set; }
public byte[] WBToByte(IWorkbook wb)
{
NpoiMemoryStream ms = new NpoiMemoryStream
{
AllowClose = false
};
wb.Write(ms);
byte[] data = new byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(data, 0, data.Length);
ms.AllowClose = true;
return data;
}
}
///
/// NPOI Row与对象间的转换处理
///
/// 处理对象
public class OPNPOIRow : OPNPOIRow
where T : class, new()
{
public OPNPOIRow(T model, IRow row) : base(row)
{
Model = model;
CellExpressions = new List();
}
public T Model
{
get;
}
public List CellExpressions
{
get; set;
}
///
/// NPOIExcel列反序列化对象
///
public void Deserialize()
{
int emptyCellCount = 0;
IRow topRow = Row.Sheet.GetRow(0);
for (int i = 0; i < topRow.LastCellNum; i++)
{
ICell topCell = topRow.GetCell(i);
if (topCell != null && topCell.CellType == CellType.String)
{
string name = topCell.StringCellValue;
ICell cell = Row.GetCell(i);
if (cell == null || cell.CellType == CellType.Blank)
emptyCellCount++;
if (emptyCellCount == topRow.LastCellNum)
{
//全部空记录时直接返回
break;
}
//过滤空行
if (cell != null && cell.CellType != CellType.Blank)
{
if (topCell.CellComment == null)
{
SetPropertyVal(cell, name, Model);
}
else
{
//根据注解的序号生成List并进行实体与属性填充
string[] propertyConfig = topCell.CellComment.String.String.Split('-');
string pName = propertyConfig[0];
int index = int.Parse(propertyConfig[1]);
PropertyInfo p = typeof(T).GetProperty(pName);
Type type = typeof(List<>);
//目前仅解析List数组
if (p.PropertyType.GetGenericTypeDefinition() == type)
{
object list = null;
object pModel = null;
int count = 0;
if (p.GetValue(Model, null) == null)
{
//实例化所有组员
list = Activator.CreateInstance(p.PropertyType);
p.SetValue(Model, list);
}
else
{
list = p.GetValue(Model, null);
}
count = (int)(list.GetType().GetProperty("Count").GetValue(list));
if (count < index)
{
MethodInfo method = p.PropertyType.GetMethod("Add");
pModel = Activator.CreateInstance(p.PropertyType.GenericTypeArguments[0]);
method.Invoke(list, new object[] { pModel });
}
else
{
MethodInfo method = p.PropertyType.GetMethod("get_Item");
pModel = method.Invoke(list, new object[] { index - 1 });
}
Type pModelType = pModel.GetType();
string pModelPropertyName = name;
SetPropertyVal(cell, name.Split('-')[0], pModel);
}
}
}
}
}
}
///
/// NPOI 数据转换为C#类上的属性
///
/// 数据
/// 需赋值的列的DisplayName
/// 需赋值的实体
private void SetPropertyVal(ICell cell, string name, object model)
{
//根据DisplayName查找相关的属性
PropertyInfo p = model.GetType().GetProperties().Where(x =>
{
DisplayNameAttribute attr = x.GetCustomAttribute(typeof(DisplayNameAttribute)) as DisplayNameAttribute;
if (attr != null)
{
return (attr.DisplayName == name);
}
else
{
return false;
}
}).FirstOrDefault();
//类型转换
if (p != null)
{
if (p.PropertyType == typeof(string))
{
if (cell.CellType == CellType.Numeric)
{
p.SetValue(model, cell.NumericCellValue.ToString(), null);
}
else
{
if (cell.StringCellValue.Contains("("))
{
p.SetValue(model, cell.StringCellValue.TrimEnd(')').Split('(')[1], null);
}
else
{
p.SetValue(model, cell.StringCellValue, null);
}
}
}
else if (p.PropertyType == typeof(int) || p.PropertyType == typeof(decimal) || p.PropertyType == typeof(float) || p.PropertyType == typeof(Enum))
{
if (cell.CellType == CellType.String)
{
if (cell.StringCellValue.Split('-').Length > 1)
{
p.SetValue(model, int.Parse(cell.StringCellValue.Split('-')[1]), null);
}
}
else
{
if (p.PropertyType == typeof(int))
{
p.SetValue(model, (int)cell.NumericCellValue, null);
}
else if (p.PropertyType == typeof(decimal))
{
p.SetValue(model, (decimal)cell.NumericCellValue, null);
}
}
}
else if (p.PropertyType == typeof(DateTime))
{
p.SetValue(model, cell.DateCellValue, null);
}
else if (p.PropertyType == typeof(Nullable))
{
p.SetValue(model, cell.DateCellValue, null);
}
else if (p.PropertyType == typeof(bool))
{
p.SetValue(model, cell.BooleanCellValue, null);
}
else
{
p.SetValue(model, cell.StringCellValue, null);
}
}
else
{
return;
}
}
public void Serialize()
{
Serialize(Model, Row);
}
List refData = new List();
public void MSSerialize(T t, IRow row)
{
refData.Add(t);
}
public void CSVSerialize(T t, IRow row)
{
refData.Add(t);
}
public byte[] ToMSExcel()
{
var customerMap = new MSExcelDefaultMapping();
foreach (LambdaExpression expression in CellExpressions)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
IList displayNameAttr =
propertyInfo.CustomAttributes.Where(x => x.AttributeType == typeof(DisplayNameAttribute)).Select(x => x.ConstructorArguments).FirstOrDefault();
var m = customerMap.Map(memberExpression.Member);
if (displayNameAttr != null)
{
m.Name(displayNameAttr[0].Value as string);
}
else
{
m.Name(propertyInfo.Name);
}
}
if (!System.IO.Directory.Exists(tempPath))
System.IO.Directory.CreateDirectory(tempPath);
var msHelper = new MSExcelHelper.MSExcelHelper();
return msHelper.OutDataAsByte(refData, customerMap);
}
readonly string tempPath = AppContext.BaseDirectory + "\\temp";
public byte[] ToCsv()
{
var customerMap = new DefaultClassMap();
foreach (LambdaExpression expression in CellExpressions)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
IList displayNameAttr =
propertyInfo.CustomAttributes.Where(x => x.AttributeType == typeof(DisplayNameAttribute)).Select(x => x.ConstructorArguments).FirstOrDefault();
var m = customerMap.Map(typeof(T), memberExpression.Member);
if (displayNameAttr != null)
{
m.Name(displayNameAttr[0].Value as string);
}
else
{
m.Name(propertyInfo.Name);
}
}
if (!System.IO.Directory.Exists(tempPath))
System.IO.Directory.CreateDirectory(tempPath);
string filePath = tempPath + "\\" + Guid.NewGuid() + ".csv";
using (var writer = new StreamWriter(filePath, false, Encoding.UTF8))
{
using (var csv = new CsvWriter(writer, System.Globalization.CultureInfo.InvariantCulture))
{
csv.WriteRecords(refData);
}
}
var data = File.ReadAllBytes(filePath);
File.Delete(filePath);
return data;
}
public void Serialize(T t, IRow row)
{
foreach (LambdaExpression expression in CellExpressions)
{
object value = expression.Compile().DynamicInvoke(t);
int cellNum = row.LastCellNum == -1 ? 0 : row.LastCellNum;
if (value != null)
{
if (value.GetType() == typeof(string))
{
ICell cell = row.CreateCell(cellNum);
cell.SetCellValue(value as string);
}
else if (
value.GetType() == typeof(int) ||
value.GetType() == typeof(long) ||
value.GetType() == typeof(uint) ||
value.GetType() == typeof(ulong) ||
value.GetType() == typeof(short) ||
value.GetType() == typeof(sbyte) ||
value.GetType() == typeof(byte) ||
value.GetType() == typeof(ushort) ||
value.GetType() == typeof(decimal) ||
value.GetType() == typeof(float) ||
value.GetType() == typeof(double)
)
{
ICell cell = row.CreateCell(cellNum);
cell.SetCellValue(Convert.ToDouble(value));
}
else if (value.GetType() == typeof(bool))
{
ICell cell = row.CreateCell(cellNum);
cell.SetCellValue(Convert.ToBoolean(value));
}
else if (value.GetType() == typeof(DateTime))
{
ICell cell = row.CreateCell(cellNum);
cell.SetCellValue(Convert.ToDateTime(value));
}
else
{
ICell cell = row.CreateCell(cellNum);
cell.SetCellValue(value as string);
}
}
else
{
ICell cell = row.CreateCell(cellNum, CellType.Blank);
}
}
}
///
/// 获取相关注解区域的最大值(已停用)
///
///
///
private int GetDeserializeListCount(IRow topRow)
{
Regex numberRegex = new Regex("\\d+");
int qty = 0;
for (int i = 0; i < topRow.LastCellNum; i++)
{
ICell cell = topRow.GetCell(i);
if (cell.CellComment != null)
{
Match match = numberRegex.Match(cell.CellComment.String.String);
if (match.Success)
{
int index = int.Parse(match.Value);
if (index > qty)
{
qty = index;
}
}
}
}
return qty;
}
}
///
/// NOPIRow 扩展类
///
public static class OPNPOIRowExpress
{
///
/// 根据表达式生成列头标签(读取相关的DisplayName)
///
///
///
///
///
///
///
public static OPNPOIRow Cell(this OPNPOIRow Row, Expression> expression, string suffix = null) where TModel : class, new()
{
if (expression.Body.NodeType == ExpressionType.MemberAccess)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
IList displayNameAttr = propertyInfo.CustomAttributes.Where(x => x.AttributeType == typeof(DisplayNameAttribute)).Select(x => x.ConstructorArguments).FirstOrDefault();
Row.CellExpressions.Add(expression);
if (displayNameAttr != null)
{
string name = displayNameAttr[0].Value as string;
Row.Cell(name + suffix);
}
else
{
Row.Cell(propertyInfo.Name);
}
return Row;
}
return null;
}
public static OPNPOIRow CellWithName(this OPNPOIRow Row, Expression> expression, string colName) where TModel : class, new()
{
if (expression.Body.NodeType == ExpressionType.MemberAccess)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
PropertyInfo propertyInfo = memberExpression.Member as PropertyInfo;
Row.CellExpressions.Add(expression);
if (!string.IsNullOrEmpty(colName))
{
Row.Cell(colName);
}
else
{
Row.Cell(propertyInfo.Name);
}
return Row;
}
return null;
}
}
public static class WBWriteExpress
{
public static byte[] WriteBytes(this IWorkbook wb)
{
NpoiMemoryStream ms = new NpoiMemoryStream
{
AllowClose = false
};
wb.Write(ms);
byte[] data = new byte[ms.Length];
ms.Seek(0, SeekOrigin.Begin);
ms.Read(data, 0, data.Length);
ms.AllowClose = true;
return data;
}
}
///
/// NOPI流的特殊处理
///
public class NpoiMemoryStream : MemoryStream
{
public NpoiMemoryStream()
{
AllowClose = true;
}
public bool AllowClose { get; set; }
public override void Close()
{
if (AllowClose)
{
base.Close();
}
}
public NpoiMemoryStream(Stream stream) : this()
{
byte[] data = new byte[stream.Length];
stream.Read(data, 0, data.Length);
Write(data, 0, data.Length);
stream.Close();
Seek(0, SeekOrigin.Begin);
}
}
}