vue集成xlsl实现前端表格导入导出

file.js

javascript 复制代码
import * as XLSX from "xlsx";
// 导入excel文件显示到前端页面
const getTableFileData = async (file, tableColumns) => {
    const data = await readFile(file.raw);
    // 使用 xlsx 解析
    let workbook = XLSX.read(data, {
        type: 'array',
        cellDates: true,
        cellStyles: true
    });
    const sheetName = workbook.SheetNames[0];
    const sheet = workbook.Sheets[sheetName];
    const rawData = XLSX.utils.sheet_to_json(sheet, {
        header: 1,
        defval: ""
    });
    let list = [];
    const [head, ...fileData] = rawData;
    fileData && fileData.map(item => {
        let obj = {};
        tableColumns.map(column => {
            let index = head.indexOf(column.label);
            // 特殊类型字段默认值判断
            let def = column.type === "number" ? null : "";
            obj[column.prop] = index != -1 ? item[index] || def : def;
        })
        list.push(obj)
    })
    return list;
};
const readFile = (file) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onload = (e) => resolve(e.target.result);
        reader.onerror = reject;
        reader.readAsArrayBuffer(file);
    });
};
// 导出页面数据,生成excel文件
const exportTableFile = (tableData, tableColumns, title, fileName) => {
    const wb = XLSX.utils.book_new()
        
    // 顶部合并单元格的标题
    let wsData = title ? [[title]] : []
    
    // 添加表头
    if (tableColumns && tableColumns.length > 0) {
        const headerRow = tableColumns.map(h => h.label || h)
        wsData.push(headerRow)
    }
    
    // 添加数据行
    tableData.forEach(item => {
        if (tableColumns) {
            // 按表头配置提取数据
            const row = tableColumns.map(header => {
                const value = getNestedValue(item, header.prop || header)
                return formatCellValue(value, header.formatter)
            })
            wsData.push(row)
        } else {
            // 如果没有表头配置,直接使用对象值
            const row = Object.values(item)
            wsData.push(row)
        }
    })
    
    // 创建工作表
    const ws = XLSX.utils.aoa_to_sheet(wsData)
    
    // 设置列宽
    if (tableColumns) {
        const colWidths = tableColumns.map(header => ({
            wch: header.width || Math.max(
                (header.label || header).length,
                ...tableData.map(item => {
                    const value = getNestedValue(item, header.prop || header)
                    return String(value || '').length
                })
            ) * 2
        }))
        ws['!cols'] = colWidths
    }
    // 合并标题单元格
    if (title) {
        ws['!merges'] = [
            XLSX.utils.decode_range('A1:Q1') // 合并第一行
        ]
    }
    XLSX.utils.book_append_sheet(wb, ws, 'Sheet1')
    
    // 生成 Excel 文件并下载
    XLSX.writeFile(wb, fileName + ".xlsx");
};
// 获取嵌套对象的值
const getNestedValue = (obj, path) => {
    return path.split('.').reduce((prev, curr) => {
        return prev ? prev[curr] : null
    }, obj)
}

// 格式化单元格值
const formatCellValue = (value, formatter) => {
    if (formatter && typeof formatter === 'function') {
        return formatter(value)
    }
    return value
}
export{
    getTableFileData,
    exportTableFile
}

page.vue

javascript 复制代码
import { getTableFileData, exportTableFile } from "./file.js";
const tableColumns = [
    {
        prop: "index",
        label: "序号"
    },
    {
        prop: "name",
        abel: "名称"
    },
    {
        prop: "age",
        label: "年龄"
    }
];

const importTableData = (file) => {
    getTableFileData(file, tableColumns).then(res => {
        tableList = tableList.concat(res);
    });
};
const exportTableData = () => {
    exportTableFile(tableList, tableColumns, "", "导出文件")
};

file为<input type="file" accept=".xls,.xlsx" /> change选择的文件

相关推荐
恋猫de小郭3 小时前
AI 可以让 WIFI 实现监控室内人体位置和姿态,无需摄像头?
前端·人工智能·ai编程
哀木4 小时前
给自己整一个 claude code,解锁编程新姿势
前端
程序员鱼皮4 小时前
GitHub 关注突破 2w,我总结了 10 个涨星涨粉技巧!
前端·后端·github
UrbanJazzerati4 小时前
Vue3 父子组件通信完全指南
前端·面试
是一碗螺丝粉4 小时前
5分钟上手LangChain.js:用DeepSeek给你的App加上AI能力
前端·人工智能·langchain
wuhen_n4 小时前
双端 Diff 算法详解
前端·javascript·vue.js
UrbanJazzerati4 小时前
Vue 3 纯小白快速入门指南
前端·面试
雮尘4 小时前
手把手带你玩转Android gRPC:一篇搞定原理、配置与客户端开发
android·前端·grpc
光影少年4 小时前
说说闭包的理解和应用场景?
前端·javascript·掘金·金石计划
是一碗螺丝粉4 小时前
LangChain 核心组件深度解析:模型与提示词模板
前端·langchain·aigc