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
}