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.

194 lines
6.4 KiB

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. /* eslint-disable */
  2. import { saveAs } from 'file-saver'
  3. import * as XLSX from 'xlsx'
  4. import * as XLSXStyle from "xlsx-style";
  5. function datenum(v, date1904) {
  6. if (date1904) v += 1462;
  7. var epoch = Date.parse(v);
  8. return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
  9. }
  10. function sheet_from_array_of_arrays(data, opts) {
  11. var ws = {};
  12. var range = {
  13. s: {
  14. c: 10000000,
  15. r: 10000000
  16. },
  17. e: {
  18. c: 0,
  19. r: 0
  20. }
  21. };
  22. for (var R = 0; R != data.length; ++R) {
  23. for (var C = 0; C != data[R].length; ++C) {
  24. if (range.s.r > R) range.s.r = R;
  25. if (range.s.c > C) range.s.c = C;
  26. if (range.e.r < R) range.e.r = R;
  27. if (range.e.c < C) range.e.c = C;
  28. var cell = {
  29. v: data[R][C]
  30. };
  31. if (cell.v == null) continue;
  32. var cell_ref = XLSX.utils.encode_cell({
  33. c: C,
  34. r: R
  35. });
  36. if (typeof cell.v === 'number') cell.t = 'n';
  37. else if (typeof cell.v === 'boolean') cell.t = 'b';
  38. else if (cell.v instanceof Date) {
  39. cell.t = 'n';
  40. cell.z = XLSX.SSF._table[14];
  41. cell.v = datenum(cell.v);
  42. } else cell.t = 's';
  43. ws[cell_ref] = cell;
  44. }
  45. }
  46. if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
  47. return ws;
  48. }
  49. function Workbook() {
  50. if (!(this instanceof Workbook)) return new Workbook();
  51. this.SheetNames = [];
  52. this.Sheets = {};
  53. }
  54. function s2ab(s) {
  55. var buf = new ArrayBuffer(s.length);
  56. var view = new Uint8Array(buf);
  57. for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF;
  58. return buf;
  59. }
  60. export function export_json_to_excel({
  61. multiHeader = [], // 第一行表头
  62. multiHeader2 = [], // 第二行表头
  63. data,
  64. filename, //文件名
  65. merges = [], // 合并
  66. bookType = 'xlsx'
  67. } = {}) {
  68. /* original data */
  69. filename = filename || '列表';
  70. data = [...data]
  71. data.unshift(multiHeader2)
  72. data.unshift(multiHeader)
  73. console.log('data:', data)
  74. var ws_name = "SheetJS";
  75. var wb = new Workbook(),
  76. ws = sheet_from_array_of_arrays(data);
  77. if (merges.length > 0) {
  78. if (!ws['!merges']) ws['!merges'] = [];
  79. merges.forEach(item => {
  80. ws['!merges'].push(XLSX.utils.decode_range(item))
  81. })
  82. }
  83. /* add worksheet to workbook */
  84. wb.SheetNames.push(ws_name);
  85. wb.Sheets[ws_name] = ws;
  86. var wbout = XLSXStyle.write(wb, {
  87. bookType: bookType,
  88. bookSST: false,
  89. type: 'binary'
  90. });
  91. saveAs(new Blob([s2ab(wbout)], {
  92. type: "application/octet-stream"
  93. }), `${filename}.${bookType}`);
  94. }
  95. // 根据dom导出表格
  96. export function exportToExcel(idSelector, fileName, isNew, list, titleNum = 1) {
  97. // 设置导出的内容是否只做解析,不进行格式转换 false:要解析, true:不解析
  98. const xlsxParam = { raw: true }
  99. let table = document.querySelector(idSelector).cloneNode(true);
  100. // 因为element-ui的表格的fixed属性导致多出一个table,会下载重复内容,这里删除掉
  101. if (table.querySelector('.el-table__fixed-right')) {
  102. table.removeChild(table.querySelector('.el-table__fixed-right'));
  103. }
  104. if (table.querySelector('.el-table__fixed')) {
  105. table.removeChild(table.querySelector('.el-table__fixed'));
  106. }
  107. const wb = XLSX.utils.table_to_book(table, xlsxParam)
  108. console.log(wb)
  109. if (isNew) {
  110. for (let i = 0; i < list.length; i++) {
  111. let index = list[i]
  112. delete wb.Sheets['Sheet1']['A' + index]
  113. }
  114. // for (let i = 0; i < wb.Sheets['Sheet1']['!merges'].length; i++) {
  115. // let index = wb.Sheets['Sheet1']['!merges'][i].s.r
  116. // delete wb.Sheets['Sheet1']['A' + index]
  117. // }
  118. }
  119. let range = XLSX.utils.decode_range(wb.Sheets['Sheet1']['!ref']);
  120. let cWidth = [];
  121. for (let C = range.s.c; C < range.e.c; ++C) { //SHEET列
  122. let len = 100; //默认列宽
  123. let len_max = 400; //最大列宽
  124. for (let R = range.s.r; R <= range.e.r; ++R) { //SHEET行
  125. let cell = { c: C, r: R }; //二维 列行确定一个单元格
  126. let cell_ref = XLSX.utils.encode_cell(cell); //单元格 A1、A2
  127. if (wb.Sheets['Sheet1'][cell_ref]) {
  128. // if (R == 0){
  129. if (R < titleNum) {
  130. wb.Sheets['Sheet1'][cell_ref].s = { //设置第一行单元格的样式 style
  131. alignment: {
  132. horizontal: 'center',
  133. vertical: 'center',
  134. },
  135. };
  136. } else {
  137. wb.Sheets['Sheet1'][cell_ref].s = {
  138. alignment: {
  139. horizontal: 'center',
  140. vertical: 'center',
  141. },
  142. };
  143. }
  144. //动态自适应:计算列宽
  145. let va = JSON.parse(JSON.stringify(wb.Sheets['Sheet1'][cell_ref].v));
  146. var card1 = JSON.parse(JSON.stringify(va)).match(/[\u4e00-\u9fa5]/g); //匹配中文
  147. var card11 = "";
  148. if (card1) {
  149. card11 = card1.join("")
  150. }
  151. var card2 = JSON.parse(JSON.stringify(va)).replace(/([^\u0000-\u00FF])/g, ""); //剔除中文
  152. let st = 0;
  153. if (card11) {
  154. // st += card11.length * 16 //中文字节码长度
  155. st += card11.length * 20 //中文字节码长度
  156. }
  157. if (card2) {
  158. // st += card2.length * 8 //非中文字节码长度
  159. st += card2.length * 10 //非中文字节码长度
  160. }
  161. if (st > len) {
  162. len = st;
  163. }
  164. }
  165. }
  166. if (len > len_max) { //最大宽度
  167. len = len_max;
  168. }
  169. cWidth.push({ 'wpx': len }); //列宽
  170. }
  171. wb.Sheets['Sheet1']['!cols'] = cWidth
  172. const wbout = XLSXStyle.write(wb, { bookType: 'xlsx', bookSST: false, type: 'binary' })
  173. try {
  174. saveAs(new Blob([s2ab(wbout)], { type: '' }), `${fileName}.xlsx`)
  175. } catch (e) {
  176. if (typeof console !== 'undefined') {
  177. console.log(e, wbout)
  178. }
  179. }
  180. return wbout
  181. }