关于下载上传的sheetjs

一、背景

需要讲后端返回来的表格数据通过前端设置导出其中某些字段,而且得是xlsx格式的。

那就考虑使用控件SheetJS。如果是几年前,一般来说,保存excel的文件都是后端去处理,处理完成给前端一个接口,前端调用了打开就可以下载到该表格了。但是,因为PC电脑的硬件处理数据的能力越来越好,前端也具备了处理一些大数据的能力。那么处理大数据就需要把相关的情况考虑完全的控件,SheetJS就是这样的一个工具。

二、官网

API Reference | SheetJS Community Edition

三、常用的API

* XLSX.utils.aoa_to_sheet:数组转换为worksheet

* XLSX.utils.json_to_sheet:json对象转换为worksheet

* XLSX.utils.table_to_sheet:表格转换为worksheet

四、两大对象

workbook对象与worksheet对象

可以理解成,workbook对象是整个表格的内容,而worksheet可以理解成表格的数据内容。

直观点看:

复制代码
fileInput.addEventListener("change", (event) => {

     handleFileUpload(event.target.files[0]);

 });
// 文件上传函数
        function handleFileUpload(file) {
            const reader = new FileReader();
            reader.readAsArrayBuffer(file);

            
            // 定义一个加载完成的回调,在 FileReader 完成文件读取操作后被调用。
            reader.onload = (event) => {
                const data = new Uint8Array(event.target.result);
                const workbook = XLSX.read(data, { type: "array" });
                console.log('workbook', workbook)
                // 获取工作表名数组
                const sheetNameArray = workbook.SheetNames;
                // 获取第一个工作表
                const firstSheet = workbook.Sheets[sheetNameArray[0]];
                // 将工作表转换为二维数组
                const sheetDataArray = XLSX.utils.sheet_to_json(firstSheet, {
                    // defval: "" // 配置这个得到对象数组的格式
                    header: 1 // 得到二维数组
                });
                // 调用渲染 Excel 的函数
                renderTable(sheetDataArray);
            };
        }

打印的workbook如下:

显然,多个表,它也能够把它的数据抓出来。

五、上传相关

复制代码
//读取(本地或网络)文件,并创建一个工作薄
let workbook = XLSX.read(data, opts);
//创建一个新的工作簿
let workbook = XLSX.utils.book_new();
//通过抓取页面中的 HTML TABLE 创建工作表
let workbook = XLSX.utils.table_to_book(dom_element, opts);

//将Array<Object>生成为sheet,其中包含基于对象键自动生成的"标题"。
//header 标题使用指定的字段顺序(默认 Object.keys)
//skipHeader 如果为true,则不会在输出中包含标题行
let worksheet = XLSX.utils.json_to_sheet(Array<Object>, {header, skipHeader: false});
//将Array<Array>生成为sheet
let worksheet = XLSX.utils.aoa_to_sheet(Array<Array>);
//接受一个表 DOM 元素并返回一个类似于输入表的工作薄	
let worksheet = XLSX.utils.table_to_sheet(DOM)

//更新sheet,在对应位置进行覆盖
XLSX.utils.sheet_add_json(worksheet, Array<Object>, {header,skipHeader: true, origin: "A2"});
XLSX.utils.sheet_add_aoa(worksheet, Array<Array>, { origin: "A1" });
XLSX.utils.sheet_add_dom(worksheet, DOM, { origin: -1 });

//将sheet工作表添加到该工作薄中
XLSX.utils.book_append_sheet(workbook, worksheet, "sheet名称");

伪代码(开发过程根据自己的业务进行):

复制代码
function excelImport(vv) {
        const eleInput = document.createElement('input');
        eleInput.type = 'file';
        eleInput.style.display = 'block';
        eleInput.onchange = function (e) {
            const file = e.target.files[0];
            let name = file.name
            let suffix = name.substr(name.lastIndexOf("."));
            let reader = new FileReader()
            reader.onload = async (event) => {
                try {
                    // 判断文件类型是否正确
                    if (".xls" != suffix && ".xlsx" != suffix) {
                        cb.utils.alert("选择Excel格式的文件导入!");
                        return false;
                    }
                    let { result } = event.target;
                    // 读取文件
                    let workbook = XLSX.read(result, { type: 'binary' });
                    let data = [];
                    // 循环文件中的每个表
                    let reg = /[\u4e00-\u9fa5|(|)|_$]/g;
                    for (let sheet in workbook.Sheets) {
                        if (workbook.Sheets.hasOwnProperty(sheet)) {
                            let str = XLSX.utils.sheet_to_json(workbook.Sheets[sheet])
                            sheet = sheet.replace(reg, "")
                            // 将获取到表中的数据转化为json格式
                            data = data.concat(str)
                        }
                    }
                    let source = data.splice(3, data.length);
                    insertExcellData(vv, source); //该方法是处理数据的详细方式,根据业务需要来处理。
                } catch (e) {
                    cb.utils.alert("文件类型不正确!");
                }
            }
            reader.readAsBinaryString(file);
            document.body.removeChild(eleInput);
        }
        document.body.appendChild(eleInput);
        eleInput.dispatchEvent(new MouseEvent('click'))
    }

也可以试试直接cdn引入的方式:

复制代码
<html lang="zh-CN">

<head>
    <meta charset="utf-8">
    </meta>
</head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.18.4/xlsx.full.min.js"></script>

<body>
    <!-- 用于点击上传文件的输入字段 -->
    <input type="file" id="fileInput" style="display: none" accept=".xls,.xlsx" required />
    <label for="fileInput" class="label">点击上传文件</label>

    <!-- 用于拖放文件上传的输入字段 -->
    <div id="dropArea">
        <p>拖拽文件至此处</p>
    </div>

    <!-- 用于显示解析后的数据表 -->
    <div id="table-container" style="margin-top: 20px"></div>
    <script>
        const fileInput = document.getElementById("fileInput");
        const dropArea = document.getElementById("dropArea");

        fileInput.addEventListener("change", (event) => {
            handleFileUpload(event.target.files[0]);
        });

        dropArea.addEventListener("drop", (e) => {
            e.preventDefault();
            dropArea.style.border = "2px dashed #ccc";
            const droppedFiles = e.dataTransfer.files;
            handleFileUpload(droppedFiles[0]);
        });

        // 文件上传函数
        function handleFileUpload(file) {
            const reader = new FileReader();
            console.log('file', file)
            reader.readAsArrayBuffer(file);

            
            // 定义一个加载完成的回调,在 FileReader 完成文件读取操作后被调用。
            reader.onload = (event) => {
                console.log('event', event)
                const data = new Uint8Array(event.target.result);
                const workbook = XLSX.read(data, { type: "array" });
                console.log('workbook', workbook)
                // 获取工作表名数组
                const sheetNameArray = workbook.SheetNames;
                // 获取第一个工作表
                const firstSheet = workbook.Sheets[sheetNameArray[0]];
                // 将工作表转换为二维数组
                const sheetDataArray = XLSX.utils.sheet_to_json(firstSheet, {
                    // defval: "" // 配置这个得到对象数组的格式
                    header: 1 // 得到二维数组
                });
                // 调用渲染 Excel 的函数
                renderTable(sheetDataArray);
            };
        }

        // 将数据渲染为一个表格
        function renderTable(sheetDataArray) {
            const table = document.createElement("table");
            table.classList.add("table", "table-striped");

            sheetDataArray.forEach((row) => {
                const tableRow = document.createElement("tr");

                row.forEach((cell) => {
                    const tableCell = document.createElement("td");
                    tableCell.textContent = cell;
                    tableRow.appendChild(tableCell);
                });

                table.appendChild(tableRow);
            });

            // 添加数据表到表格容器
            const tableContainer = document.getElementById("table-container");
            tableContainer.innerHTML = "";
            tableContainer.appendChild(table);
        }

        // 为拖放添加事件监听器
        dropArea.addEventListener("dragover", (e) => {
            e.preventDefault();
            dropArea.style.border = "2px dashed #333";
        });

        dropArea.addEventListener("dragleave", () => {
            dropArea.style.border = "2px dashed #ccc";
        });


    </script>
</body>

</html>

六、下载相关

最重要的代码片段如下:

复制代码
//数据

                let sheet=XLSX.utils.json_to_sheet(arr),
                book=XLSX.utils.book_new();
                XLSX.utils.book_append_sheet(book,sheet,"sheet1");
                // user开头加时间戳的文件名,可以修改成其它名字
                XLSX.writeFile(book,`列表.xls`);

伪代码如下:

复制代码
<div onclick="clickfn()">点击这里</div>
function clickfn() {
            let arr = [
                {
                    '序号': 1,
                    '名字': '张三',
                    '员工号码': '789'
                }
            ]
            let sheet=XLSX.utils.json_to_sheet(arr), //arr 数据需要业务上给与
               book=XLSX.utils.book_new();
               XLSX.utils.book_append_sheet(book,sheet,"sheet1");
               // user开头加时间戳的文件名,可以修改成其它名字
               XLSX.writeFile(book,`列表.xls`);
        }
相关推荐
码云数智-园园4 小时前
优雅分页:Spring Boot 中 Pageable 参数的自动提取与全局复用实践
状态模式
PPPPickup13 小时前
easymall----管理后端分类展示
状态模式
前端不太难16 小时前
HarmonyOS 游戏运行态的完整状态机图
游戏·状态模式·harmonyos
前端不太难2 天前
HarmonyOS 为何用 Ability 约束游戏?
游戏·状态模式·harmonyos
新缸中之脑2 天前
5个AI设计的音乐 UI 比较
人工智能·ui·状态模式
前端不太难2 天前
游戏在 HarmonyOS 上如何“活”?
游戏·状态模式·harmonyos
浮游本尊2 天前
React 18.x 学习计划 - 第十三天:部署与DevOps实践
学习·react.js·状态模式
Vv1997_3 天前
JavaWeb后端全局异常处理
状态模式
小郎君。3 天前
PDF-知识图谱全流程前后端实现【工具已实现,搭建前后端pipline】
pdf·状态模式·知识图谱
前端不太难3 天前
HarmonyOS PC 焦点系统的正确建模方式
华为·状态模式·harmonyos