美文网首页大前端
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