Files
“wanyongkang” ed3b2c653e 接口文件
2024-04-10 13:55:27 +08:00

644 lines
24 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<Stream> 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();
}
}
/// <summary>
/// excel二进制文件转二维string结合
/// </summary>
/// <param name="stream"></param>
/// <param name="st"></param>
/// <returns></returns>
public static List<List<string>> 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<List<string>> lis1 = new List<List<string>>();
{
//获取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<string> lis = new List<string>();
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;
}
/// <summary>
/// 导出列表到excel
/// 导出到sheet的数据一致
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="excelData">每一个sheet的数据</param>
/// <param name="excelTitle">列表的属性和名称值</param>
/// <returns></returns>
public static byte[] ExportListToExcel<T>(List<ExcelData<T>> excelData, List<ExcelTitle> 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<T>(ExcelData<T> excelData, List<ExcelTitle> 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;
}
}
/// <summary>
/// 创建excel表单数据
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="workbook"></param>
/// <param name="excelData"></param>
/// <param name="excelTitle"></param>
/// <param name="entityProperties"></param>
private static void CreateSheetData<T>(NPOI.XSSF.UserModel.XSSFWorkbook workbook,
ExcelData<T> excelData, List<ExcelTitle> 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()
/// <summary>
/// 下载
/// </summary>
/// <param name="stream">流</param>
/// <param name="fileName">文件名,包含扩展名</param>
public static async Task DownloadAsync(this ControllerBase controllerBase, Stream stream, string fileName)
{
await DownloadAsync(controllerBase,stream, fileName, Encoding.UTF8);
}
/// <summary>
/// 下载
/// </summary>
/// <param name="stream">流</param>
/// <param name="fileName">文件名,包含扩展名</param>
/// <param name="encoding">字符编码</param>
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);
}
/// <summary>
/// 下载
/// </summary>
/// <param name="bytes">字节流</param>
/// <param name="fileName">文件名,包含扩展名</param>
public static async Task DownloadAsync(this ControllerBase controllerBase, byte[] bytes, string fileName)
{
await DownloadAsync(controllerBase,bytes, fileName, Encoding.UTF8);
}
/// <summary>
/// 下载
/// </summary>
/// <param name="bytes">字节流</param>
/// <param name="fileName">文件名,包含扩展名</param>
/// <param name="encoding">字符编码</param>
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
{
/// <summary>
/// 导出数据对应的 属性字段名
/// </summary>
public string Property { get; set; }
/// <summary>
/// excel 的title
/// </summary>
public string Title { get; set; }
public Func<object, object> Format { get; set; }
public Func<object, object> Expr { get; set; }
}
public class ExcelData<T>
{
/// <summary>
/// 导出数据对应的 属性字段名
/// </summary>
public string SheetName { get; set; }
/// <summary>
/// excel 的title
/// </summary>
public List<T> Data { get; set; }
}
#region Excel导入验证
/// <summary>
/// Excel导入验证
/// </summary>
public static class ValidForExcel
{
/// <summary>
/// 解析字符串到int32、double、datetime...
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <param name="rowNo"></param>
/// <param name="message"></param>
/// <param name="isCanNullOrEmpty"></param>
/// <param name="isPositiveOrZero">自然数0,1,2,3...</param>
/// <returns></returns>
public static T ValidParseStr<T>(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}的值有误");
}
/// <summary>
/// 提供正则、提示信息,返回验证结果
/// </summary>
/// <param name="str"></param>
/// <param name="rowNo"></param>
/// <param name="pattern"></param>
/// <param name="message"></param>
/// <param name="isCanNullOrEmpty"></param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 根据枚举判断
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="str"></param>
/// <param name="message"></param>
/// <param name="isCanNullOrEmpty"></param>
/// <returns></returns>
public static int? ValidByEnum<T>(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<T>().Find(s => s.Name == str)?.Value;
if (value == null) throw new BusinessException($"未知的数据:{str}");
return Convert.ToInt32(value);
}
}
}
#endregion
}