You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

364 lines
14 KiB

  1. ///-----------------------------------------------------------------------
  2. /// <copyright file="ExcelExtansion.cs" company="ChipMOS">
  3. /// 程式代號: ExcelExtansion
  4. /// 程式名稱: ExcelExtansion
  5. /// 程式說明:
  6. /// 起始作者: Rexxar.eng
  7. /// 起始日期: 2017/03/13 16:55:08
  8. /// 最新修改人: Hercules
  9. /// 最新修日期: 2017/05/18 17:45:54
  10. /// </copyright>
  11. ///-----------------------------------------------------------------------
  12. #region 程式異動記錄
  13. /// xx.YYYY/MM/DD VER AUTHOR COMMENTS(說明修改的內容)
  14. /// 01.2017/03/13 1.000 Rexxar.eng Excel tools(RV.3120)
  15. /// 02.2017/03/13 1.001 Rexxar.eng Excel tools(RV.3121)
  16. /// 03.2017/03/13 1.002 Rexxar.eng Excel tools(RV.3126)
  17. /// 04.2017/03/14 1.003 Hercules 調整Excel Export(RV.3129)
  18. /// 05.2017/05/18 1.004 Hercules 補程式Header註解(RV.4375)
  19. #endregion
  20. using CounsellorBL.BLStructure;
  21. using MonumentDefine;
  22. using NPOI.HSSF.UserModel;
  23. using NPOI.SS.UserModel;
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Data;
  27. using System.Globalization;
  28. using System.IO;
  29. using System.Linq;
  30. namespace CounsellorBL.Helper
  31. {
  32. /// <summary>
  33. /// 類別名稱:ExcelHelper
  34. /// 類別說明:
  35. /// 起始作者:
  36. /// 起始日期:
  37. /// 最新修改人:
  38. /// 最新修改日:
  39. /// </summary>
  40. public static partial class ExcelHelper
  41. {
  42. /// <summary>
  43. /// 函式名稱:ExportExcel
  44. /// 函式說明:
  45. /// 起始作者:
  46. /// 起始日期:
  47. /// 最新修改人:
  48. /// 最新修改日:
  49. /// </summary>
  50. /// <param name="i_pInfo">
  51. /// 參數說明
  52. /// </param>
  53. /// <returns>
  54. /// 回傳
  55. /// </returns>
  56. public static bool ExportExcel(ExcelHelperParameter i_pInfo)
  57. {
  58. //暫存於伺服器端提供下載檔案路徑
  59. return ExportExcelWithMultSheet(new List<ExcelHelperParameter>() { i_pInfo });
  60. }
  61. /// <summary>
  62. /// 函式名稱:ExportExcel
  63. /// 函式說明:
  64. /// 起始作者:
  65. /// 起始日期:
  66. /// 最新修改人:
  67. /// 最新修改日:
  68. /// </summary>
  69. /// <param name="i_pInfo">
  70. /// 參數說明
  71. /// </param>
  72. /// <returns>
  73. /// 回傳
  74. /// </returns>
  75. public static bool ExportExcelWithMultSheet(List<ExcelHelperParameter> i_lpInfo)
  76. {
  77. bool success = false;
  78. if (i_lpInfo != null)
  79. {
  80. string sPath = i_lpInfo[0].Path;
  81. string sFileName = i_lpInfo[0].FileName;
  82. HSSFWorkbook workbook = new HSSFWorkbook();
  83. foreach (ExcelHelperParameter i_pInfo in i_lpInfo)
  84. {
  85. //Excel創建工作表
  86. ISheet sheet = workbook.CreateSheet((string.IsNullOrEmpty(i_pInfo.SheetName)) ? i_pInfo.FileName : i_pInfo.SheetName);
  87. int iRowIndex = 0;
  88. IRow row = sheet.CreateRow(iRowIndex++);
  89. QueryResponse qrRes = new QueryResponse(i_pInfo.QueryData);
  90. List<Dictionary<string, object>> data = qrRes.Records;
  91. List<string> lColumnOrder = new List<string>();
  92. int iLen = i_pInfo.HeaderMappingData.Count;
  93. for (int iIdx = 0; iIdx < iLen; iIdx++)
  94. {
  95. Dictionary<string, object> dic = i_pInfo.HeaderMappingData[iIdx];
  96. lColumnOrder.Add(dic[BLWording.NAME].ToString());
  97. row.CreateCell(iIdx).SetCellValue(dic[BLWording.DISPLAY].ToString());
  98. }
  99. int iColumnLen = lColumnOrder.Count;
  100. int iDataLen = data.Count;
  101. for (int iDataIdx = 0; iDataIdx < iDataLen; iDataIdx++)
  102. {
  103. row = sheet.CreateRow(iRowIndex++);
  104. Dictionary<string, object> dic = data[iDataIdx];
  105. for (int iColumnIdx = 0; iColumnIdx < iColumnLen; iColumnIdx++)
  106. {
  107. object oData = !i_pInfo.TraslateMap.ContainsKey(lColumnOrder[iColumnIdx]) ? dic[lColumnOrder[iColumnIdx]] : i_pInfo.TraslateMap[lColumnOrder[iColumnIdx]](dic);
  108. if (oData is bool)
  109. {
  110. row.CreateCell(iColumnIdx).SetCellValue(Convert.ToBoolean(oData, CultureInfo.CurrentCulture));
  111. }
  112. else if (oData is DateTime)
  113. {
  114. row.CreateCell(iColumnIdx).SetCellValue(Convert.ToDateTime(oData, CultureInfo.CurrentCulture));
  115. }
  116. else if (TypeCheckerHelper.IsNumeric(oData))
  117. {
  118. row.CreateCell(iColumnIdx).SetCellValue(Convert.ToDouble(oData, CultureInfo.CurrentCulture));
  119. }
  120. else
  121. {
  122. if (oData != null)
  123. {
  124. row.CreateCell(iColumnIdx).SetCellValue(oData.ToString());
  125. }
  126. else
  127. {
  128. row.CreateCell(iColumnIdx);
  129. }
  130. }
  131. }
  132. }
  133. int count = iDataLen + 1;
  134. for (int j = 0; j < count; j++)
  135. {
  136. sheet.AutoSizeColumn(j);
  137. }
  138. }
  139. var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, sPath);
  140. var fileName = System.IO.Path.Combine(path, sFileName);
  141. if (!Directory.Exists(path))
  142. {
  143. //如果匯出暫存路徑不存在,建立它。
  144. Directory.CreateDirectory(path);
  145. }
  146. using (MemoryStream ms = new MemoryStream())
  147. {
  148. using FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
  149. workbook.Write(fs);
  150. }
  151. success = true;
  152. }
  153. //暫存於伺服器端提供下載檔案路徑
  154. return success;
  155. }
  156. /// <summary>
  157. /// 函式名稱:GetDataTableFromExcelFile
  158. /// 函式說明:匯入
  159. /// 起始作者:Rexxar
  160. /// 起始日期:2017/01/05
  161. /// 最新修改人: Justin
  162. /// 最新修改日: 2017/01/05
  163. /// </summary>
  164. /// <param name="fileName"></param>
  165. /// 參數說明
  166. /// </param>
  167. /// <returns>
  168. /// 回傳
  169. /// </returns>
  170. public static DataTable GetDataTableFromExcelFile(string fileName, string i_sSheetName = null)
  171. {
  172. FileStream fs = null;
  173. DataTable dt = new DataTable();
  174. try
  175. {
  176. IWorkbook wb = null;
  177. fs = File.Open(fileName, FileMode.Open, FileAccess.Read);
  178. switch (Path.GetExtension(fileName).ToUpper(CultureInfo.CurrentCulture))
  179. {
  180. case ".XLS":
  181. {
  182. wb = new HSSFWorkbook(fs);
  183. }
  184. break;
  185. case ".XLSX":
  186. {
  187. wb = new NPOI.XSSF.UserModel.XSSFWorkbook(fs);
  188. }
  189. break;
  190. }
  191. if (wb?.NumberOfSheets > 0)
  192. {
  193. ISheet sheet = (string.IsNullOrEmpty(i_sSheetName)) ? wb.GetSheetAt(0) : wb.GetSheet(i_sSheetName);
  194. if (sheet == null)
  195. {
  196. sheet = wb.GetSheetAt(0);
  197. }
  198. IRow headerRow = sheet.GetRow(0);
  199. //處理標題列
  200. for (int i = headerRow.FirstCellNum; i < headerRow.LastCellNum; i++)
  201. {
  202. dt.Columns.Add(headerRow.GetCell(i).StringCellValue.Trim());
  203. }
  204. IRow row = null;
  205. DataRow dr = null;
  206. CellType ct;
  207. //標題列之後的資料
  208. for (int i = sheet.FirstRowNum + 1; i <= sheet.LastRowNum; i++)
  209. {
  210. dr = dt.NewRow();
  211. row = sheet.GetRow(i);
  212. if (row == null) continue;
  213. for (int j = row.FirstCellNum; j < row.LastCellNum && j < headerRow.LastCellNum; j++)
  214. {
  215. ICell ic = row.GetCell(j);
  216. if (ic == null)
  217. {
  218. dr[j] = DBNull.Value;
  219. }
  220. else
  221. {
  222. ct = ic.CellType;
  223. //如果此欄位格式為公式 則去取得CachedFormulaResultType
  224. if (ct == CellType.Formula)
  225. {
  226. CellType ctFormulaResulat = row.GetCell(j).CachedFormulaResultType;
  227. dr[j] = ctFormulaResulat switch
  228. {
  229. CellType.String => ic.StringCellValue,
  230. _ => throw new NotImplementedException($"No handle row.GetCell(j).CachedFormulaResultType = {ctFormulaResulat}"),
  231. };
  232. }
  233. else if (ct == CellType.Numeric)
  234. {
  235. if (DateUtil.IsCellInternalDateFormatted(row.GetCell(j)) || DateUtil.IsCellDateFormatted(row.GetCell(j)))
  236. {
  237. dr[j] = row.GetCell(j).DateCellValue;
  238. }
  239. else
  240. {
  241. dr[j] = row.GetCell(j).NumericCellValue;
  242. }
  243. }
  244. else if (ct == CellType.String)
  245. {
  246. dr[j] = row.GetCell(j).ToString();
  247. }
  248. else
  249. {
  250. dr[j] = row.GetCell(j).ToString().Replace("$", "", StringComparison.OrdinalIgnoreCase);
  251. }
  252. }
  253. }
  254. dt.Rows.Add(dr);
  255. }
  256. }
  257. fs.Close();
  258. }
  259. finally
  260. {
  261. if (fs != null) fs.Dispose();
  262. }
  263. return dt;
  264. }
  265. /// <summary>
  266. /// Adds the new datarow.
  267. /// </summary>
  268. /// <param name="dt1">The DT1.</param>
  269. /// <param name="dt2">The DT2.</param>
  270. /// <param name="i_iec">The i iec.</param>
  271. /// <returns></returns>
  272. public static IEnumerable<DataRow> AddNewRow(DataTable dt1, DataTable dt2, IEqualityComparer<DataRow> i_iec)
  273. {
  274. return dt1.AsEnumerable().Except(dt2.AsEnumerable(), i_iec);
  275. }
  276. /// <summary>
  277. /// Adds or modify datarow.
  278. /// </summary>
  279. /// <param name="i_dtOld">The i dt old.</param>
  280. /// <param name="i_dtNew">The i dt new.</param>
  281. /// <param name="o_ldrAdd">The o LDR add.</param>
  282. /// <param name="o_ldrModify">The o LDR modify.</param>
  283. public static void AddOrModifyRow(DataTable i_dtOld, DataTable i_dtNew, out List<DataRow> o_ldrAdd, out List<DataRow> o_ldrModify)
  284. {
  285. List<DataRow> ldrResModify = new List<DataRow>();
  286. List<DataRow> ldrResAdd = new List<DataRow>();
  287. IEnumerable<DataRow> ieOld = i_dtOld.AsEnumerable();
  288. IEnumerable<DataRow> ieNew = i_dtNew.AsEnumerable();
  289. foreach (DataRow drNew in ieNew)
  290. {
  291. DataRow drFind = ieOld.FirstOrDefault(f => f[BLWording.UID] != null
  292. && drNew[BLWording.UID] != null
  293. && f[BLWording.UID].ToString() == drNew[BLWording.UID].ToString());
  294. if (drFind != null) // Modify
  295. {
  296. foreach (DataColumn dc in drNew.Table.Columns)
  297. {
  298. if (dc.ColumnName == BLWording.UID)
  299. {
  300. continue;
  301. }
  302. if (drNew[dc.ColumnName] == null && drFind[dc.ColumnName] != null)
  303. {
  304. ldrResModify.Add(drFind);
  305. break;
  306. }
  307. else if (drNew[dc.ColumnName].ToString() != drFind[dc.ColumnName].ToString())
  308. {
  309. ldrResModify.Add(drNew);
  310. break;
  311. }
  312. }
  313. }
  314. else
  315. {
  316. ldrResAdd.Add(drNew);
  317. }
  318. }
  319. o_ldrAdd = ldrResAdd;
  320. o_ldrModify = ldrResModify;
  321. }
  322. }
  323. }