xlsx-js-style前端组装表格数据下载到本地
1.数据格式:
对象:key/value
const data1 = { '合同 主体信息': '{\n "合同编号": "FWTsAEY-S1T-2023-01",\n "项目编号": "FTCG2023000265A",\n "项目名称": "福田区第二人民医院食堂服务采购项直",\n "总计/价款": "6,200,000.00元/年",\n "甲方(采购)单位": "深圳市福田区第二人民医院",\n "甲方法定代表人": "赵蓉",\n "甲方单位地址": "深圳市福田区上梅林中康路25、27号,梅林街道龙尾社区梅亭路1号4栋",\n "乙方(供应)单位": "深圳市润浣餐饮服务管理有限公司",\n "乙方法定代表人": "刘鹏飞",\n "乙方单位地址": "深圳市福田区沙头街道天安社区泰然八路深业泰然大厦24C01,24C02-1",\n "合同签订时间": "2023年8月2日"\n}', '中标 主体信息': '{\n "项目编号": "FWCGHTCG2023000265",\n "项目名称": "福田区第二人民医院食堂服务采购",\n "中标金额": "0.98",\n "甲方(采购)单位": "深圳市福田区第二人民医院",\n "甲方单位地址": "深圳市福田区上梅林中康路27号",\n "乙方(供应)单位": "深圳市润沅餐饮服务管理有限公司",\n "乙方单位地址": "深圳市福田区沙头街道天安社区泰然八路深业泰然大厦24C01、24C02-1",\n "通知书发布时间/公告期限": "2023年08月09日至2023年08月12日",\n "合同签订事宜": null\n}', '合同-中标 主体信息一致性比对': '{\n "偏离情况": "无偏离",\n "判断依据": "中标主体信息与合同主体信息均为undefined,无法进行有效对比"\n}', };
2. 实现效果如图(包含表格样式)
(1)纵向的表格
(2)横向的表格
(3)每截取3个数据为一组的横向排布
3. 具体实现
- 用到插件 "xlsx-js-style": "^1.2.0" + vue3
- 下载:
npm install xlsx-js-style
- 引入:
import * as XLSXStyle from 'xlsx-js-style';
具体代码:
- html:
<el-button type="primary" @click="exportToExcel(data1)">导出</el-button>
- 源数据:
const data1 = { '合同 主体信息': '{\n "合同编号": "FWTsAEY-S1T-2023-01",\n "项目编号": "FTCG2023000265A",\n "项目名称": "福田区第二人民医院食堂服务采购项直",\n "总计/价款": "6,200,000.00元/年",\n "甲方(采购)单位": "深圳市福田区第二人民医院",\n "甲方法定代表人": "赵蓉",\n "甲方单位地址": "深圳市福田区上梅林中康路25、27号,梅林街道龙尾社区梅亭路1号4栋",\n "乙方(供应)单位": "深圳市润浣餐饮服务管理有限公司",\n "乙方法定代表人": "刘鹏飞",\n "乙方单位地址": "深圳市福田区沙头街道天安社区泰然八路深业泰然大厦24C01,24C02-1",\n "合同签订时间": "2023年8月2日"\n}', '中标 主体信息': '{\n "项目编号": "FWCGHTCG2023000265",\n "项目名称": "福田区第二人民医院食堂服务采购",\n "中标金额": "0.98",\n "甲方(采购)单位": "深圳市福田区第二人民医院",\n "甲方单位地址": "深圳市福田区上梅林中康路27号",\n "乙方(供应)单位": "深圳市润沅餐饮服务管理有限公司",\n "乙方单位地址": "深圳市福田区沙头街道天安社区泰然八路深业泰然大厦24C01、24C02-1",\n "通知书发布时间/公告期限": "2023年08月09日至2023年08月12日",\n "合同签订事宜": null\n}', '合同-中标 主体信息一致性比对': '{\n "偏离情况": "无偏离",\n "判断依据": "中标主体信息与合同主体信息均为undefined,无法进行有效对比"\n}', };
- 横向表格代码:
// 导出表格 --- 横向排布的 function exportToExcel2(data) { console.log('表格数据组装', data); const borderStyle = { top: { style: 'thin', color: { rgb: '000000' } }, right: { style: 'thin', color: { rgb: '000000' } }, bottom: { style: 'thin', color: { rgb: '000000' } }, left: { style: 'thin', color: { rgb: '000000' } }, }; const headerStyle = { font: { bold: true }, fill: { fgColor: { rgb: 'e6f4ff' } }, alignment: { vertical: 'center', horizontal: 'center' }, border: borderStyle, }; const contentStyle = { font: { bold: false }, border: borderStyle, alignment: { wrapText: true, vertical: 'top', horizontal: 'left' }, }; // 构建表格数据 const headers = ['标题', ...Object.keys(data)]; const contents = ['内容', ...Object.values(data)]; const sheetData = [headers, contents]; const worksheet = XLSXStyle.utils.aoa_to_sheet(sheetData); // 设置单元格样式 // 设置标题样式 for (let col = 0; col < headers.length; col++) { const cell = worksheet[XLSXStyle.utils.encode_cell({ r: 0, c: col })]; cell.s = headerStyle; } // 设置内容样式 for (let col = 0; col < contents.length; col++) { const cell = worksheet[XLSXStyle.utils.encode_cell({ r: 1, c: col })]; cell.s = col === 0 ? headerStyle : contentStyle; // 第一列使用 headerStyle,其他列使用 contentStyle } // 设置列宽 worksheet['!cols'] = [ { wch: 25 }, // 第一列宽度固定为50 ...Array(headers.length - 1).fill({ wch: 80 }), // 其他列宽度固定为200 ]; // 设置行高 worksheet['!rows'] = [ { hpx: 30 }, // 标题行高度 { hpx: 300 }, // 内容行高度 ]; const workbook = XLSXStyle.utils.book_new(); XLSXStyle.utils.book_append_sheet(workbook, worksheet, '比对结果'); XLSXStyle.writeFile(workbook, '比对结果表格.xlsx'); proxy.$modal.msgSuccess('比对结果已下载到本地'); }
- 纵向表格代码:
// 导出表格 --- 纵向排布的 function exportToExcel(data) { const borderStyle = { top: { style: 'thin', color: { rgb: '000000' } }, right: { style: 'thin', color: { rgb: '000000' } }, bottom: { style: 'thin', color: { rgb: '000000' } }, left: { style: 'thin', color: { rgb: '000000' } }, }; const headerStyle = { font: { bold: true }, fill: { fgColor: { rgb: 'e6f4ff' } }, alignment: { vertical: 'center', horizontal: 'center' }, border: borderStyle, }; const contentStyle = { font: { bold: false }, border: borderStyle, alignment: { wrapText: true, vertical: 'top', horizontal: 'left' }, }; const sheetData = [ [ { v: '标题', s: headerStyle }, { v: '内容', s: headerStyle }, ], ...Object.entries(data).map(([key, value]) => [ { v: key, s: headerStyle }, { v: value, s: contentStyle }, ]), ]; const worksheet = XLSXStyle.utils.aoa_to_sheet(sheetData); // 设置列宽 worksheet['!cols'] = [{ wch: 40 }, { wch: 100 }]; // 设置行高 worksheet['!rows'] = [ { hpx: 40 }, // 标题行高度 ]; const workbook = XLSXStyle.utils.book_new(); XLSXStyle.utils.book_append_sheet(workbook, worksheet, '比对结果'); XLSXStyle.writeFile(workbook, '比对结果表格.xlsx'); proxy.$modal.msgSuccess('比对结果已下载到本地'); }
- 每3个数据为一组的横向排布方法(自行修改数据源)
// 每3项为一组 function exportToExcel3(data) { const borderStyle = { top: { style: 'thin', color: { rgb: '000000' } }, right: { style: 'thin', color: { rgb: '000000' } }, bottom: { style: 'thin', color: { rgb: '000000' } }, left: { style: 'thin', color: { rgb: '000000' } }, }; const headerStyle = { font: { bold: true }, fill: { fgColor: { rgb: 'e6f4ff' } }, alignment: { vertical: 'center', horizontal: 'center' }, border: borderStyle, }; const contentStyle = { font: { bold: false }, border: borderStyle, alignment: { wrapText: true, vertical: 'top', horizontal: 'left' }, }; // 拆分数据为每3项为一组 const dataEntries = Object.entries(data); const sheetData = []; for (let i = 0; i < dataEntries.length; i += 3) { const headers = [...dataEntries.slice(i, i + 3).map(([key]) => key)]; const contents = [...dataEntries.slice(i, i + 3).map(([, value]) => value)]; // const headers = ['标题', ...dataEntries.slice(i, i + 3).map(([key]) => key)]; // const contents = ['内容', ...dataEntries.slice(i, i + 3).map(([, value]) => value)]; sheetData.push(headers, contents); } // 将数据转换为工作表 const worksheet = XLSXStyle.utils.aoa_to_sheet(sheetData); // 设置单元格样式 // 设置标题和内容样式 for (let row = 0; row < sheetData.length; row++) { for (let col = 0; col < sheetData[row].length; col++) { const cell = worksheet[XLSXStyle.utils.encode_cell({ r: row, c: col })]; if (row % 2 === 0) { cell.s = headerStyle; // 偶数行(标题行)使用 headerStyle } else { cell.s = contentStyle; // 奇数行(内容行)使用 contentStyle } } } // 设置列宽 worksheet['!cols'] = Array(sheetData[0].length).fill({ wch: 80 }); // 设置行高 const rowHeights = []; for (let row = 0; row < sheetData.length; row++) { rowHeights.push(row % 2 === 0 ? { hpx: 30 } : { hpx: 300 }); } worksheet['!rows'] = rowHeights; const workbook = XLSXStyle.utils.book_new(); XLSXStyle.utils.book_append_sheet(workbook, worksheet, '比对结果'); XLSXStyle.writeFile(workbook, '比对结果表格.xlsx'); proxy.$modal.msgSuccess('比对结果已下载到本地'); }