Files
YunTongJackYunTask/Reportapi/MyCode.Project.Infrastructure/Exports/ExportExcelConfig.cs
2025-07-04 09:50:02 +08:00

427 lines
16 KiB
C#
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
using System.Collections.Generic;
using System.IO;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.POIFS.FileSystem;
using MyCode.Project.Infrastructure.Common;
using NPOI.SS.Util;
using System.Linq;
namespace MyCode.Project.Infrastructure.Exports
{
/// <summary>
/// 导出Excel配置类
/// </summary>
public class ExportExcelConfig
{
/// <summary>
/// 查询条件
/// </summary>
public object Condition { get; set; }
/// <summary>
/// Excel中的标题和实体属性中的字段Map例如标题->Title
/// </summary>
public List<ExportExcelProperty> Properties { get; }
public List<NpoiHeadCfg> Heads = new List<NpoiHeadCfg>();
/// <summary>
/// 初始化一个<see cref="ExportExcelConfig"/>类型的实例
/// </summary>
public ExportExcelConfig()
{
Properties = new List<ExportExcelProperty>();
Heads = new List<NpoiHeadCfg>();
}
/// <summary>
/// 根据数据实体和配置生成相应的Excel文件
/// </summary>
/// <param name="sourceData">数据源</param>
/// <param name="fileName">文件名</param>
/// <returns></returns>
public string CreateExcelFile(IList sourceData,string fileName)
{
//初始化枚举字典
var dicEnum = new Dictionary<string, Dictionary<int, string>>();
//获取列表第一个元素的数据类型
Type type = null;
if (sourceData.Count > 0)
{
type = sourceData[0].GetType();
}
//创建2007的Excel
HSSFWorkbook workbook = null;
//如果文件存在,则直接获取采用追加的方式追加进去
string filePath = GetDownloadPath(fileName);
string absFilePath = FileUtils.GetPhysicalPath(filePath);
ISheet sheet = null;
IRow row = null;
// (absFilePath);
workbook = new HSSFWorkbook();
sheet = workbook.CreateSheet();
//设置标题列样式
ICellStyle headStyle = workbook.CreateCellStyle();
headStyle.VerticalAlignment = VerticalAlignment.Center;
headStyle.Alignment = HorizontalAlignment.Center;
//设置字体-加粗字体
IFont headFont = workbook.CreateFont();
headFont.IsBold = true;
row = sheet.CreateRow(0);
//设置默认边框
ICellStyle style0 = workbook.CreateCellStyle();
style0.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
style0.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
style0.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
style0.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
int dataRowIndex = 0;
int endColIndex = 0;
if (Heads == null || Heads.Count == 0)
{
//创建标题列
for (int i = 0; i < this.Properties.Count; i++)
{
var cell = row.CreateCell(i);
cell.SetCellValue(this.Properties[i].Caption);
cell.CellStyle = headStyle;
cell.CellStyle.SetFont(headFont);
if (this.Properties[i].Width > 0) { sheet.SetColumnWidth(i, this.Properties[i].Width); }
//设置边框
row.Sheet.SetDefaultColumnStyle(i, style0);
}
}
else
{
endColIndex = Heads.Max(t => t.EndColIndex);
//设置边框
for (int i = 0; i <= endColIndex; i++)
{
row.Sheet.SetDefaultColumnStyle(i, style0);
}
CreadHeader(workbook, ref sheet, Heads);
dataRowIndex = Heads.Max(t => t.EndRowIndex);
}
//创建内容列
for (int i = 0; i < sourceData.Count ; i++)
{
var entity = sourceData[i];
//创建新的内容行
//row = sheet.CreateRow(i + sheet.LastRowNum + 1);
row = sheet.CreateRow(dataRowIndex + 1);
//根据配置的属性列创建对应单元格
for (int j = 0; j < this.Properties.Count; j++)
{
var prop = this.Properties[j].EntityProp;
//储存内容值
object value = null;
//检查是否存在+号,如果存在则表示是拼接数据
if (prop.IndexOf("+", StringComparison.Ordinal) > -1)
{
value = GetValueOfAddSymbol(this.Properties, type, entity, j);
}
else
{
value = this.GetPropValue(prop, type, entity);
}
//根据数据类型填写对应的单元格
if (value == null)
{
row.CreateCell(j).SetCellValue("");
}
else if (value is decimal)
{
row.CreateCell(j).SetCellValue(Convert.ToDouble(value));
}
else if (value is double)
{
row.CreateCell(j).SetCellValue((double)value);
}
else if (value is DateTime)
{
row.CreateCell(j).SetCellValue(Convert.ToDateTime(value).ToString("yyyy-MM-dd HH:mm:ss"));
}
else if (value is bool)
{
row.CreateCell(j).SetCellValue((bool)value);
}
else if (value is int )
{
//枚举
if (this.Properties[j].EnumType != null)
{
var enumValue = GetEnumValue(dicEnum, this.Properties[j].EnumType, this.Properties[j].EntityProp, Convert.ToInt32(value));
row.CreateCell(j).SetCellValue(enumValue);
}
else
{
row.CreateCell(j).SetCellValue((int)value);
}
}
else
{
row.CreateCell(j).SetCellValue(value.ToString());
}
}
dataRowIndex++;
}
using (FileStream fs = File.OpenWrite(absFilePath))
{
workbook.Write(fs);
fs.Close();
fs.Dispose();
}
workbook = null;
//SaveFilePath = filePath;
return filePath;
}
#region GetEnumValue()
/// <summary>
/// 得到枚举值
/// </summary>
/// <param name="dicAllEnum">所有字典</param>
/// <param name="enumType">枚举类型</param>
/// <param name="fieldName">属性名</param>
/// <param name="dicValue">枚举值</param>
/// <returns></returns>
private string GetEnumValue(Dictionary<string, Dictionary<int, string>> dicAllEnum,Type enumType,string fieldName,int dicValue)
{
if (!dicAllEnum.ContainsKey(fieldName))
{
dicAllEnum[fieldName] = EnumHelper.GetDictionary(enumType);
}
if (!dicAllEnum[fieldName].ContainsKey(dicValue)) { return dicValue.ToString(); }
return dicAllEnum[fieldName][dicValue];
}
#endregion
#region GetDownloadPath()
/// <summary>
/// 获取下载路径
/// </summary>
/// <param name="fileName">文件名</param>
/// <returns></returns>
private string GetDownloadPath(string fileName)
{
string dirPath = "/download/exceltemp/";
string absFilePath = FileUtils.GetPhysicalPath(dirPath);
if (!Directory.Exists(absFilePath))
{
Directory.CreateDirectory(absFilePath);
}
//string newFileName = DateTime.Now.ToString("yyyyMMddHHmmss_fff");
//string filePath = Path.Combine(dirPath, fileName + "_" + newFileName + ".xls");
//return filePath;
return Path.Combine(dirPath, fileName);
}
#endregion
#region GetPropValue()
/// <summary>
/// 获取字段值
/// </summary>
/// <param name="prop">属性名</param>
/// <param name="type">类型</param>
/// <param name="entity">实体对象</param>
/// <returns></returns>
private object GetPropValue(string prop, Type type, object entity)
{
object value = null;
//如果存在.号则表示是复杂类型属性,需要依次去获取数据
if (prop.IndexOf(".", StringComparison.Ordinal) > -1)
{
var props = prop.Split('.');
//获取第一级实体
value = type.GetProperty(props[0]).GetValue(entity);
for (int p = 1; p < props.Length; p++)
{
//如果值为空,则直接退出
if (value == null)
{
break;
}
Type childType = value.GetType();
value = childType.GetProperty(props[p]).GetValue(value);
}
}
else
{
value = type.GetProperty(prop).GetValue(entity);
}
return value;
}
#endregion
#region GetValueOfAddSymbol(+)
/// <summary>
/// 如果字段名用了+号
/// </summary>
/// <param name="prop"></param>
/// <param name="type"></param>
/// <param name="entity"></param>
/// <returns></returns>
private object GetValueOfAddSymbol(List<ExportExcelProperty> listProp,Type type,object entity,int j)
{
var prop = listProp[j].EntityProp;
//储存内容值
object value = null;
var joinProps = prop.Split('+');
for (int jp = 0; jp < joinProps.Length; jp++)
{
var jprop = joinProps[jp];
var newValue = this.GetPropValue(jprop, type, entity);
if (value != null)
{
if (newValue != null)
{
//这里只智齿字符串的累加,主要解决地址合并省市区的情况
value = value.ToString() + listProp[j].JoinPropChar + newValue.ToString();
}
}
else
{
value = newValue;
}
}
return value;
}
#endregion
#region CreadHeader()
/// <summary>
/// 创建表头,支持多行
/// </summary>
/// <param name="book"></param>
/// <param name="sheet"></param>
/// <param name="dt"></param>
/// <param name="heads"></param>
/// <remarks>
/// 创建:余宇波 2020-09-04
/// </remarks>
private static void CreadHeader(HSSFWorkbook book,ref ISheet sheet, List<NpoiHeadCfg> heads)
{
//创建 表格头部
if (heads != null && heads.Count > 0)
{
List<int> rows = new List<int>();
IRow headRow = sheet.CreateRow(0);//创建空行
rows.Add(0);
var style = GetCellStyle(book, heads[0]);
foreach (var t in heads)
{
if (!rows.Contains(t.StartRowIndex)) //假如没有创建行
{
rows.Add(t.StartRowIndex);
headRow = sheet.CreateRow(t.StartRowIndex);
}
else
{
headRow = sheet.GetRow(t.StartRowIndex);
}
headRow.Height = (short)(t.Height * 20); //设置行高 为25
ICell cell = headRow.CreateCell(t.StartColIndex); //创建单元格
cell.SetCellValue(t.FieldName); //设置单元格内容
// 设置列宽
if (t.Width > 0)
{
sheet.SetColumnWidth(cell.ColumnIndex, t.Width * 256);
}
else
{
sheet.SetColumnWidth(cell.ColumnIndex, 13 * 256);
}
//合并单元格
if (t.EndColIndex > t.StartColIndex || t.EndRowIndex > t.StartRowIndex)
{
CellRangeAddress region1 = new CellRangeAddress(t.StartRowIndex, t.EndRowIndex, (short)t.StartColIndex, (short)t.EndColIndex);
headRow.Sheet.AddMergedRegion(region1);
}
cell.CellStyle = style;
}
}
}
private static ICellStyle GetCellStyle(HSSFWorkbook book, NpoiHeadCfg headCfg)
{
ICellStyle style0 = book.CreateCellStyle();
// 2、行高
// row.Height = 30 * 20; //行高为30
// excelRow.Height = 25 * 20;
// 单元格 列宽:
//if (headCfg.Width > 0) {
// cell.Row.Sheet.SetColumnWidth(cell.ColumnIndex, headCfg.Width * 256);
//}
//三、设置居中:
//cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中
style0.Alignment = HorizontalAlignment.Left;
style0.VerticalAlignment = VerticalAlignment.Center;
//四、设置字体:
IFont font = book.CreateFont();
font.FontName = "黑体";//.SetFontName("黑体");
font.FontHeightInPoints = (short)11.5;//.SetFontHeightInPoints((short)16);//设置字体大小
style0.SetFont(font);//选择需要用到的字体格式
//大坑大坑大坑shunlu 2018-10-10
//必须设置单元格背景色 FillForegroundColor 和 FillPattern 的值才能正确显示背景色
style0.FillForegroundColor = NPOI.HSSF.Util.HSSFColor.Grey25Percent.Index; //(short)1灰色 NPOI.HSSF.Util.HSSFColor.LightBlue.Index;
style0.FillPattern = FillPattern.SolidForeground; // CellStyle.SOLID_FOREGROUND
//二、设置边框:
//cellStyle.setBorderBottom(HSSFCellStyle.BORDER_THIN); //下边框    cellStyle.setBorderLeft(HSSFCellStyle.BORDER_THIN);//左边框    cellStyle.setBorderTop(HSSFCellStyle.BORDER_THIN);//上边框    cellStyle.setBorderRight(HSSFCellStyle.BORDER_THIN);//右边框    三、设置居中:      cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中    
//style0.BorderBottom = BorderStyle.Medium;// CellStyle.SOLID_FOREGROUND
//style0.BorderRight = BorderStyle.Medium;
style0.BorderBottom = NPOI.SS.UserModel.BorderStyle.Thin;
style0.BorderLeft = NPOI.SS.UserModel.BorderStyle.Thin;
style0.BorderRight = NPOI.SS.UserModel.BorderStyle.Thin;
style0.BorderTop = NPOI.SS.UserModel.BorderStyle.Thin;
//三、设置居中:
//cellStyle.setAlignment(HSSFCellStyle.ALIGN_CENTER); // 居中
style0.Alignment = HorizontalAlignment.Left;
style0.VerticalAlignment = VerticalAlignment.Center;
//
return style0;
}
#endregion
}
}