ExportExcel_EPPlus.cs 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. using OfficeOpenXml;
  2. using OfficeOpenXml.Style;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Data;
  6. using System.Drawing;
  7. using System.IO;
  8. public class ExcelExportService
  9. {
  10. public static byte[] ExportDataTableToBytes(DataTable dataTable, Dictionary<string, string> customHeaders = null)
  11. {
  12. try
  13. {
  14. if (dataTable == null || dataTable.Rows.Count == 0)
  15. {
  16. throw new ArgumentException("数据表不能为空");
  17. }
  18. using (var package = new ExcelPackage())
  19. {
  20. var worksheet = package.Workbook.Worksheets.Add("Sheet1");
  21. // 写入列标题
  22. WriteHeaders(worksheet, dataTable, customHeaders);
  23. // 写入数据行
  24. WriteData(worksheet, dataTable);
  25. // 应用格式
  26. ApplyFormatting(worksheet, dataTable);
  27. return package.GetAsByteArray();
  28. }
  29. }
  30. catch (Exception ex)
  31. {
  32. throw new Exception($"导出失败: {ex.Message}", ex);
  33. }
  34. }
  35. /// <summary>
  36. /// 导出DataTable到Excel并返回文件信息
  37. /// </summary>
  38. public static ExportResult ExportDataTable(DataTable dataTable, string exportPath,
  39. string fileName = null,
  40. Dictionary<string, string> customHeaders = null)
  41. {
  42. try
  43. {
  44. if (dataTable == null || dataTable.Rows.Count == 0)
  45. {
  46. return ExportResult.Error("数据表不能为空");
  47. }
  48. // 确保目录存在
  49. if (!Directory.Exists(exportPath))
  50. {
  51. Directory.CreateDirectory(exportPath);
  52. }
  53. // 生成文件名
  54. if (string.IsNullOrEmpty(fileName))
  55. {
  56. fileName = $"QC检验数据_{DateTime.Now:yyyyMMdd_HHmmss}.xlsx";
  57. }
  58. else if (!fileName.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase))
  59. {
  60. fileName += ".xlsx";
  61. }
  62. string filePath = Path.Combine(exportPath, fileName);
  63. // 确保文件名唯一
  64. filePath = GetUniqueFilePath(filePath);
  65. // 导出Excel
  66. using (var package = new ExcelPackage())
  67. {
  68. var worksheet = package.Workbook.Worksheets.Add("Sheet1");
  69. // 写入列标题
  70. WriteHeaders(worksheet, dataTable, customHeaders);
  71. // 写入数据行
  72. WriteData(worksheet, dataTable);
  73. // 应用格式
  74. ApplyFormatting(worksheet, dataTable);
  75. // 保存文件
  76. package.SaveAs(new FileInfo(filePath));
  77. }
  78. // 返回导出结果
  79. return ExportResult.SuccessResult(filePath, fileName, dataTable.Rows.Count);
  80. }
  81. catch (Exception ex)
  82. {
  83. return ExportResult.Error($"导出失败: {ex.Message}");
  84. }
  85. }
  86. /// <summary>
  87. /// 获取唯一文件名
  88. /// </summary>
  89. private static string GetUniqueFilePath(string filePath)
  90. {
  91. if (!File.Exists(filePath))
  92. return filePath;
  93. string directory = Path.GetDirectoryName(filePath);
  94. string fileNameWithoutExt = Path.GetFileNameWithoutExtension(filePath);
  95. string extension = Path.GetExtension(filePath);
  96. int counter = 1;
  97. string newFilePath;
  98. do
  99. {
  100. newFilePath = Path.Combine(directory,
  101. $"{fileNameWithoutExt}_{counter}{extension}");
  102. counter++;
  103. } while (File.Exists(newFilePath));
  104. return newFilePath;
  105. }
  106. /// <summary>
  107. /// 写入列标题
  108. /// </summary>
  109. private static void WriteHeaders(ExcelWorksheet worksheet, DataTable dataTable,
  110. Dictionary<string, string> customHeaders)
  111. {
  112. for (int i = 0; i < dataTable.Columns.Count; i++)
  113. {
  114. string headerText = dataTable.Columns[i].ColumnName;
  115. if (customHeaders != null && customHeaders.ContainsKey(headerText))
  116. {
  117. headerText = customHeaders[headerText];
  118. }
  119. worksheet.Cells[1, i + 1].Value = headerText;
  120. }
  121. // 设置标题样式
  122. using (var range = worksheet.Cells[1, 1, 1, dataTable.Columns.Count])
  123. {
  124. range.Style.Font.Bold = true;
  125. range.Style.Font.Size = 11;
  126. range.Style.Fill.PatternType = ExcelFillStyle.Solid;
  127. range.Style.Fill.BackgroundColor.SetColor(Color.LightBlue);
  128. range.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
  129. range.Style.VerticalAlignment = ExcelVerticalAlignment.Center;
  130. }
  131. }
  132. /// <summary>
  133. /// 写入数据
  134. /// </summary>
  135. private static void WriteData(ExcelWorksheet worksheet, DataTable dataTable)
  136. {
  137. for (int row = 0; row < dataTable.Rows.Count; row++)
  138. {
  139. for (int col = 0; col < dataTable.Columns.Count; col++)
  140. {
  141. object value = dataTable.Rows[row][col];
  142. if (value == DBNull.Value || value == null)
  143. {
  144. worksheet.Cells[row + 2, col + 1].Value = "";
  145. }
  146. else if (dataTable.Columns[col].DataType == typeof(DateTime))
  147. {
  148. worksheet.Cells[row + 2, col + 1].Value = value;
  149. worksheet.Cells[row + 2, col + 1].Style.Numberformat.Format = "yyyy-mm-dd hh:mm:ss";
  150. }
  151. else if (dataTable.Columns[col].DataType == typeof(bool))
  152. {
  153. worksheet.Cells[row + 2, col + 1].Value = (bool)value ? "是" : "否";
  154. }
  155. else
  156. {
  157. worksheet.Cells[row + 2, col + 1].Value = value;
  158. }
  159. }
  160. }
  161. }
  162. /// <summary>
  163. /// 应用格式
  164. /// </summary>
  165. private static void ApplyFormatting(ExcelWorksheet worksheet, DataTable dataTable)
  166. {
  167. if (worksheet.Dimension == null) return;
  168. // 设置数据区域边框
  169. using (var range = worksheet.Cells[worksheet.Dimension.Address])
  170. {
  171. range.Style.Border.Top.Style = ExcelBorderStyle.Thin;
  172. range.Style.Border.Bottom.Style = ExcelBorderStyle.Thin;
  173. range.Style.Border.Left.Style = ExcelBorderStyle.Thin;
  174. range.Style.Border.Right.Style = ExcelBorderStyle.Thin;
  175. }
  176. // 自动调整列宽
  177. worksheet.Cells[worksheet.Dimension.Address].AutoFitColumns();
  178. }
  179. /// <summary>
  180. /// 获取默认导出目录
  181. /// </summary>
  182. public static string GetDefaultExportPath(string filename)
  183. {
  184. string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
  185. string exportFolder = Path.Combine(desktopPath, filename);
  186. if (!Directory.Exists(exportFolder))
  187. {
  188. Directory.CreateDirectory(exportFolder);
  189. }
  190. return exportFolder;
  191. }
  192. }
  193. /// <summary>
  194. /// 导出结果
  195. /// </summary>
  196. public class ExportResult
  197. {
  198. public bool Success { get; set; }
  199. public string Message { get; set; }
  200. public string FilePath { get; set; }
  201. public string FileName { get; set; }
  202. public string FullPath { get; set; }
  203. public int RecordCount { get; set; }
  204. public DateTime ExportTime { get; set; }
  205. public long FileSize { get; set; }
  206. public static ExportResult SuccessResult(string filePath, string fileName, int recordCount)
  207. {
  208. var fileInfo = new FileInfo(filePath);
  209. return new ExportResult
  210. {
  211. Success = true,
  212. Message = "导出成功",
  213. FilePath = filePath,
  214. FileName = fileName,
  215. FullPath = filePath,
  216. RecordCount = recordCount,
  217. ExportTime = DateTime.Now,
  218. FileSize = fileInfo.Exists ? fileInfo.Length : 0
  219. };
  220. }
  221. public static ExportResult Error(string errorMessage)
  222. {
  223. return new ExportResult
  224. {
  225. Success = false,
  226. Message = errorMessage,
  227. ExportTime = DateTime.Now
  228. };
  229. }
  230. }