using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; using System.Web; using AngleSharp; using AngleSharp.Dom; using Hncore.Infrastructure.Data; using Hncore.Infrastructure.Extension; using Microsoft.AspNetCore.Mvc; using NPOI.HSSF.UserModel; namespace Hncore.Infrastructure.Common { public static class ExcelHelper { public static async Task GetStreamFromHtml(string html) { MemoryStream ms = new MemoryStream(); HSSFWorkbook book = new HSSFWorkbook(); var context = BrowsingContext.New(Configuration.Default); var document = await context.OpenAsync(req => req.Content(html)); try { var tables = document.GetElementsByTagName("table"); foreach (var table in tables) { var sheetName = table.GetAttribute("sheetname"); var sheet = book.CreateSheet(sheetName); var trs = table.GetElementsByTagName("tr"); var rowIndex = 0; foreach (var tr in trs) { var row = sheet.CreateRow(rowIndex); var tds = tr.GetElementsByTagName("td"); var columnIndex = 0; foreach (var td in tds) { row.CreateCell(columnIndex).SetCellValue(td.InnerHtml.Trim()); columnIndex++; } rowIndex++; } } book.Write(ms); ms.Position = 0; } finally { document.Close(); document.Dispose(); context.Active.Close(); context.Active.Dispose(); document = null; context = null; book.Clear(); book.Close(); book = null; } return ms; } public static async Task ResponseExcelFromHtml(this ControllerBase controllerBase, string fileName, string html) { using (var ms = await GetStreamFromHtml(html)) { var bytes = ms.StreamToBytes(); var response = controllerBase.HttpContext.Response; response.ContentType = "application/octet-stream"; response.Headers.Add("Content-Disposition", $"attachment; filename={fileName.UrlEncode()}"); response.Headers.Add("X-Suggested-Filename", fileName.UrlEncode()); response.Headers.Add("Content-Length", bytes.Length.ToString()); await response.Body.WriteAsync(bytes, 0, bytes.Length); await response.Body.FlushAsync(); } } /// /// excel二进制文件转二维string结合 /// /// /// /// public static List> ReadFromStream(Stream stream, int st = 0) { //根据路径通过已存在的excel来创建HSSFWorkbook,即整个excel文档 HSSFWorkbook workbook; try { workbook = new HSSFWorkbook(stream); } catch (Exception ex) { LogHelper.Error("ReadFromStream",ex); throw new BusinessException("文件读取错误!"); } List> lis1 = new List>(); { //获取excel的第一个sheet var sheet = workbook.GetSheetAt(st); if (sheet == null) throw new BusinessException("该文件内没有包含任何工作簿"); //获取sheet的首行 var headerRow = sheet.GetRow(0); //一行最后一个方格的编号 即总的列数 int cellCount = headerRow.LastCellNum; try { for (int i = 0; i <= sheet.LastRowNum; i++) { List lis = new List(); var row = sheet.GetRow(i); if (row == null) continue; for (int j = 0; j < cellCount; j++) { var cell = row.GetCell(j); if (cell == null) { lis.Add(""); continue; } try { switch (cell.CellType) { case NPOI.SS.UserModel.CellType.Unknown: lis.Add("Unknown"); break; case NPOI.SS.UserModel.CellType.Numeric: if (HSSFDateUtil.IsCellDateFormatted(cell))//对日期格式进行特殊对待 lis.Add(HSSFDateUtil.GetJavaDate(cell.NumericCellValue).ToString()); else lis.Add(cell.NumericCellValue.ToString()); break; case NPOI.SS.UserModel.CellType.String: lis.Add(cell.StringCellValue.ToString()); break; case NPOI.SS.UserModel.CellType.Formula: lis.Add(cell.CellFormula.ToString()); break; case NPOI.SS.UserModel.CellType.Blank: lis.Add(""); break; case NPOI.SS.UserModel.CellType.Boolean: lis.Add(cell.BooleanCellValue.ToString()); break; case NPOI.SS.UserModel.CellType.Error: lis.Add(cell.ErrorCellValue.ToString()); break; default: break; } } catch { lis.Add(""); } } //如果本行所有单元格都是空,就跳过本行 if (lis.All(item => string.IsNullOrEmpty(item))) continue; lis1.Add(lis); } } catch(Exception ex) { LogHelper.Error("ReadFromStream", ex); throw new BusinessException("文件格式错误!"); } } #region 细节化处理 lis1 = lis1.Where(s => !s.TrueForAll(f => string.IsNullOrWhiteSpace(f))).ToList();//去除全是空格的空行。 lis1 = lis1.Select(s => s = s.Select(y => y = y.Trim()).ToList()).ToList();//去除空格 if (lis1.Count == 1) throw new Exception("Excel中无有效数据!"); #endregion return lis1; } /// /// 导出列表到excel /// 导出到sheet的数据一致 /// /// /// 每一个sheet的数据 /// 列表的属性和名称值 /// public static byte[] ExportListToExcel(List> excelData, List excelTitle) { var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook(); var entityType = typeof(T); PropertyInfo[] entityProperties = entityType.GetProperties(); if (excelData == null || excelData.Count == 0) { return null; } try { foreach (var item in excelData) { #region MyRegion //var sheet = workbook.CreateSheet(item.SheetName.Replace('/','-')); //var titleRow = sheet.CreateRow(0); //for (int i = 0; i < excelTitle.Count; i++) //{ // titleRow.CreateCell(i).SetCellValue(excelTitle[i].Title); //} //var sheetData = item.Data; //for (int j = 0; j < sheetData.Count; j++) //{ // var dataRow = sheet.CreateRow(j + 1); // for (int i = 0; i < excelTitle.Count; i++) // { // if (excelTitle[i].Property.ToUpper().Equals("ID")) // { // var num = j + 1; // dataRow.CreateCell(i).SetCellValue(num); // continue; // } // var entityProperty = entityProperties.FirstOrDefault(m => m.Name == excelTitle[i].Property); // var cellVal = entityProperty?.GetValue(sheetData[j]); // if (cellVal?.GetType().Name == "DateTime") // { // dataRow.CreateCell(i).SetCellValue(((DateTime?)cellVal)?.ToString("yyyy/MM/dd HH:mm:ss")); // } // else // { // dataRow.CreateCell(i).SetCellValue(cellVal?.ToString()); // } // //dataRow.CreateCell(i).SetCellValue(cellVal?.ToString()); // } //} #endregion CreateSheetData(workbook, item, excelTitle, entityProperties); } using (var ms = new MemoryStream()) { workbook.Write(ms); var bytes = ms.ToArray(); return bytes; } } catch(Exception ex) { LogHelper.Error("ExportListToExcel=>" + ex); throw ex; } finally { workbook.Clear(); workbook.Close(); workbook = null; } } public static byte[] ExportListToExcel(ExcelData excelData, List excelTitle) { var workbook = new NPOI.XSSF.UserModel.XSSFWorkbook(); var entityType = typeof(T); PropertyInfo[] entityProperties = entityType.GetProperties(); try { #region MyRegion //var sheet = workbook.CreateSheet(excelData.SheetName.Replace('/', '-')); //var titleRow = sheet.CreateRow(0); //for (int i = 0; i < excelTitle.Count; i++) //{ // titleRow.CreateCell(i).SetCellValue(excelTitle[i].Title); //} //var sheetData = excelData.Data; //for (int j = 0; j < sheetData.Count; j++) //{ // var dataRow = sheet.CreateRow(j + 1); // for (int i = 0; i < excelTitle.Count; i++) // { // var cellVal = entityProperties.FirstOrDefault(m => m.Name == excelTitle[i].Property)?.GetValue(sheetData[j]); // if (cellVal?.GetType().Name == "DateTime") // { // dataRow.CreateCell(i).SetCellValue(((DateTime?)cellVal)?.ToString("yyyy/MM/dd HH:mm:ss")); // } // else // { // dataRow.CreateCell(i).SetCellValue(cellVal?.ToString()); // } // } //} #endregion CreateSheetData(workbook, excelData, excelTitle, entityProperties); using (var ms = new MemoryStream()) { workbook.Write(ms); var bytes = ms.ToArray(); return bytes; } } catch (Exception ex) { LogHelper.Error("ExportListToExcel=>" + ex); throw ex; } finally { workbook.Clear(); workbook.Close(); workbook = null; } } /// /// 创建excel表单数据 /// /// /// /// /// /// private static void CreateSheetData(NPOI.XSSF.UserModel.XSSFWorkbook workbook, ExcelData excelData, List excelTitle,PropertyInfo[] entityProperties) { var sheet = workbook.CreateSheet(excelData.SheetName.Replace('/', '-')); var titleRow = sheet.CreateRow(0); for (int i = 0; i < excelTitle.Count; i++) { titleRow.CreateCell(i).SetCellValue(excelTitle[i].Title); } var sheetData = excelData.Data; for (int j = 0; j < sheetData.Count; j++) { var dataRow = sheet.CreateRow(j + 1); for (int i = 0; i < excelTitle.Count; i++) { var currentTitle = excelTitle[i]; if (currentTitle.Property.Equals("序号")) { var num = j + 1; dataRow.CreateCell(i).SetCellValue(num); continue; } var cellVal = entityProperties.FirstOrDefault(m => m.Name == currentTitle.Property)?.GetValue(sheetData[j]); if (currentTitle.Format != null) { cellVal = currentTitle.Format(cellVal); } if (currentTitle.Expr != null) { cellVal = currentTitle.Expr(sheetData[j]); } else if (cellVal?.GetType().Name == "DateTime") { dataRow.CreateCell(i).SetCellValue(((DateTime?)cellVal)?.ToString("yyyy/MM/dd HH:mm:ss")); } dataRow.CreateCell(i).SetCellValue(cellVal?.ToString()); } } } #region DownloadAsync(下载) /// /// 下载 /// /// 流 /// 文件名,包含扩展名 public static async Task DownloadAsync(this ControllerBase controllerBase, Stream stream, string fileName) { await DownloadAsync(controllerBase,stream, fileName, Encoding.UTF8); } /// /// 下载 /// /// 流 /// 文件名,包含扩展名 /// 字符编码 public static async Task DownloadAsync(this ControllerBase controllerBase, Stream stream, string fileName, Encoding encoding) { stream.Seek(0, SeekOrigin.Begin); var buffer = new byte[stream.Length]; stream.Read(buffer, 0, buffer.Length); await DownloadAsync(controllerBase, buffer, fileName, encoding); } /// /// 下载 /// /// 字节流 /// 文件名,包含扩展名 public static async Task DownloadAsync(this ControllerBase controllerBase, byte[] bytes, string fileName) { await DownloadAsync(controllerBase,bytes, fileName, Encoding.UTF8); } /// /// 下载 /// /// 字节流 /// 文件名,包含扩展名 /// 字符编码 public static async Task DownloadAsync(this ControllerBase controllerBase,byte[] bytes, string fileName, Encoding encoding) { var response = controllerBase.HttpContext.Response; if (bytes == null || bytes.Length == 0) return; fileName = fileName.Replace(" ", ""); fileName = HttpUtility.UrlEncode(fileName, encoding); response.ContentType = "application/octet-stream"; response.Headers.Add("Content-Disposition", $"attachment; filename={fileName}"); response.Headers.Add("Content-Length", bytes.Length.ToString()); response.Headers.Add("X-Suggested-Filename", fileName); await response.Body.WriteAsync(bytes, 0, bytes.Length); await response.Body.FlushAsync(); } #endregion } public class ExcelTitle { /// /// 导出数据对应的 属性字段名 /// public string Property { get; set; } /// /// excel 的title /// public string Title { get; set; } public Func Format { get; set; } public Func Expr { get; set; } } public class ExcelData { /// /// 导出数据对应的 属性字段名 /// public string SheetName { get; set; } /// /// excel 的title /// public List Data { get; set; } } #region Excel导入验证 /// /// Excel导入验证 /// public static class ValidForExcel { /// /// 解析字符串到int32、double、datetime... /// /// /// /// /// /// /// 自然数0,1,2,3... /// public static T ValidParseStr(string str,string message = "数据", bool isCanNullOrEmpty = true, bool isPositiveOrZero = true) { var val = default(T); if (string.IsNullOrEmpty(str)) { if (isCanNullOrEmpty) { return default(T); } else { throw new Exception($"{message}不能为空"); } } else { if (typeof(T).Name == typeof(int).Name || typeof(T).FullName == typeof(int?).FullName) { if (int.TryParse(str, out var valueInt)) { if (isPositiveOrZero && valueInt < 0) { goto error; } return (T)Convert.ChangeType(valueInt, TypeCode.Int32); } else { goto error; } } if (typeof(T).Name == typeof(Decimal).Name || typeof(T).FullName == typeof(Decimal?).FullName) { if (Decimal.TryParse(str, out var valueInt)) { if (isPositiveOrZero && valueInt < 0) { goto error; } return (T)Convert.ChangeType(valueInt, TypeCode.Decimal); } else { goto error; } } if (typeof(T).Name == typeof(Double).Name || typeof(T).FullName == typeof(Double?).FullName) { if (Double.TryParse(str, out var valueInt)) { if (isPositiveOrZero && valueInt < 0) { goto error; } return (T)Convert.ChangeType(valueInt, TypeCode.Double); } else { goto error; } } if (typeof(T).Name == typeof(Single).Name || typeof(T).FullName == typeof(Single?).FullName) { if (Single.TryParse(str, out var valueInt)) { if (isPositiveOrZero && valueInt < 0) { goto error; } return (T)Convert.ChangeType(valueInt, TypeCode.Single); } else { goto error; } } if (typeof(T).Name == typeof(DateTime).Name || typeof(T).FullName == typeof(DateTime?).FullName) { if (DateTime.TryParse(str, out var valueInt)) { return (T)Convert.ChangeType(valueInt, TypeCode.DateTime); } else { goto error; } } } return val; error: throw new Exception($"{message}的值有误"); } /// /// 提供正则、提示信息,返回验证结果 /// /// /// /// /// /// /// public static string ValidByPattern(string str,string pattern, string message = "数据", bool isCanNullOrEmpty = true) { if (string.IsNullOrEmpty(str)) { if (isCanNullOrEmpty) { return str; } else { throw new BusinessException($"{message}不能为空"); } } else { if (!Regex.IsMatch(str, pattern)) throw new BusinessException($"{message}输入有误"); return str; } } /// /// 根据枚举判断 /// /// /// /// /// /// public static int? ValidByEnum(string str, string message, bool isCanNullOrEmpty = true) //where T:Enum { if (string.IsNullOrEmpty(str)) { if (isCanNullOrEmpty) { return null; } else { throw new BusinessException($"{message}不能为空"); } } else { var value = EnumExtension.EnumToList().Find(s => s.Name == str)?.Value; if (value == null) throw new BusinessException($"未知的数据:{str}"); return Convert.ToInt32(value); } } } #endregion }