当前位置:   article > 正文

.net core Excel导入导出,1W条数据之内很好用的ExcelHelper_.net core memorystream excel

.net core memorystream excel

老样子,先贴码。


数据导出

 只需要两行代码,即可导出数据。

只有一个约定:DisplayName 为列头。 即可导出

如下:

导出效果: 

 导出后的数据:

导出结束!!! 

数据导入,可直接转换对应model

注意:因为导入会往服务器保存excel原本数据,ExcelHelper没有自动清理的本领

 

 只需要一行代码即可。

也是只有一个约定,导入数据Excel的列头 和,和导入Model 属性上的  DisplayName 值一致。

如下:

 

效果:

 控制台数据一条条输出:

 ExcelHelper源码:

  1. /// <summary>
  2. /// 和 model displayName 一起使用
  3. /// 导入时只需要核对 列头与displayName值是否一致
  4. /// </summary>
  5. public class ExcelHelper
  6. {
  7. /// <summary>
  8. /// 第一步
  9. /// 上传Excel 并返回上传路径
  10. /// </summary>
  11. /// <param name="files"></param>
  12. /// <param name="directoryName">文件夹名称</param>
  13. /// <returns>
  14. /// 返回路径
  15. /// </returns>
  16. private static string DepositExcel(IFormFile file, string directoryName)
  17. {
  18. //创建需要存放的位置 返回一个准确的路径
  19. var path = CreateDirectory("Upload/Excels/" + directoryName);
  20. //文件名
  21. string fileName = DateTime.Now.Ticks.ToString() + "." + file.FileName.Split('.').Last();
  22. path = path + "/" + fileName;
  23. if (File.Exists(path))
  24. {
  25. File.Delete(path);
  26. }
  27. using (var stream = new FileStream(path, FileMode.CreateNew))
  28. {
  29. file.CopyTo(stream);
  30. }
  31. return path;
  32. }
  33. /// <summary>
  34. /// 第二步
  35. /// 得到Excel 内容
  36. /// </summary>
  37. /// <param name="path"></param>
  38. /// <returns></returns>
  39. private static ISheet GetSheet(string path)
  40. {
  41. ISheet sheet;
  42. using (var file = new FileStream(path, FileMode.Open, FileAccess.Read))
  43. {
  44. MemoryStream ms = new MemoryStream();
  45. if (Path.GetExtension(path) == ".xls")
  46. {
  47. HSSFWorkbook workbook = new HSSFWorkbook(file);
  48. //获取一个sheetName
  49. sheet = workbook.GetSheetAt(0);
  50. }
  51. else
  52. {
  53. XSSFWorkbook workbook = new XSSFWorkbook(file);
  54. //获取一个sheetName
  55. sheet = workbook.GetSheetAt(0);
  56. }
  57. }
  58. return sheet;
  59. }
  60. /// <summary>
  61. /// 第三步
  62. /// 根据Excel 内容得到想要的List
  63. /// </summary>
  64. /// <typeparam name="T"></typeparam>
  65. /// <param name="sheet"></param>
  66. /// <param name="headNum"></param>
  67. /// <returns></returns>
  68. private static List<T> GetList<T>(ISheet sheet, int headNum)
  69. {
  70. List<T> list = new List<T>();
  71. Dictionary<int, string> dict = new Dictionary<int, string>();
  72. //获得列名所对应的字段名
  73. var propertys = GetPropertyByType<T>(false);
  74. //得到每个字段对应的序号
  75. IRow head = sheet.GetRow(headNum);
  76. for (int i = 0; i < head.LastCellNum; i++)
  77. {
  78. ICell cell = head.GetCell(i);
  79. if (propertys.ContainsKey(cell.StringCellValue.Trim()))
  80. {
  81. dict.Add(i, propertys[cell.StringCellValue.Trim()]);
  82. }
  83. }
  84. if (dict.Count != head.LastCellNum)
  85. {
  86. throw new Exception("Import tables head and requirements inconsistency");
  87. }
  88. var type = typeof(T).GetProperties();
  89. int c = 0;
  90. try
  91. {
  92. for (int i = headNum + 1; i <= sheet.LastRowNum; i++)
  93. {
  94. c = i;
  95. IRow row = sheet.GetRow(i);
  96. if (row != null)
  97. {
  98. bool isAddList = true;
  99. T t = Activator.CreateInstance<T>();
  100. for (int j = 0; j < row.LastCellNum; j++)
  101. {
  102. ICell cell = row.GetCell(j);
  103. string name = "";
  104. dict.TryGetValue(j, out name);
  105. if (cell != null)
  106. {
  107. if (cell.CellType == CellType.Blank)//空值
  108. {
  109. isAddList = IsAdd(name, true);
  110. }
  111. else
  112. {
  113. var item = type.FirstOrDefault(m => m.Name == name);
  114. if (item != null)
  115. {
  116. if (item.PropertyType == typeof(DateTime))
  117. {
  118. try
  119. {
  120. if (cell.CellType == CellType.String)
  121. {
  122. var value = Convert.ToDateTime(cell.ToString());
  123. item.SetValue(t, value);
  124. }
  125. else
  126. {
  127. item.SetValue(t, cell.DateCellValue);
  128. }
  129. }
  130. catch
  131. {
  132. throw new Exception($"DateTime{cell.ToString()}格式不正确!");
  133. }
  134. }
  135. else if (item.PropertyType == typeof(int))
  136. {
  137. try
  138. {
  139. item.SetValue(t, Convert.ToInt32(cell.ToString()));
  140. }
  141. catch
  142. {
  143. throw new Exception($"int{cell.ToString()}格式不正确!");
  144. }
  145. }
  146. else if (item.PropertyType == typeof(string))
  147. {
  148. if (cell.CellType == CellType.String)
  149. {
  150. item.SetValue(t, cell.ToString());
  151. isAddList = IsAdd(name, string.IsNullOrEmpty(cell.ToString()));
  152. }
  153. else
  154. {
  155. item.SetValue(t, cell.NumericCellValue.ToString());
  156. }
  157. }
  158. else if (item.PropertyType == typeof(decimal?) || item.PropertyType == typeof(decimal))
  159. {
  160. if (cell != null)
  161. {
  162. try
  163. {
  164. var value = 0m;
  165. if (cell.CellType == CellType.String)
  166. {
  167. value = Convert.ToDecimal(cell.ToString());
  168. }
  169. else
  170. {
  171. value = Convert.ToDecimal(cell.NumericCellValue);
  172. }
  173. item.SetValue(t, value);
  174. isAddList = IsAdd(name, value == 0);
  175. }
  176. catch
  177. {
  178. throw new Exception($"decimal{cell.ToString()}格式不正确!");
  179. }
  180. }
  181. }
  182. }
  183. }
  184. if (isAddList == false)
  185. {
  186. break;
  187. }
  188. }
  189. }
  190. if (isAddList)
  191. {
  192. list.Add(t);
  193. }
  194. }
  195. }
  196. }
  197. catch (Exception e)
  198. {
  199. throw e;
  200. }
  201. return list;
  202. }
  203. private static bool IsAdd(string name, bool isOk)
  204. {
  205. bool result = true;
  206. string[] isNotStrs = { };
  207. if (isNotStrs.Contains(name) && isOk)
  208. {
  209. result = false;
  210. }
  211. return result;
  212. }
  213. #region 辅助方法
  214. /// <summary>
  215. /// 创建目录
  216. /// </summary>
  217. /// <param name="directoryPath">目录路径</param>
  218. private static string CreateDirectory(string directoryPath = "")
  219. {
  220. var path = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Content");
  221. if (!string.IsNullOrEmpty(directoryPath))
  222. {
  223. if (directoryPath.Substring(0, 1) != "/")
  224. {
  225. directoryPath = "/" + directoryPath;
  226. }
  227. path += directoryPath;
  228. }
  229. if (!Directory.Exists(path))
  230. {
  231. Directory.CreateDirectory(path);
  232. }
  233. return path;
  234. }
  235. /// <summary>
  236. /// 获得Excel列名
  237. /// </summary>
  238. private static Dictionary<string, string> GetPropertyByType<In>(bool isToExcel)
  239. {
  240. Dictionary<string, string> dict = new Dictionary<string, string>();
  241. var type = typeof(In);
  242. try
  243. {
  244. foreach (var item in type.GetProperties())
  245. {
  246. var displayName = item.GetCustomAttribute<DisplayNameAttribute>();
  247. if (displayName != null)
  248. {
  249. if (isToExcel)
  250. {
  251. dict.Add(item.Name, displayName.DisplayName);
  252. }
  253. else
  254. {
  255. dict.Add(displayName.DisplayName, item.Name);
  256. }
  257. }
  258. }
  259. }
  260. catch (Exception e)
  261. {
  262. throw e;
  263. }
  264. return dict;
  265. }
  266. #endregion
  267. /// <summary>
  268. /// 功能,
  269. /// 导入Excel
  270. /// 列头名和实体的DispName 要一致。
  271. /// </summary>
  272. /// <typeparam name="T">要转换的实体</typeparam>
  273. /// <param name="files">上传的Excel文件</param>
  274. /// <param name="headNum">Excel头部行数</param>
  275. /// <returns>
  276. /// 获得转换后的List 集合
  277. /// </returns>
  278. public static List<T> GetList<T>(IFormFile files, int headNum)
  279. {
  280. List<T> list = new List<T>();
  281. string path = DepositExcel(files, typeof(T).Name);
  282. //得到上传文件内容
  283. ISheet sheet = GetSheet(path);
  284. //转换成List
  285. var t = GetList<T>(sheet, headNum);
  286. if (t != null && t.Count > 0)
  287. {
  288. list.AddRange(t);
  289. }
  290. return list;
  291. }
  292. /// <summary>
  293. /// 生成Excel流数据,
  294. /// return File(memoryStream.ToArray(), "application/vnd.ms-excel", fileName); //vnd.ms 此模式有些不兼容
  295. /// 或者
  296. /// return File(memoryStream.ToArray(), "application/ms-excel", "红包列表.xls")
  297. /// </summary>
  298. /// <typeparam name="T">数据模型</typeparam>
  299. /// <param name="excelType">excel扩展名类型</typeparam>
  300. /// <param name="data">数据集</param>
  301. /// <param name="sheetSize">Excel的单个Sheet的行数,不能超过65535,否则会抛出异常</param>
  302. /// <returns></returns>
  303. public static MemoryStream ToExcel<T>(List<T> data, string excelType = "xls", int sheetSize = 50000)
  304. {
  305. IWorkbook wk;
  306. if (excelType == "xlsx")
  307. {
  308. wk = new XSSFWorkbook();
  309. }
  310. else
  311. {
  312. wk = new HSSFWorkbook();
  313. }
  314. var itemType = Activator.CreateInstance<T>().GetType();
  315. int baseNum = 65535;//单个Sheet最大行数65535
  316. int cNum = data.Count / baseNum;
  317. int myForCount = data.Count % baseNum == 0 ? cNum : cNum + 1;
  318. for (int i = 0; i < myForCount; i++)
  319. {
  320. var list = data.Skip(i * baseNum).Take(baseNum).ToList();
  321. string sheetName = "sheet" + i;
  322. CreateSheet(wk, list, itemType, sheetName);
  323. }
  324. MemoryStream m = new MemoryStream();
  325. wk.Write(m);
  326. return m;
  327. }
  328. /// <summary>
  329. /// 创建并得到一个 sheet
  330. /// </summary>
  331. /// <typeparam name="T"></typeparam>
  332. /// <typeparam name="IN"></typeparam>
  333. /// <param name="wk"></param>
  334. /// <param name="data"></param>
  335. /// <param name="itemType"></param>
  336. /// <param name="sheetName"></param>
  337. /// <param name="sheetSize"></param>
  338. /// <param name="valueHandlerDict"></param>
  339. private static void CreateSheet<T>(IWorkbook wk, List<T> data, Type itemType, string sheetName, int sheetSize = 50000)
  340. {
  341. try
  342. {
  343. ISheet sheet = null;
  344. var headers = GetPropertyByType<T>(true);
  345. sheet = CreateHeaders(wk, headers, sheetName);
  346. if (data.Count > 0)
  347. {
  348. for (var i = 0; i < data.Count; i++)
  349. {
  350. //创建内容
  351. IRow row = sheet.CreateRow(i % sheetSize + 1);
  352. //遍历填充每条数据
  353. int j = 0;
  354. foreach (var item in headers)
  355. {
  356. var p = itemType.GetProperty(item.Key);//获取对应列名
  357. if (p != null)
  358. {
  359. var value = p.GetValue(data[i]);
  360. value = value == null ? string.Empty : value;
  361. ICell cell = row.CreateCell(j);
  362. cell.SetCellValue(value.ToString());
  363. }
  364. j++;
  365. }
  366. }
  367. }
  368. }
  369. catch (Exception ex)
  370. {
  371. throw ex;
  372. }
  373. }
  374. /// <summary>
  375. /// 创建sheet 表头
  376. /// </summary>
  377. /// <param name="wk">workbook</param>
  378. /// <param name="headers">表头</param>
  379. /// <param name="sheetName"></param>
  380. /// <returns>
  381. /// 返回一个sheet
  382. /// </returns>
  383. private static ISheet CreateHeaders(IWorkbook wk, Dictionary<string, string> headers, string sheetName)
  384. {
  385. var sheet = wk.CreateSheet(sheetName);
  386. IRow rowHead = sheet.CreateRow(0);
  387. ICellStyle style = wk.CreateCellStyle();
  388. IFont font = wk.CreateFont();//创建字体样式
  389. font.Boldweight = (short)FontBoldWeight.Bold;
  390. style.SetFont(font);
  391. int i = 0;
  392. foreach (var item in headers)
  393. {
  394. ICell cellHead = rowHead.CreateCell(i);
  395. cellHead.SetCellValue(item.Value);
  396. cellHead.CellStyle = style;
  397. i++;
  398. }
  399. return sheet;
  400. }
  401. }

源码地址:https://github.com/BigMaJx/OOPDemo/blob/master/Common/ExcelHelper.cs

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/216013
推荐阅读
相关标签
  

闽ICP备14008679号