using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.ComponentModel;
using Microsoft.AspNetCore.Http;
namespace Estsh.Core.Util
{
///
/// 和 model displayName 一起使用
/// 导入时只需要核对 列头与displayName值是否一致
///
public class ExcelHelper
{
///
/// 第一步
/// 上传Excel 并返回上传路径
///
///
/// 文件夹名称
///
/// 返回路径
///
private static string DepositExcel(IFormFile file, string directoryName)
{
//创建需要存放的位置 返回一个准确的路径
var path = CreateDirectory("Upload/Excels/" + directoryName);
//文件名
string fileName = DateTime.Now.Ticks.ToString() + "." + file.FileName.Split('.').Last();
path = path + "/" + fileName;
if (File.Exists(path))
{
File.Delete(path);
}
using (var stream = new FileStream(path, FileMode.CreateNew))
{
file.CopyTo(stream);
}
return path;
}
///
/// 第二步
/// 得到Excel 内容
///
///
///
private static ISheet GetSheet(string path)
{
ISheet sheet;
using (var file = new FileStream(path, FileMode.Open, FileAccess.Read))
{
MemoryStream ms = new MemoryStream();
if (Path.GetExtension(path) == ".xls")
{
HSSFWorkbook workbook = new HSSFWorkbook(file);
//获取一个sheetName
sheet = workbook.GetSheetAt(0);
}
else
{
XSSFWorkbook workbook = new XSSFWorkbook(file);
//获取一个sheetName
sheet = workbook.GetSheetAt(0);
}
}
return sheet;
}
///
/// 第三步
/// 根据Excel 内容得到想要的List
///
///
///
///
///
private static List GetList(ISheet sheet, int headNum)
{
List list = new List();
Dictionary dict = new Dictionary();
//获得列名所对应的字段名
var propertys = GetPropertyByType(false);
//得到每个字段对应的序号
IRow head = sheet.GetRow(headNum);
for (int i = 0; i < head.LastCellNum; i++)
{
ICell cell = head.GetCell(i);
if (propertys.ContainsKey(cell.StringCellValue.Trim()))
{
dict.Add(i, propertys[cell.StringCellValue.Trim()]);
}
}
if (dict.Count != head.LastCellNum)
{
throw new Exception("Import tables head and requirements inconsistency");
}
var type = typeof(T).GetProperties();
int c = 0;
try
{
for (int i = headNum + 1; i <= sheet.LastRowNum; i++)
{
c = i;
IRow row = sheet.GetRow(i);
if (row != null)
{
bool isAddList = true;
T t = Activator.CreateInstance();
for (int j = 0; j < row.LastCellNum; j++)
{
ICell cell = row.GetCell(j);
string name = "";
dict.TryGetValue(j, out name);
if (cell != null)
{
if (cell.CellType == CellType.Blank)//空值
{
isAddList = IsAdd(name, true);
}
else
{
var item = type.FirstOrDefault(m => m.Name == name);
if (item != null)
{
if (item.PropertyType == typeof(DateTime))
{
try
{
if (cell.CellType == CellType.String)
{
var value = Convert.ToDateTime(cell.ToString());
item.SetValue(t, value);
}
else
{
item.SetValue(t, cell.DateCellValue);
}
}
catch
{
throw new Exception($"DateTime{cell.ToString()}格式不正确!");
}
}
else if (item.PropertyType == typeof(int))
{
try
{
item.SetValue(t, Convert.ToInt32(cell.ToString()));
}
catch
{
throw new Exception($"int{cell.ToString()}格式不正确!");
}
}
else if (item.PropertyType == typeof(string))
{
if (cell.CellType == CellType.String)
{
item.SetValue(t, cell.ToString() == null ? "" : cell.ToString().Trim());
isAddList = IsAdd(name, string.IsNullOrEmpty(cell.ToString()));
}
else
{
item.SetValue(t, cell.NumericCellValue.ToString());
}
}
else if (item.PropertyType == typeof(decimal?) || item.PropertyType == typeof(decimal))
{
if (cell != null)
{
try
{
var value = 0m;
if (cell.CellType == CellType.String)
{
value = Convert.ToDecimal(cell == null ? "0" : cell.ToString());
}
else
{
value = Convert.ToDecimal(cell.NumericCellValue);
}
item.SetValue(t, value);
isAddList = IsAdd(name, value == 0);
}
catch
{
throw new Exception($"decimal{cell.ToString()}格式不正确!");
}
}
}
}
}
if (isAddList == false)
{
break;
}
}
}
if (isAddList)
{
list.Add(t);
}
}
}
}
catch (Exception e)
{
throw e;
}
return list;
}
private static bool IsAdd(string name, bool isOk)
{
bool result = true;
string[] isNotStrs = { };
if (isNotStrs.Contains(name) && isOk)
{
result = false;
}
return result;
}
#region 辅助方法
///
/// 创建目录
///
/// 目录路径
private static string CreateDirectory(string directoryPath = "")
{
var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Content");
if (!string.IsNullOrEmpty(directoryPath))
{
if (directoryPath.Substring(0, 1) != "/")
{
directoryPath = "/" + directoryPath;
}
path += directoryPath;
}
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
///
/// 获得Excel列名
///
private static Dictionary GetPropertyByType(bool isToExcel)
{
Dictionary dict = new Dictionary();
var type = typeof(In);
try
{
foreach (var item in type.GetProperties())
{
var displayName = item.GetCustomAttribute();
if (displayName != null)
{
if (isToExcel)
{
dict.Add(item.Name, displayName.DisplayName);
}
else
{
dict.Add(displayName.DisplayName, item.Name);
}
}
}
}
catch (Exception e)
{
throw e;
}
return dict;
}
#endregion
///
/// 功能,
/// 导入Excel
/// 列头名和实体的DispName 要一致。
///
/// 要转换的实体
/// 上传的Excel文件
/// Excel头部行数
///
/// 获得转换后的List 集合
///
public static List GetList(IFormFile files, int headNum)
{
List list = new List();
string path = DepositExcel(files, typeof(T).Name);
//得到上传文件内容
ISheet sheet = GetSheet(path);
//转换成List
var t = GetList(sheet, headNum);
if (t != null && t.Count > 0)
{
list.AddRange(t);
}
return list;
}
///
/// 生成Excel流数据,
/// return File(memoryStream.ToArray(), "application/vnd.ms-excel", fileName); //vnd.ms 此模式有些不兼容
/// 或者
/// return File(memoryStream.ToArray(), "application/ms-excel", "红包列表.xls")
///
/// 数据模型
/// excel扩展名类型
/// 数据集
/// Excel的单个Sheet的行数,不能超过65535,否则会抛出异常
///
public static MemoryStream ToExcel(List data, string excelType = "xls", int sheetSize = 50000)
{
IWorkbook wk;
if (excelType == "xlsx")
{
wk = new XSSFWorkbook();
}
else
{
wk = new HSSFWorkbook();
}
var itemType = Activator.CreateInstance().GetType();
int baseNum = 65535;//单个Sheet最大行数65535
int cNum = data.Count / baseNum;
int myForCount = data.Count % baseNum == 0 ? cNum : cNum + 1;
for (int i = 0; i < myForCount; i++)
{
var list = data.Skip(i * baseNum).Take(baseNum).ToList();
string sheetName = "sheet" + i + 1;
CreateSheet(wk, list, itemType, sheetName);
}
if (myForCount == 0)
{
var list = data.Skip(1 * baseNum).Take(baseNum).ToList();
string sheetName = "sheet" + 1;
var headers = GetPropertyByType(true);
ISheet sheet = CreateHeaders(wk, headers, sheetName);
}
MemoryStream m = new MemoryStream();
wk.Write(m);
return m;
}
///
/// 创建并得到一个 sheet
///
///
///
///
///
///
///
///
///
private static void CreateSheet(IWorkbook wk, List data, Type itemType, string sheetName, int sheetSize = 50000)
{
try
{
ISheet sheet = null;
var headers = GetPropertyByType(true);
sheet = CreateHeaders(wk, headers, sheetName);
if (data.Count > 0)
{
for (var i = 0; i < data.Count; i++)
{
//创建内容
IRow row = sheet.CreateRow(i % sheetSize + 1);
//遍历填充每条数据
int j = 0;
foreach (var item in headers)
{
var p = itemType.GetProperty(item.Key);//获取对应列名
if (p != null)
{
var value = p.GetValue(data[i]);
value = value == null ? string.Empty : value;
ICell cell = row.CreateCell(j);
cell.SetCellValue(value.ToString().Trim());
}
j++;
}
}
}
}
catch (Exception ex)
{
throw ex;
}
}
///
/// 创建sheet 表头
///
/// workbook
/// 表头
///
///
/// 返回一个sheet
///
private static ISheet CreateHeaders(IWorkbook wk, Dictionary headers, string sheetName)
{
var sheet = wk.CreateSheet(sheetName);
IRow rowHead = sheet.CreateRow(0);
ICellStyle style = wk.CreateCellStyle();
IFont font = wk.CreateFont();//创建字体样式
font.Boldweight = (short)FontBoldWeight.Bold;
style.SetFont(font);
int i = 0;
foreach (var item in headers)
{
ICell cellHead = rowHead.CreateCell(i);
cellHead.SetCellValue(item.Value);
cellHead.CellStyle = style;
i++;
}
return sheet;
}
}
}