Files
SzmediTools/Szmedi.RvKits/Assists/EPPlusHelpers.cs
2025-09-16 16:06:41 +08:00

455 lines
16 KiB
C#
Raw 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 OfficeOpenXml;
using OfficeOpenXml.Style;
using System;
using System.Data;
using System.Linq;
using System.Reflection;
using Szmedi.Toolkit.Assists;
namespace Szmedi.RvKits.Assists;
public static class EPPlusHelpers //公式计算最后需要调用Calculate()
{
private static PropertyInfo GetPropValue<T>(this T obj, string propName)
{
return obj.GetType().GetProperty(propName);
}
private static object Cast(object value, PropertyConfiguration propertyConfiguration)
{
return value == null
? null
: propertyConfiguration.WriteFormatFunc != null ? propertyConfiguration.WriteFormatFunc(value) : (object)value.ToString().Trim();
}
/// <summary>
/// DataTable导出为Excel
/// </summary>
/// <param name="destFileName"></param>
/// <param name="dt"></param>
public static void DataTableToExcel(DataTable dt, string destFileName)
{
FileInfo fi = new(destFileName);
using ExcelPackage package = new(fi);
try
{
ExcelWorksheet workSheet = package.Workbook.Worksheets.Add(dt.TableName);
workSheet.Cells["A1"].LoadFromDataTable(dt, true);
}
catch (Exception)
{
// ignored
}
finally
{
package.Save();
}
}
/// <summary>
/// 给第一个表中的单元格赋值
/// </summary>
/// <param name="fileName"></param>
/// <param name="rowNum"></param>
/// <param name="columnNum"></param>
/// <param name="value"></param>
public static void EditCellValue(string fileName, int rowNum, int columnNum, string value)
{
FileInfo fi = new(fileName);
using ExcelPackage package = new(fi);
//ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelWorksheet sheet = package.Workbook.Worksheets[0];
//string filename = System.IO.Path.GetFileNameWithoutExtension(fileName);
sheet.Cells[rowNum, columnNum].Value = value;
package.Save();
}
/// <summary>
/// 工作表转换为DataTable,首行为表头
/// </summary>
/// <param name="worksheet">行列索引从1开始</param>
/// <returns></returns>
public static DataTable ExcelSheetToDataTable(ExcelWorksheet worksheet)
{
if (worksheet == null)
{
return null;
}
//获取worksheet的行数
int rows = worksheet.Dimension.End.Row;
//获取worksheet的列数
int cols = worksheet.Dimension.End.Column;
DataTable dt = new(worksheet.Name);
DataRow dr = null;
for (int i = 1; i <= rows; i++)
{
if (i > 1)
{
dr = dt.Rows.Add();
}
for (int j = 1; j <= cols; j++)
{
//默认将第一行设置为datatable的标题
var value = worksheet.Cells[i, j].Value;
if (i == 1)
{
dt.Columns.Add(value == null ? $"标题{i}" : value.ToString());
}
//剩下的写入datatable
else
{
dr[j - 1] = value == null ? string.Empty : value.ToString();
}
}
}
return dt;
}
/// <summary>
/// 工作表转换为DataTable
/// </summary>
/// <param name="fileName"></param>
/// <param name="sheetName"></param>
/// <returns></returns>
public static DataTable ExcelSheetToDataTable(string fileName, string sheetName)
{
FileInfo fi = new(fileName);
ExcelPackage p = new(fi);
ExcelWorkbook workbook = p.Workbook;
ExcelWorksheet worksheet = workbook.Worksheets[sheetName];
return ExcelSheetToDataTable(worksheet);
}
/// <summary>
/// 从 ExcelPackage 中提取数据集。
/// </summary>
/// <param name="package">The Excel package.</param>
/// <param name="firstRowContainsHeader">if set to <c>true</c> [first row contains header].</param>
/// <returns></returns>
public static DataSet ToDataSet(this ExcelPackage package, bool firstRowContainsHeader = false)
{
var headerRow = firstRowContainsHeader ? 1 : 0;
return ToDataSet(package, headerRow);
}
/// <summary>
/// 从 ExcelPackage 中提取数据集。
/// </summary>
/// <param name="package">The Excel package.</param>
/// <param name="headerRow">标题行。如果没有标题行,则使用 0。值必须为 0 或更大。</param>
/// <returns></returns>
/// <exception cref="ArgumentException">headerRow 必须为 0 或更大。</exception>
public static DataSet ToDataSet(this ExcelPackage package, int headerRow = 0)
{
if (headerRow < 0)
{
throw new ArgumentOutOfRangeException(nameof(headerRow), headerRow, "必须为 0 或更大。");
}
var result = new DataSet();
foreach (var sheet in package.Workbook.Worksheets)
{
var table = new DataTable { TableName = sheet.Name };
int sheetStartRow = 1;
if (headerRow > 0)
{
sheetStartRow = headerRow;
}
var columns = from firstRowCell in sheet.Cells[sheetStartRow, 1, sheetStartRow, sheet.Dimension.End.Column]
select new DataColumn(headerRow > 0 ? firstRowCell.Value.ToString() : $"Column {firstRowCell.Start.Column}");
table.Columns.AddRange(columns.ToArray());
var startRow = headerRow > 0 ? sheetStartRow + 1 : sheetStartRow;
for (var rowIndex = startRow; rowIndex <= sheet.Dimension.End.Row; rowIndex++)
{
var inputRow = sheet.Cells[rowIndex, 1, rowIndex, sheet.Dimension.End.Column];
var row = table.Rows.Add();
foreach (var cell in inputRow)
{
row[cell.Start.Column - 1] = cell.Value;
}
}
result.Tables.Add(table);
}
return result;
}
public static void TrimLastEmptyRows(this ExcelWorksheet worksheet)
{
while (worksheet.IsLastRowEmpty())
{
worksheet.DeleteRow(worksheet.Dimension.End.Row, 1);
}
}
public static bool IsLastRowEmpty(this ExcelWorksheet worksheet)
{
var empties = new List<bool>();
for (var index = 1; index <= worksheet.Dimension.End.Column; index++)
{
var value = worksheet.Cells[worksheet.Dimension.End.Row, index].Value;
empties.Add(value == null || string.IsNullOrWhiteSpace(value.ToString()));
}
return empties.All(e => e);
}
/// <summary>
/// 获取工作表
/// </summary>
/// <param name="excelFilePath"></param>
/// <param name="sheetName"></param>
/// <returns></returns>
/// <exception cref="Exception"></exception>
public static ExcelWorksheet GetExcelWorksheet(string excelFilePath, string sheetName)
{
var excelworkbook = new FileInfo(excelFilePath);
using var p = new ExcelPackage(excelworkbook);
var ws = p.Workbook.Worksheets[sheetName];
return ws ?? throw new Exception("工作表不存在。");
}
/// <summary>
/// 读取Excel所有表
/// </summary>
/// <param name="filePath"></param>
public static void ReadSheets(string filePath)
{
using ExcelPackage package = new(new FileStream(filePath, FileMode.Open));
for (int i = 1; i <= package.Workbook.Worksheets.Count; ++i)
{
ExcelWorksheet sheet = package.Workbook.Worksheets[i];
for (int j = sheet.Dimension.Start.Column, k = sheet.Dimension.End.Column; j <= k; j++)
{
for (int m = sheet.Dimension.Start.Row, n = sheet.Dimension.End.Row; m <= n; m++)
{
//string str = GetValue(sheet, m, j);
//if (str != null)
//{
// // do something
//}
}
}
}
}
/// <summary>
/// 读取Excel所有表
/// </summary>
/// <param name="filePath"></param>
public static ExcelPackage ReadExcel(string filePath)
{
return new(new FileStream(filePath, FileMode.Open));
}
/// <summary>
/// 设置单元格的值
/// </summary>
/// <param name="sheet"></param>
/// <param name="rowNum">1开始</param>
/// <param name="columnNum">1开始</param>
/// <param name="value"></param>
public static void SetCellValue(ExcelWorksheet sheet, int rowNum, int columnNum, string value)
{
//sheet.Cells[rowNum, ColumnNum].Value = value;
sheet.SetValue(rowNum, columnNum, value);
}
/// <summary>
/// 通过单元格名设置值
/// </summary>
/// <param name="sheet"></param>
/// <param name="cellName"></param>
/// <param name="value"></param>
public static void SetCellValue(ExcelWorksheet sheet, string cellName, string value)
{
sheet.Cells[cellName].Value = value;
}
/// <summary>
/// 给工作表中的单元格赋值
/// </summary>
/// <param name="fileName"></param>
/// <param name="sheetname"></param>
/// <param name="rowNum"></param>
/// <param name="columnNum"></param>
/// <param name="value"></param>
public static void SetCellValue(string fileName, string sheetname, int rowNum, int columnNum, string value)
{
FileInfo fi = new(fileName);
using ExcelPackage package = new(fi);
//ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelWorksheet sheet = package.Workbook.Worksheets[sheetname];
//string filename = System.IO.Path.GetFileNameWithoutExtension(fileName);
sheet.SetValue(rowNum, columnNum, value);
package.Save();
}
/// <summary>
/// 给工作表中的单元格赋值
/// </summary>
/// <param name="fileName"></param>
/// <param name="sheetname"></param>
/// <param name="cellName">单元格名称比如A1</param>
/// <param name="value"></param>
public static void SetCellValue(string fileName, string sheetname, string cellName, string value)
{
FileInfo fi = new(fileName);
using ExcelPackage package = new(fi);
//ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelWorksheet sheet = package.Workbook.Worksheets[sheetname];
//string filename = System.IO.Path.GetFileNameWithoutExtension(fileName);
sheet.Cells[cellName].Value = value;
package.Save();
}
/// <summary>
/// 给工作表中的单元格赋值
/// </summary>
/// <param name="fileName"></param>
/// <param name="index">表索引0开始</param>
/// <param name="cellName">单元格名称如A1</param>
/// <param name="value"></param>
public static void SetCellValue(string fileName, int index, string cellName, string value)
{
FileInfo fi = new(fileName);
using ExcelPackage package = new(fi);
//ExcelPackage.LicenseContext = LicenseContext.NonCommercial;
ExcelWorksheet sheet = package.Workbook.Worksheets[index];
//string filename = System.IO.Path.GetFileNameWithoutExtension(fileName);
sheet.Cells[cellName].Value = value;
package.Save();
}
/// <summary>
/// 设置样式
/// </summary>
/// <param name="sheet"></param>
/// <param name="fromRow"></param>
/// <param name="fromCol"></param>
/// <param name="toRow"></param>
/// <param name="toCol"></param>
public static void SetStyle(ExcelWorksheet sheet, int fromRow, int fromCol, int toRow, int toCol)
{
using var range = sheet.Cells[fromRow, fromCol, toRow, toCol];
//range.Style.Font.Name = "微软雅黑";
range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
range.Style.Font.Size = 12;
range.Style.Border.Top.Style = ExcelBorderStyle.Thin;
range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
range.Style.Border.Left.Style = ExcelBorderStyle.Thin;
range.Style.Border.Right.Style = ExcelBorderStyle.Thin;
//range.Style.SetBackgroundColor(System.Drawing.Color.FromArgb(142, 169, 219));
}
/// <summary>
/// 设置表头样式
/// </summary>
/// <param name="sheet"></param>
/// <param name="fromRow"></param>
/// <param name="fromCol"></param>
/// <param name="toRow"></param>
/// <param name="toCol"></param>
public static void SetTitle(ExcelWorksheet sheet, int fromRow, int fromCol, int toRow, int toCol)
{
using var range = sheet.Cells[fromRow, fromCol, toRow, toCol];
range.Style.Font.Name = "微软雅黑";
range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
range.Style.Font.Size = 14;
range.Style.Font.Bold = true;
range.Style.Border.Top.Style = ExcelBorderStyle.Thin;
range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
range.Style.Border.Left.Style = ExcelBorderStyle.Thin;
range.Style.Border.Right.Style = ExcelBorderStyle.Thin;
//range.SetBackgroundColor(System.Drawing.Color.FromArgb(142, 169, 219));
}
/// <summary>
/// 创建Excel文件添加Excel表格
/// </summary>
/// <param name="filePath"></param>
/// <param name="sheetName"></param>
/// <param name="action"></param>
public static void WriteExcel(string filePath, string sheetName, Action<ExcelPackage> action)
{
using ExcelPackage package = new();
ExcelWorksheet sheet = package.Workbook.Worksheets.Add(sheetName);
using Stream stream = new FileStream(filePath, FileMode.Create);
action(package);
package.SaveAs(stream);
}
/// <summary>
/// 写入Excel
/// </summary>
/// <param name="filePath"></param>
/// <param name="action"></param>
public static void WriteExcel(string filePath, Action<ExcelPackage> action)
{
var fileInfo = new FileInfo(filePath);
if (fileInfo.Exists)
{
fileInfo.Delete();
}
using ExcelPackage package = new(fileInfo);
action(package);
package.Save();
}
public static IEnumerable<T> ReadRecords<T>(string path, int headerIndex = 1, string sheet = null, Type type = null)
where T : new()
{
using var package = new ExcelPackage(new FileInfo(path));
var worksheet = string.IsNullOrWhiteSpace(sheet)
? package.Workbook.Worksheets.FirstOrDefault()
: package.Workbook.Worksheets.FirstOrDefault(i => i.Name == sheet);
var results = worksheet.Read<T>(headerIndex, type);
return results;
}
public static byte[] ToBytes<T>(IEnumerable<T> items, string sheetName, Type type = null)
{
var mapClass = type ?? AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.StartsWith("Namespace"))
.SelectMany(i => i.GetTypes().Where(t => t.IsClass && typeof(BaseTypeConfiguration<T>).IsAssignableFrom(t)))
.FirstOrDefault();
var instance = (BaseTypeConfiguration<T>)Activator.CreateInstance(mapClass);
var mappings = instance.GetMappings().OrderBy(x => x.Order).ToList();
var cols = new List<(int index, string name, int order, PropertyConfiguration propertyConfiguration)>();
var results = new List<object>();
using var package = new ExcelPackage();
var worksheet = package.Workbook.Worksheets.Add(sheetName);
var row = 1;
mappings.ForEach(map => worksheet.Cells[row, map.Order].Value = map.Name);
foreach (var item in items)
{
row++;
mappings.ForEach(map =>
{
var propertyInfo = item.GetPropValue(map.Member.Name);
var value = Cast(propertyInfo.GetValue(item, null), map);
worksheet.Cells[row, map.Order].Value = value;
});
}
return package.GetAsByteArray();
}
}