美文网首页大前端
excel.js前端灵活导出数据,导出的单元格下拉选择,不可随意

excel.js前端灵活导出数据,导出的单元格下拉选择,不可随意

作者: jack钱 | 来源:发表于2022-07-11 10:47 被阅读0次
要用到的2个包:
exceljs文档
FileSaver文档(用于保存文件下载)

基本导出案例:

const workbook = new ExcelJS.Workbook();
const worksheet = workbook.addWorksheet('My Sheet');
// 设置列
worksheet.columns = [
    { header: 'Id', key: 'id', width: 10 },
    { header: 'Name', key: 'name', width: 32 },
    { header: 'D.O.B.', key: 'DOB', width: 10 }
];
// 插入数据
worksheet.addRow({ id: 1, name: 'John Doe', DOB: '2022-06-18' });
worksheet.addRow({ id: 2, name: 'Jane Doe', DOB: '2022-06-18' });
// 写入文件
const buffer = await workbook.xlsx.writeBuffer();
FileSaver.saveAs(new Blob([buffer]), `${formatMessage({ id: 'menu.LeaveManagement.WorkforceManagement' }) + '-' + filterDate}.xlsx`)

具体的灵活操作可以参考exceljs文档

如下图,导出后用户只能进行选择单元格值的功能,在文档中搜索 “数据验证”


image.png
image.png
具体案例

有不懂的可以复制属性在文档中搜索

// 导出
const exportExcel = async (selectedRows: any[]) => {
    const workbook = new ExcelJS.Workbook();  // 新建文档
    const worksheet = workbook.addWorksheet('Sheet1', {  //新建工作表
        views: [{ state: 'frozen', xSplit: 4, ySplit: 0 }], // 冻结视图:xSplit:冻结多少列
        properties: { defaultColWidth: 18 } // 默认列宽
    });

    // 列数据
    let _columns = [...columns, ...dateColumns];
    _columns = _columns.filter(item => (!item.hideInTable && item.dataIndex != 'index')).map(item => ({
        header: item.title,
        key: item.dataIndex
    }));
    worksheet.columns = [{  // 第一列增加可选班次对象,导入时对照出id用
        header: '可选班次对象',
        key: 'workShiftObj',
        hidden: true
    }, ..._columns];

    // 批量通过考勤组织id查询考勤班次
    let attendanceIds = selectedRows.map(item => item.attendance_org_id);
    attendanceIds = [...new Set(attendanceIds)];    // 去重
    const { data: workShifts } = await getWorkscheduleByIds(attendanceIds);
    // [{
    //     attendance_org_id: "***"
    //     id: "***"
    //     name: "B"
    //     tenant_id: "***"
    //     type: 1
    // }]

    // 数据
    let _selectedRows = JSON.parse(JSON.stringify(selectedRows));
    for (let i = 0; i < _selectedRows.length; i++) {
        for (let key in _selectedRows[i]) {
            if (_selectedRows[i][key].attendance_work_shift_name) {
                _selectedRows[i][key] = _selectedRows[i][key].attendance_work_shift_name;
            }
        }
        // 给第一列可选班次对象赋值
        _selectedRows[i].workShiftObj = workShifts.find((item: { attendance_org_id: string; }) => item.attendance_org_id == _selectedRows[i].attendance_org_id); // 考勤组织Id一致
    }
    worksheet.addRows(_selectedRows);  // 添加行数据

    // 遍历工作表中具有值的所有行
    worksheet.eachRow(function (row, rowNumber) {
        // 连续遍历所有非空单元格
        row.eachCell(function (cell, colNumber) {
            // console.log('Cell ' + rowNumber + '-' + colNumber + ' = ' + cell.value);
            if (rowNumber > 1 && colNumber > 4) {    // 标题不给范围 前3个列不给范围
                cell.dataValidation = {
                    type: 'list',
                    allowBlank: true, // 允许为空
                    showErrorMessage: true,
                    errorStyle: 'error',
                    formulae: [`"${workShifts.map((item: { name: string; }) => item.name).join(',')}"`]
                    // formulae: ['"One,Two,Three,Four"']
                };
                cell.protection = { locked: false };    // 锁定后 这些列可编辑,不设置的话整个文档都不可编辑了
            }
        });
    });
    // 锁定文档,防止用户操作不该操作的列
    await worksheet.protect('the/pass_word/danger', {
        selectLockedCells: false
    });
    // 写入文件导出
    const buffer = await workbook.xlsx.writeBuffer();
    FileSaver.saveAs(new Blob([buffer]), `${formatMessage({ id: 'menu.LeaveManagement.WorkforceManagement' }) + '-' + filterDate}.xlsx`)
};

导入

async function importExcel(file: Buffer) {
    const workbook = new ExcelJS.Workbook();  // new一下
    await workbook.xlsx.load(file);  // 读文件
    const worksheet = workbook.getWorksheet(1);  // 读sheet1
    const row2: any = worksheet.getRow(2);  // 读第二行数据
    row2.values.forEach((item: any) => {  // 处理第2行的数据
       
    });
    worksheet.eachRow(function (row, rowNumber) {  // 遍历行
        row.eachCell(function (cell, colNumber) {  // 遍历每一行的列
            cell.value  // 列值
        });
     });
}

ExcelJS只能读取buffer类型,所以需要用到文件转buffer
转buffer方法:

function getBuffer(file: File) {
    let reader = new FileReader();
    reader.readAsArrayBuffer(file);
    reader.onload = function (e: any) {
        try {
            let res = e.target.result; // ArrayBuffer
            let buf = Buffer.from(res); // Buffer
            importExcel(buf);
        } catch { }
    }
}

相关文章

网友评论

    本文标题:excel.js前端灵活导出数据,导出的单元格下拉选择,不可随意

    本文链接:https://www.haomeiwen.com/subject/lvaobrtx.html