newToExcel.ts 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // +----------------------------------------------------------------------
  2. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  3. // +----------------------------------------------------------------------
  4. // | Copyright (c) 2016~2024 https://www.crmeb.com All rights reserved.
  5. // +----------------------------------------------------------------------
  6. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  7. // +----------------------------------------------------------------------
  8. // | Author: CRMEB Team <admin@crmeb.com>
  9. // +----------------------------------------------------------------------
  10. // import { isEmpty } from 'element-ui/lib/utils/util';
  11. import ExcelJS from 'exceljs'
  12. import * as FileSaver from 'file-saver'
  13. const isEmpty = (val:any) => {
  14. // null or undefined
  15. if (val == null) return true;
  16. if (typeof val === 'boolean') return false;
  17. if (typeof val === 'number') return !val;
  18. if (val instanceof Error) return val.message === '';
  19. switch (Object.prototype.toString.call(val)) {
  20. // String or Array
  21. case '[object String]':
  22. case '[object Array]':
  23. return !val.length;
  24. // Map or Set or File
  25. case '[object File]':
  26. case '[object Map]':
  27. case '[object Set]':
  28. {
  29. return !val.size;
  30. }
  31. // Plain Object
  32. case '[object Object]':
  33. {
  34. return !Object.keys(val).length;
  35. }
  36. }
  37. return false;
  38. }
  39. interface SheetStyle {
  40. properties?: {
  41. tabColor?: { argb: string };
  42. defaultRowHeight?: number;
  43. };
  44. }
  45. type SheetConfig = [string, SheetStyle] | string;
  46. type ExcelData = (string | (string[])[] )[][];
  47. export default function createWorkBook(
  48. header: string[],
  49. title: string | string[],
  50. data: ExcelData,
  51. foot: string | string[],
  52. filename?: string,
  53. sheets?: SheetConfig
  54. ): void {
  55. const letter = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
  56. let lcomun = 1;
  57. let worksheet: ExcelJS.Worksheet;
  58. const workBook: ExcelJS.Workbook = new ExcelJS.Workbook();
  59. let long = header.length;
  60. /**
  61. * 创建工作薄
  62. * @param sheets
  63. */
  64. function createSheets(sheets: SheetConfig | undefined): void {
  65. let sheet: string;
  66. let style: SheetStyle = {};
  67. if (Array.isArray(sheets)) {
  68. sheet = sheets[0];
  69. style = sheets[1] || {};
  70. } else {
  71. sheet = sheets || 'Sheet1';
  72. }
  73. worksheet = workBook.addWorksheet(sheet, style);
  74. }
  75. /**
  76. * 设置表名介绍等
  77. * @param title
  78. * @param long
  79. */
  80. function setTitle(title: string | string[] | undefined, long: number): void {
  81. if (isEmpty(title)) return;
  82. const titles: string[] = Array.isArray(title) ? title : (title as string).split(',');
  83. for (let i = 0; i < titles.length; i++) {
  84. let ti = worksheet.getRow(i + 1);
  85. ti.getCell(1).value = titles[i];
  86. ti.height = 30;
  87. ti.font = { bold: true, size: 20, vertAlign: 'subscript' };
  88. ti.alignment = { vertical: 'bottom', horizontal: 'center' };
  89. ti.outlineLevel = 1;
  90. worksheet.mergeCells(i + 1, 1, i + 1, long);
  91. ti.commit();
  92. lcomun++;
  93. }
  94. }
  95. /**
  96. * 设置表头行
  97. * @param header
  98. */
  99. function setHeader(header: string[]): void {
  100. if (isEmpty(header)) return;
  101. const headerRow = worksheet.getRow(lcomun) as any;
  102. for (let index = 1; index <= header.length; index++) {
  103. headerRow.getCell(index).value = header[index - 1];
  104. }
  105. headerRow.height = 25;
  106. headerRow.width = 50;
  107. headerRow.font = { bold: true, size: 18, vertAlign: 'subscript' };
  108. headerRow.alignment = { vertical: 'bottom', horizontal: 'center' };
  109. headerRow.outlineLevel = 1;
  110. headerRow.commit();
  111. lcomun++;
  112. }
  113. /**
  114. * 导出内容
  115. * @param data
  116. */
  117. function setContent(data: ExcelData): void {
  118. if (isEmpty(data)) return;
  119. console.log(data,'zhe')
  120. for (let h = 0; h < data.length; h++) {
  121. let satarLcomun = lcomun;
  122. let lcomunNow = worksheet.getRow(lcomun);
  123. let hasMerge = false;
  124. let starKey = 0;
  125. let endKey = 0;
  126. /** 循环列 */
  127. //需要操作第几列
  128. let sk = 0;
  129. for (let l = 0; l < data[h].length; l++) {
  130. if (Array.isArray(data[h][l])) {
  131. //数组长度
  132. starKey = sk;
  133. hasMerge = true;
  134. setArrayContent(data[h][l] as (string[])[], sk);
  135. sk = sk + (data[h][l] as string[][])[0].length;
  136. endKey = sk;
  137. } else {
  138. //不是数组
  139. lcomunNow.getCell(getLetter(sk)).value = data[h][l] as string;
  140. lcomunNow.getCell(getLetter(sk)).border = {
  141. top: { style: 'thin' },
  142. left: { style: 'thin' },
  143. bottom: { style: 'thin' },
  144. right: { style: 'thin' }
  145. };
  146. lcomunNow.alignment = { vertical: 'middle', horizontal: 'center' };
  147. sk++;
  148. }
  149. }
  150. if (hasMerge) setMergeLcomun(satarLcomun, lcomun, starKey, endKey);
  151. lcomunNow.height = 25;
  152. lcomunNow.commit();
  153. lcomun++;
  154. }
  155. }
  156. /**
  157. * 占多行的数组
  158. * @param arr
  159. * @param sk
  160. */
  161. function setArrayContent(arr: string[][], sk: number): void {
  162. /**
  163. * 循环二维数组,在循环行
  164. */
  165. let al = arr.length;
  166. let sl = al - 1;
  167. for (let i = 0; i < arr.length; i++) {
  168. let lcomunNow = worksheet.getRow(lcomun);
  169. for(let v = 0; v < arr[i].length; v++) {
  170. lcomunNow.getCell(getLetter(sk + v)).value = arr[i][v];
  171. lcomunNow.getCell(getLetter(sk + v)).border = {
  172. top: { style: 'thin' },
  173. left: { style: 'thin' },
  174. bottom: { style: 'thin' },
  175. right: { style: 'thin' }
  176. };
  177. lcomunNow.alignment = { vertical: 'middle', horizontal: 'center' };
  178. }
  179. lcomunNow.height = 25;
  180. lcomunNow.commit();
  181. if (i < sl) lcomun++;
  182. }
  183. }
  184. /**
  185. * 合并操作
  186. * @param satarLcomun
  187. * @param endLcomun
  188. * @param starKey
  189. * @param endKey
  190. */
  191. function setMergeLcomun(
  192. satarLcomun: number,
  193. endLcomun: number,
  194. starKey: number,
  195. endKey: number
  196. ): void {
  197. for(let ml = 0; ml < long; ml++) {
  198. if (ml < starKey || ml >= endKey) {
  199. worksheet.mergeCells(getLetter(ml) + satarLcomun + ':' + getLetter(ml) + endLcomun);
  200. }
  201. }
  202. }
  203. /**
  204. * 设置表末尾统计备注等
  205. * @param footData
  206. */
  207. function setFoot(footData: string | string[] | undefined): void {
  208. if (isEmpty(footData)) return;
  209. if (Array.isArray(footData)) {
  210. for (let f = 0; f < footData.length; f++) {
  211. let lcomunNow = worksheet.getRow(lcomun);
  212. lcomunNow.getCell(1).value = footData[f];
  213. lcomunNow.getCell(1).border = {
  214. top: { style: 'thin' },
  215. left: { style: 'thin' },
  216. bottom: { style: 'thin' },
  217. right: { style: 'thin' }
  218. };
  219. lcomunNow.alignment = { vertical: 'middle', horizontal: 'left' };
  220. worksheet.mergeCells('A' + lcomun + ':' + getLetter(long - 1) + lcomun);
  221. lcomun++;
  222. }
  223. } else {
  224. let lcomunNow = worksheet.getRow(lcomun);
  225. lcomunNow.getCell(1).value = footData;
  226. lcomunNow.getCell(1).border = {
  227. top: { style: 'thin' },
  228. left: { style: 'thin' },
  229. bottom: { style: 'thin' },
  230. right: { style: 'thin' }
  231. };
  232. lcomunNow.alignment = { vertical: 'middle', horizontal: 'left' };
  233. worksheet.mergeCells('A' + lcomun + ':' + getLetter(long - 1) + lcomun);
  234. }
  235. }
  236. /**
  237. * 处理超过26个字母的列
  238. * @param number
  239. * @returns
  240. */
  241. function getLetter(number: number): string {
  242. if (number < 26) {
  243. return letter[number];
  244. } else {
  245. let n = number % 26;
  246. let l = Math.floor(number / 26) - 1;
  247. return letter[l] + letter[n];
  248. }
  249. }
  250. /**
  251. * 导出下载
  252. * @param filename
  253. */
  254. function saveAndDowloade(filename?: string): void {
  255. const finalFilename = filename || new Date().getTime().toString();
  256. workBook.xlsx.writeBuffer().then(data => {
  257. const blob = new Blob([data], { type: 'application/octet-stream' });
  258. FileSaver.saveAs(blob, finalFilename + '.xlsx');
  259. });
  260. }
  261. createSheets(sheets);
  262. setTitle(title, long);
  263. setHeader(header);
  264. setContent(data);
  265. setFoot(foot);
  266. saveAndDowloade(filename);
  267. }