ExportApplication.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. 
  2. using DocumentFormat.OpenXml.ExtendedProperties;
  3. using Hotline.Application.Tools;
  4. using Hotline.Share.Dtos.CallCenter;
  5. using Hotline.Share.Dtos.Order;
  6. using Hotline.Share.Enums.Article;
  7. using Hotline.Share.Tools;
  8. using Hotline.Tools;
  9. using Mapster;
  10. using MapsterMapper;
  11. using Microsoft.AspNetCore.Http;
  12. using Microsoft.AspNetCore.Mvc;
  13. using Microsoft.Extensions.DependencyInjection;
  14. using MiniExcelLibs;
  15. using NPOI.HPSF;
  16. using NPOI.SS.Formula.Functions;
  17. using SqlSugar;
  18. using System.Net.Http;
  19. using System.Reflection;
  20. using XF.Domain.Dependency;
  21. using XF.Utility.EnumExtensions;
  22. namespace Hotline.Application.ExportExcel
  23. {
  24. public class ExportApplication : IExportApplication, IScopeDependency
  25. {
  26. private readonly IMapper _mapper;
  27. public ExportApplication(IMapper mapper)
  28. {
  29. _mapper = mapper;
  30. }
  31. /// <summary>
  32. /// 导出数据
  33. /// </summary>
  34. /// <typeparam name="T"></typeparam>
  35. /// <param name="list">数据集</param>
  36. /// <param name="name">导出文件名(不传则生成yyyyMMddhhmmss)</param>
  37. /// <returns></returns>
  38. public FileStreamResult ExportData<T>(IList<T> list, string? name)
  39. {
  40. var stream = new MemoryStream();
  41. stream.SaveAs(list);
  42. stream.Seek(0, SeekOrigin.Begin);
  43. return new FileStreamResult(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
  44. {
  45. FileDownloadName = string.IsNullOrEmpty(name) ? DateTime.Now.ToString("yyyyMMddhhmmss") + ".xlsx" : name
  46. };
  47. }
  48. public Stream GetExcelStream<T, D>(ExportExcelDto<D> dto, IList<T> items, Func<IList<T>, T>? func = null)
  49. {
  50. if (items != null && items.Count > 0 && func != null)
  51. {
  52. items.Add(func.Invoke(items));
  53. }
  54. dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(dto.ColumnInfos);
  55. var dtos = items
  56. .Select(stu => _mapper.Map(stu, typeof(T), dynamicClass))
  57. .Cast<object>()
  58. .ToList();
  59. return ExcelHelper.CreateStream(dtos);
  60. }
  61. public FileStreamResult GetExcelFile<T, D>(ExportExcelDto<D> dto, IList<T> items, string fileName, Func<IList<T>, T>? func = null)
  62. {
  63. return GetExcelStream(dto, items, func).GetExcelFile(fileName);
  64. }
  65. public FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName, string? totalFiledName)
  66. {
  67. if (totalFiledName.IsNullOrEmpty()) return GetExcelFile(typeT, typeD, dto, items, fileName);
  68. var fieldsAll = typeT.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  69. var fields = fieldsAll.Where(f => IsNumericType(f.FieldType)); // 只选择数值类型字段
  70. var totalField = fieldsAll.Where(m => m.Name.Contains(totalFiledName)).First();
  71. var sumDict = new Dictionary<FieldInfo, dynamic>();
  72. foreach (var field in fields)
  73. {
  74. sumDict[field] = 0;
  75. }
  76. foreach (var item in items)
  77. {
  78. foreach (var field in fields)
  79. {
  80. var value = field.GetValue(item);
  81. if (value != null)
  82. {
  83. sumDict[field] += (dynamic)value; // 使用 dynamic 累加
  84. }
  85. }
  86. }
  87. var resultItem = Activator.CreateInstance(typeT);
  88. totalField.SetValue(resultItem, "合计");
  89. foreach (var field in fields)
  90. {
  91. field.SetValue(resultItem, sumDict[field]);
  92. }
  93. items.Add(resultItem);
  94. return GetExcelFile(typeT, typeD, dto, items, fileName);
  95. }
  96. public FileStreamResult GetExcelFile(Type typeT, Type typeD, object dto, IList<object> items, string fileName)
  97. {
  98. var columnInfos = typeD.GetProperty("ColumnInfos")?.GetValue(dto) as List<ColumnInfo>;
  99. if (columnInfos == null)
  100. {
  101. throw new ArgumentException("ColumnInfos not found in dto");
  102. }
  103. dynamic? dynamicClass = DynamicClassHelper.CreateDynamicClass(columnInfos);
  104. var dtos = items
  105. .Select(item =>
  106. {
  107. var mappedItem = _mapper.Map(item, typeT, dynamicClass);
  108. foreach (var prop in mappedItem.GetType().GetProperties())
  109. {
  110. if (prop.PropertyType == typeof(string))
  111. {
  112. if((string)prop.GetValue(mappedItem) == "True")
  113. prop.SetValue(mappedItem, "是");
  114. if((string)prop.GetValue(mappedItem) == "False")
  115. prop.SetValue(mappedItem, "否");
  116. }
  117. }
  118. return mappedItem;
  119. })
  120. .Cast<object>()
  121. .ToList();
  122. return ExcelHelper.CreateStream(dtos).GetExcelFile(fileName);
  123. }
  124. public FileStreamResult GetExcelFile<T, D>(ExportExcelDto<D> dto, IList<T> items, string fileName, string totalName) where T : new()
  125. {
  126. var fieldsAll = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  127. var fields = fieldsAll.Where(f => IsNumericType(f.FieldType)); // 只选择数值类型字段
  128. var totalField = fieldsAll.Where(m => m.Name.Contains(totalName)).First();
  129. var sumDict = new Dictionary<FieldInfo, dynamic>();
  130. foreach (var field in fields)
  131. {
  132. sumDict[field] = 0;
  133. }
  134. foreach (var item in items)
  135. {
  136. foreach (var field in fields)
  137. {
  138. var value = field.GetValue(item);
  139. if (value != null)
  140. {
  141. sumDict[field] += (dynamic)value; // 使用 dynamic 累加
  142. }
  143. }
  144. }
  145. var resultItem = new T();
  146. totalField.SetValue(resultItem, "合计");
  147. foreach (var field in fields)
  148. {
  149. field.SetValue(resultItem, sumDict[field]);
  150. }
  151. items.Add(resultItem);
  152. return GetExcelFile(dto, items, fileName);
  153. }
  154. private static bool IsNumericType(Type type)
  155. {
  156. return type == typeof(int) || type == typeof(float) || type == typeof(double) ||
  157. type == typeof(decimal) || type == typeof(long) || type == typeof(short) ||
  158. type == typeof(byte) || type == typeof(uint) || type == typeof(ulong) ||
  159. type == typeof(ushort) || type == typeof(sbyte) || type == typeof(double?);
  160. }
  161. }
  162. }