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('比对结果已下载到本地');
}
posted @ 2024-08-22 17:25  行走的蒲公英  阅读(78)  评论(0编辑  收藏  举报