using System.Collections; using System.ComponentModel; using System.Reflection; using OfficeOpenXml; using OfficeOpenXml.Style; using SixLabors.ImageSharp; using Tiobon.Core.Common.Helper; namespace Tiobon.Core.Common.Extensions; public static class IQueryableExtensions { static int EXPORT_FILE_PAGESIZE = 10000; /// /// IQueryable数据写入文件(Excel) /// /// /// /// /// /// /// /// /// public static void IntoFileFromLinqExcel(this IQueryable db, string fname, string splitstr, List exportFields, List exportFieldsWidth, string headText = "", string totalText = "", bool isNeedItemNo = false) where T : class { if (db.IsNull()) return; //查询文件状态 if (File.Exists(fname)) { LoggerHelper.SendLog("文件已生成 " + fname); return; } LoggerHelper.SendLog("正在生成文件 " + fname); DateTime dt_start = DateTime.Now; if (!File.Exists(fname)) File.Create(fname).Close(); //获取需要导出的字段 Dictionary fieldDescs = GetFieldDesc(); int dbCount = db.Count(); //列名排序,返回有序列表 var (fields, colunms) = Sort(fieldDescs, exportFields); using (FileStream stream = File.Create(fname)) { using (ExcelPackage package = new ExcelPackage(stream)) { ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("sheet1"); var colunmsCount = colunms.Count; var startCol = 0; var startRow = 1; // 初始行数 if (isNeedItemNo) startCol = 1; if (!string.IsNullOrEmpty(headText)) { worksheet.Cells[startRow, 1].Value = headText; worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Merge = true; worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Style.Font.Bold = true; worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center; // Alignment is center worksheet.Cells[startRow, 1, 1, colunmsCount + startCol].Style.Font.Size = 14; startRow++; } if (isNeedItemNo) { worksheet.Cells[startRow, 1].Value = "序号"; worksheet.Cells[startRow, 1, startRow, 1].Style.Font.Bold = true; worksheet.Cells[startRow, 1, startRow, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[startRow, 1, startRow, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; } //写入列名 for (int i = 0; i < fields.Count; ++i) { worksheet.Cells[startRow, i + 1 + startCol].Value = fields[i]; worksheet.Cells[startRow, i + 1 + startCol, startRow, i + 1 + startCol].Style.Font.Bold = true; worksheet.Cells[startRow, i + 1 + startCol, startRow, i + 1 + startCol].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[startRow, i + 1 + startCol, startRow, i + 1 + startCol].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; } startRow++; //查看数据是否过大,需要分页 int totalPageNum = (dbCount + EXPORT_FILE_PAGESIZE - 1) / EXPORT_FILE_PAGESIZE; //遍历每一页 for (int pageNum = 0; pageNum < totalPageNum; ++pageNum) { var list = db.Skip(pageNum * EXPORT_FILE_PAGESIZE).Take(EXPORT_FILE_PAGESIZE).ToList(); //遍历每行 for (int row = 0; row < list.Count; ++row) { if (isNeedItemNo) { worksheet.Cells[row + startRow, 1].Value = row + 1; worksheet.Cells[row + startRow, 1, row + startRow, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[row + startRow, 1, row + startRow, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; } //遍历需要写入文件的字段 for (int i = 0; i < colunms.Count; ++i) { worksheet.Cells[row + startRow, i + 1 + startCol].Value = ConvertData2String(list[row], colunms[i]); worksheet.Cells[row + startRow, i + 1 + startCol, row + startRow, i + 1 + startCol].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[row + startRow, i + 1 + startCol, row + startRow, i + 1 + startCol].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; } } } if (!string.IsNullOrEmpty(totalText)) { worksheet.Cells[dbCount + startRow, 1].Value = "总计:"; worksheet.Cells[dbCount + startRow, 1, dbCount + startRow, 1].Style.VerticalAlignment = OfficeOpenXml.Style.ExcelVerticalAlignment.Center; worksheet.Cells[dbCount + startRow, 1, dbCount + startRow, 1].Style.HorizontalAlignment = OfficeOpenXml.Style.ExcelHorizontalAlignment.Center; worksheet.Cells[dbCount + startRow, 2, dbCount + startRow, colunms.Count + startCol].Value = totalText; worksheet.Cells[dbCount + startRow, 2, dbCount + startRow, colunms.Count + startCol].Merge = true; startRow++; } using (ExcelRange r = worksheet.Cells[1, 1, dbCount + startRow - 1, fields.Count + startCol]) { r.Style.Border.Top.Style = ExcelBorderStyle.Thin; r.Style.Border.Left.Style = ExcelBorderStyle.Thin; r.Style.Border.Right.Style = ExcelBorderStyle.Thin; r.Style.Border.Bottom.Style = ExcelBorderStyle.Thin; r.Style.Border.Top.Color.SetColor(Color.Black); r.Style.Border.Left.Color.SetColor(Color.Black); r.Style.Border.Right.Color.SetColor(Color.Black); r.Style.Border.Bottom.Color.SetColor(Color.Black); } if (isNeedItemNo) { worksheet.Column(1).Width = 20;//设置列宽为默认值 } //设置列宽 if (exportFieldsWidth == null || exportFieldsWidth.Count < fields.Count) { for (int i = 0; i < fields.Count; ++i) { worksheet.Column(i + 1 + startCol).Width = 20;//设置列宽为默认值 } } else { for (int i = 0; i < fields.Count; ++i) { worksheet.Column(i + 1 + startCol).Width = exportFieldsWidth[i];//设置列宽为前段配置的值 } } package.Workbook.Properties.Title = "数据导出"; package.Workbook.Properties.Author = "SUZHOUEU"; package.Workbook.Properties.Comments = "苏州一优信息技术有限公司提供技术支持!"; package.Workbook.Properties.Company = "苏州一优信息技术有限公司"; package.Workbook.Properties.SetCustomPropertyValue("Checked by", "SimonHsiao"); package.Workbook.Properties.SetCustomPropertyValue("AssemblyName", "SUZHOUEU"); package.Save(); } } LoggerHelper.SendLog("生成文件 " + fname + " 完毕 " + dbCount + " 耗时 " + (int)(DateTime.Now - dt_start).TotalSeconds); } private static string ConvertData2String(T t, string field) where T : class { if (t.FieldTypeIsDateTime(field)) { DateTime? time = t.GetDateTimeValueFromField(field); if (time != null) { if (time.Value.ToString("HH:mm:ss") == "00:00:00") { return time.Value.ToString("yyyy-MM-dd"); } else { return time.Value.ToString("yyyy-MM-dd HH:mm:ss"); } } else { return string.Empty; } } else { return t.GetStringValueFromField(field); } } /// /// 列名按照前端显示顺序导出 /// /// /// /// public static (List, List) Sort(Dictionary columns, List ExportFields) { List fields = new List(); List colunms = new List(); if (ExportFields == null || ExportFields.Count == 0) { return (columns.Keys.ToList(), columns.Values.ToList()); } foreach (var field in ExportFields) { foreach (var item in columns) { if (item.Key == field) { fields.Add(item.Key); colunms.Add(item.Value); } } } return (fields, colunms); } /// /// 获取数据 /// /// 对象 /// /// public static List GetPropertyData(T obj, List colunms) where T : class { List data = new List(); //声明obj的类型 Type type = obj.GetType(); // 获取obj类型的所有属性信息 System.Reflection.PropertyInfo[] PropertyList = type.GetProperties(); //循环每一个属性 foreach (var item in PropertyList) { // 获取自定义特性 object[] export = item.GetCustomAttributes(typeof(ExportDatatAttribute), true); object[] descript = item.GetCustomAttributes(typeof(DescriptionAttribute), true); //判断是否需要导出 if (export.Length > 0) { //取值 var exdesc = ((ExportDatatAttribute)export[0]); // 是否嵌套 if (exdesc != null) { //是否是序列 if (exdesc.ExportDataFlag == "1") { var tmp = item.GetValue(obj) as IEnumerable; //List if (tmp != null) { foreach (var o in tmp) { data.AddRange(GetPropertyData(o, colunms)); } } } // 如果是嵌套model else if (exdesc.ExportDataFlag == "2") { var tmp = item.GetValue(obj); if (tmp != null) { data.AddRange(GetPropertyData(tmp, colunms)); } } else if (exdesc.ExportDataFlag == "3") { if (colunms.Contains(item.Name)) { data.Add(item.GetValue(obj).ToString()); } } } } else if (descript.Length > 0) { if (colunms.Contains(item.Name)) { data.Add(item.GetValue(obj).ToString()); } } } return data; } #region 获取字段描述 /// /// 对象字段描述 /// private static Dictionary> m_FieldDesc = new Dictionary>(); /// /// 获取字段的描述(描述 - 列名) /// /// /// public static Dictionary GetFieldDesc() { var type = typeof(T).ToString(); lock (m_FieldDesc) { if (m_FieldDesc.ContainsKey(type)) return m_FieldDesc[type]; } Dictionary dic = new Dictionary(); try { PropertyInfo[] peroperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); if (peroperties != null) { foreach (PropertyInfo property in peroperties) { object[] objs = property.GetCustomAttributes(typeof(DescriptionAttribute), true); if (objs.Length > 0) { var desc = ((DescriptionAttribute)objs[0]).Description.Trim(); if (!dic.ContainsKey(desc)) { dic.Add(desc, property.Name); } else { dic[desc] = property.Name; } } } } } catch //(Exception ex) { } lock (m_FieldDesc) { if (!m_FieldDesc.ContainsKey(type)) m_FieldDesc.Add(type, dic); } return dic; } #endregion }