// ExportHunnanExcel.js import * as XLSX from 'xlsx' import XLSX2 from 'xlsx-style' export const ExportHunnanExcel = (saveName, table1Data, table3Data, table22Data, currentYear, jd) => { var merges = [ 'A20:E21', 'A1:A3', 'B1:R3', 'S1:V3', 'A4:V4', 'A5:E5', 'A13:E13', 'G5:H5', 'G6:G9', 'G10:G13', 'G14:G17', 'G18:G21', 'A6:A7', 'B6:B7', 'C6:D7', 'V6:V7', 'H6:H7', 'I6:I7', 'J6:J7', 'K6:K7', 'L6:L7', 'M6:M7', 'N6:N7', 'O6:O7', 'P6:P7', 'Q6:Q7', 'R6:R7', 'S6:S7', 'T6:T7', 'U6:U7', 'H8:H9', 'I8:I9', 'J8:J9', 'K8:K9', 'L8:L9', 'M8:M9', 'N8:N9', 'O8:O9', 'P8:P9', 'Q8:Q9', 'R8:R9', 'S8:S9', 'T8:T9', 'U8:U9', 'V8:V9', 'H10:H11', 'I10:I11', 'J10:J11', 'K10:K11', 'L10:L11', 'M10:M11', 'N10:N11', 'O10:O11', 'P10:P11', 'Q10:Q11', 'R10:R11', 'S10:S11', 'T10:T11', 'U10:U11', 'V10:V11', 'H12:H13', 'I12:I13', 'J12:J13', 'K12:K13', 'L12:L13', 'M12:M13', 'N12:N13', 'O12:O13', 'P12:P13', 'Q12:Q13', 'R12:R13', 'S12:S13', 'T12:T13', 'U12:U13', 'V12:V13', 'H14:H15', 'I14:I15', 'J14:J15', 'K14:K15', 'L14:L15', 'M14:M15', 'N14:N15', 'O14:O15', 'P14:P15', 'Q14:Q15', 'R14:R15', 'S14:S15', 'T14:T15', 'U14:U15', 'V14:V15', 'H16:H17', 'I16:I17', 'J16:J17', 'K16:K17', 'L16:L17', 'M16:M17', 'N16:N17', 'O16:O17', 'P16:P17', 'Q16:Q17', 'R16:R17', 'S16:S17', 'T16:T17', 'U16:U17', 'V16:V17', 'H18:H19', 'I18:I19', 'J18:J19', 'K18:K19', 'L18:L19', 'M18:M19', 'N18:N19', 'O18:O19', 'P18:P19', 'Q18:Q19', 'R18:R19', 'S18:S19', 'T18:T19', 'U18:U19', 'V18:V19', 'H20:H21', 'I20:I21', 'J20:J21', 'K20:K21', 'L20:L21', 'M20:M21', 'N20:N21', 'O20:O21', 'P20:P21', 'Q20:Q21', 'R20:R21', 'S20:S21', 'T20:T21', 'U20:U21', 'V20:V21', 'A8:A9', 'B8:B9', 'C8:D9', 'E8:E9', 'A10:A11', 'B10:B11', 'C10:D11', 'E10:E11', 'A14:A15', 'B14:C15', 'D14:E15', 'A16:A17', 'B16:C17', 'D16:E17', 'A18:A19', 'B18:C19', 'D18:E19', 'E6:E7' ] // 'F5:F21', 'A12:E12', 'A20:E21', 'A22:V22' // 'C15:C16', 'C6:D7', , 'C9:D10', 'B14:C14', 'B15:C16', , 'D14:E14', 'D15:E16', , , // 遍历table22Data,插入合并的行 var arr = [] table22Data = table22Data.map((v, i) => { v[14] = v[14].slice(0, 2) + '\n' + v[14].slice(2) arr.push(v) arr.push(['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']) }) arr[0].unshift('沈\n阳\n市') arr[2].unshift('沈\n阳\n市') arr[4].unshift('浑\n南\n东\n路') arr[6].unshift('浑\n南\n东\n路') arr[8].unshift('新\n秀\n街') arr[10].unshift('新\n秀\n街') arr[12].unshift('浑\n南\n区\n南\n部') arr[14].unshift('浑\n南\n区\n南\n部') var table2Data = arr var tableTitle = [[`${currentYear}年浑南区“蓝天计划”挂图作战`]] var table1Title = [[`浑南区${currentYear}蓝天保卫战进度`, '', '']] var table3Title = [[`第${jd}季度蓝天保卫战进度`, '', '']] var table2Title = [['时间', '', '1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月', '累积', '同比']] var tableHua = [[`四季度PM2.5控制浓度不高于40微克/立方米`]] // var F5Table = [[''], [''], [''], [''], [''], [''], [''], [''], [''], [''], [''], [''], [''], [''], [''], [''], ['']] // var A20E21 = [['', '', '', '', ''], ['', '', '', '', '']] var wb = XLSX.utils.book_new() // 工作簿对象包含一SheetNames数组,以及一个表对象映射表名称到表对象,XLSX.utils.book_new使用函数创建一个新的工作簿对象 var ws_name = 'SheetJS' var workbook = XLSX.utils.aoa_to_sheet([['']]) /* Write data starting at A2 */ XLSX.utils.sheet_add_aoa(workbook, tableTitle, { origin: 'B1' }) XLSX.utils.sheet_add_aoa(workbook, table1Title, { origin: 'A5' }) XLSX.utils.sheet_add_aoa(workbook, table1Data, { origin: 'A6' }) XLSX.utils.sheet_add_aoa(workbook, table3Title, { origin: 'A13' }) XLSX.utils.sheet_add_aoa(workbook, table3Data, { origin: 'A14' }) // table2Title XLSX.utils.sheet_add_aoa(workbook, table2Title, { origin: 'G5' }) XLSX.utils.sheet_add_aoa(workbook, table2Data, { origin: 'G6' }) XLSX.utils.sheet_add_aoa(workbook, [['截止 月 号']], { origin: 'S1' }) XLSX.utils.sheet_add_aoa(workbook, tableHua, { origin: 'A20' }) // XLSX.utils.sheet_add_aoa(workbook, F5Table, { origin: 'F5' }) // XLSX.utils.sheet_add_aoa(workbook, A20E21, { origin: 'A20' }) // wb.SheetNames.push(sheetName) XLSX.utils.book_append_sheet(wb, workbook, ws_name) // 遍历workbook中的第二个表格中的v,进行比较,找出大的数据,设置为红色 // 合并单元格 if (merges.length > 0) { if (!workbook['!merges']) workbook['!merges'] = [] merges.forEach(item => { workbook['!merges'].push(XLSX.utils.decode_range(item)) }) } let borderAll = { // 单元格外侧框线 top: { style: 'thin', color: { rgb: '000000' } }, bottom: { style: 'thin', color: { rgb: '000000' } }, left: { style: 'thin', color: { rgb: '000000' } }, right: { style: 'thin', color: { rgb: '000000' } } } // 设置单元格高度 if (!workbook['!rows']) workbook['!rows'] = [] // for (let i = 0; i < 3; i++) { // if (i === 0) { // workbook['!rows'][i] = { hpx: 80 } // } else { // workbook['!rows'][i] = { hpx: 150 } // } // } // 设置列宽(这里用到列的数量是用来设置不同列的不同宽度的) if (!workbook['!cols']) workbook['!cols'] = [] for (var i = 0; i <= 21; i++) { if (i === 0 || i === 1 || i === 4 || i === 7) { workbook['!cols'][i] = { wpx: 60 } // 设置列宽,只有最后一列的宽度是不同的 } else if (i === 2 || i === 3) { workbook['!cols'][i] = { wpx: 25 } } else if (i === 6) { workbook['!cols'][i] = { wpx: 40 } } else if (i >= 8 && i <= 20) { workbook['!cols'][i] = { wpx: 30 } } else if (i === 21) { workbook['!cols'][i] = { wpx: 40 } } else { workbook['!cols'][i] = { wpx: 50 } } // else if (i === 5) { // workbook['!cols'][i] = { wpx: 15 } // } } // 样式设置 var info = [] var redObj = { hnPM: [], xxPM: [], hnnbPM: [] } for (let key in workbook) { // 设置共同样式和每行的样式 if (workbook[key] instanceof Object && key !== 'B1') { workbook[key].s = { border: borderAll, alignment: {// 文字居中 //字体水平居中、垂直居中、自动换行 horizontal: 'center', vertical: 'center', wrapText: 1 }, // fill: { //背景色 // fgColor: { rgb: 'C0C0C0' } // }, font: { sz: 10, // 单元格中字体的样式与颜色设置 color: { rgb: '000000' }, bold: false }, bold: true, numFmt: 0 } } if (key === 'B1' || key === 'A1') { workbook[key].s = { border: { top: { style: 'thin', color: { rgb: 'FFFFFF' } }, bottom: { style: 'double', color: { rgb: '3E87C8' } }, left: { style: 'thin', color: { rgb: 'FFFFFF' } }, right: { style: 'thin', color: { rgb: 'FFFFFF' } } }, alignment: {// 文字居中 //字体水平居中、垂直居中、自动换行 horizontal: 'left', vertical: 'bottom', wrapText: 1 }, fill: { // 背景色 fgColor: { rgb: 'FFFFFF' } }, font: { sz: 30, // 单元格中字体的样式与颜色设置 color: { rgb: 'C0391F' }, bold: true }, bold: true, numFmt: 0 } } if (key === 'S1') { workbook[key].s.border = { top: { style: 'thin', color: { rgb: 'FFFFFF' } }, bottom: { style: 'double', color: { rgb: '3E87C8' } }, left: { style: 'thin', color: { rgb: 'FFFFFF' } }, right: { style: 'thin', color: { rgb: 'FFFFFF' } } } workbook[key].s.font = { sz: 10, // 单元格中字体的样式与颜色设置 color: { rgb: '03B3F4' }, bold: true } } if (key === 'A20') { workbook[key].s.border = { top: { style: 'thin', color: { rgb: '000000' } }, bottom: { style: 'thin', color: { rgb: 'FFFFFF' } }, left: { style: 'thin', color: { rgb: 'FFFFFF' } }, right: { style: 'thin', color: { rgb: 'FFFFFF' } } } } if (key === 'A6' || key === 'A7' || key === 'A14' || key === 'A15') { workbook[key].s.border = { top: { style: 'thin', color: { rgb: '000000' } }, bottom: { style: 'thin', color: { rgb: '000000' } }, left: { style: 'thin', color: { rgb: '000000' } }, right: { style: 'thin', color: { rgb: '000000' } }, diagonalDown: true, // 对角线向下方向 diagonal: { color: { rgb: '000000' }, style: 'thin' } // diagonalDown与diagonal必须同时使用 } } // 设置第二个大表格的样式 var str = key.substr(1, 2) if (['6', '10', '14', '18'].includes(str)) { workbook[key].s.fill = { // 绿色背景色 fgColor: { rgb: '67FF6E' } } } if (['8', '12', '16', '20'].includes(str)) { workbook[key].s.fill = { // 黄色背景色 fgColor: { rgb: 'FFFF00' } } } // 浅蓝色的单元格 if (key.replace(/[^A-Z]/ig, '') === 'B' || key.replace(/[^A-Z]/ig, '') === 'E') { workbook[key].s.fill = { // 背景色 fgColor: { rgb: '00B0F0' } } // workbook[key].s.font.color = { // 字体颜色 // rgb: '60A2BC' // } } if (key.replace(/[^A-Z]/ig, '') === 'A' || key.replace(/[^A-Z]/ig, '') === 'G') { workbook[key].s.fill = { // 背景色 fgColor: { rgb: 'FFFFFF' } } } // 进度那一列的单元格 if (key.replace(/[^A-Z]/ig, '') === 'C' || key.replace(/[^A-Z]/ig, '') === 'D') { workbook[key].s.fill = { // 背景色 fgColor: { rgb: 'FFFF00' } } } // 三个表头 var reg = /[A|B|C]/ if (str === '5' || ((reg.test(key)) && str === '13')) { workbook[key].s.fill = { // 背景色 fgColor: { rgb: 'FFFFFF' } } workbook[key].s.font.color = { // 字体颜色 rgb: '000000' } workbook['!rows'].push({ hpx: 80 }) } // 给表的title设置样式 if (key === 'B1' || key === 'A1') { // workbook[key].s.font.sz = 25 workbook[key].s.fill = { // 背景色 fgColor: { rgb: 'FFFFFF' } } } if (key === 'S1') { workbook[key].s.font.sz = 15 workbook[key].s.alignment = {// 文字居中 //字体水平居中、垂直靠下、自动换行 horizontal: 'center', vertical: 'bottom', wrapText: 1 } workbook[key].s.font.color = { // 字体颜色 rgb: '03B3F4' } } // 给F5和A20设置背景色白色 // if (key === 'F5' || key === 'A20') { // workbook[key].s.fill = { // 背景色 // fgColor: { rgb: 'FFFFFF' } // } // } // 给表2设置红色样式 var az = key.substr(0, 1) if (str === '8' && az > 'H' && az < 'V') { if (workbook[key].v === '') { info.push(0) } else { info.push(workbook[key].v) } } if (az > 'H' && az < 'V') { if (str === '12') { redObj.hnPM.push(key) } if (str === '16') { redObj.xxPM.push(key) } if (str === '20') { redObj.hnnbPM.push(key) } } } var n = 0 for (let i = 0; i < info.length; i++) { n = info[i] - 0 if (workbook[redObj.hnPM[i]].v - 0 > n) { workbook[redObj.hnPM[i]].s.fill = { // 背景色 fgColor: { rgb: 'FF0000' } } } if (workbook[redObj.xxPM[i]].v - 0 > n) { workbook[redObj.xxPM[i]].s.fill = { // 背景色 fgColor: { rgb: 'FF0000' } } } if (workbook[redObj.hnnbPM[i]].v - 0 > n) { workbook[redObj.hnnbPM[i]].s.fill = { // 背景色 fgColor: { rgb: 'FF0000' } } } } var data = addRangeBorder(workbook['!merges'], workbook) // 合并项添加边框 var filedata = sheet2blob(data) // 将一个sheet转成最终的excel文件的blob对象 openDownloadDialog(filedata, `${saveName}.xlsx`) // 下载报表 } // 为合并项添加边框 function addRangeBorder(range, workbook) { const arr = ['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'] range.forEach(item => { const startColNumber = Number(item.s.r); const endColNumber = Number(item.e.r) // 0-0 const startRowNumber = Number(item.s.c); const endRowNumber = Number(item.e.c) // 0-16 const test = workbook[arr[startRowNumber] + (startColNumber + 1)] // 合并项第一个单元格中的内容 for (let col = startColNumber; col <= endColNumber; col++) { // 0-0 for (let row = startRowNumber; row <= endRowNumber; row++) { // 0-16 workbook[arr[row] + (col + 1)] = test // A1-P1 } } }) return workbook } // 将一个sheet转成最终的excel文件的blob对象 function sheet2blob(sheet, sheetName) { sheetName = sheetName || 'sheet1' var workbook = { SheetNames: [sheetName], Sheets: {} } workbook.Sheets[sheetName] = sheet // 生成excel的配置项 var wopts = { bookType: 'xlsx', // 要生成的文件类型 bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性 type: 'binary' } var wbout = XLSX2.write(workbook, wopts) var blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' }) // 字符串转ArrayBuffer function s2ab(s) { var buf = new ArrayBuffer(s.length) var view = new Uint8Array(buf) for (var i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF return buf } return blob } // 下载报表函数 function openDownloadDialog(url, saveName) { if (typeof url === 'object' && url instanceof Blob) { url = URL.createObjectURL(url) // 创建blob地址 } var aLink = document.createElement('a') aLink.href = url aLink.download = saveName || '' // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效 var event if (window.MouseEvent) event = new MouseEvent('click') else { event = document.createEvent('MouseEvents') event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) } aLink.dispatchEvent(event) }