浏览器环境下JavaScript读写Excel文件报错求助
问题解决:浏览器环境下用SheetJS修改本地Excel文件
核心问题分析
- 浏览器安全限制:
XLSX.readFile("students.xlsx")直接读取本地固定路径文件会失败——浏览器出于安全策略,不允许JavaScript直接访问本地文件系统的指定路径文件,这是同源策略的强制限制。 - require未定义:
require("xlsx")是Node.js的模块加载语法,浏览器环境没有这个机制,必须通过<script>标签引入SheetJS库。 - SheetJS API误用:SheetJS的
worksheet对象没有addRow方法(这是ExcelJS的API),需要先将工作表转成JSON数组,添加数据后再转回工作表格式。
解决方案1:纯前端上传+修改+下载
浏览器无法直接修改本地文件,所以流程为:用户先上传原Excel文件,前端读取并修改数据,最后让用户下载更新后的文件。
完整代码
<!-- 引入SheetJS库 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/xlsx/0.16.9/xlsx.full.min.js"></script> <!-- 文件上传控件 --> <input type="file" id="excelFile" accept=".xlsx,.xls"> <!-- 表单区域 --> <form> <input type="text" id="fullname" placeholder="姓名"> <input type="text" id="grade" placeholder="年级"> <input type="date" id="birthdate"> <textarea id="address" placeholder="地址"></textarea> <input type="tel" id="phonenumber" placeholder="手机号"> <button type="button" id="save">保存数据</button> </form> <script> let workbook = null; // 存储读取后的工作簿 let originalFileName = "students.xlsx"; // 默认文件名 // 监听文件上传,加载原Excel数据 document.getElementById('excelFile').addEventListener('change', function(e) { const file = e.target.files[0]; if (!file) return; originalFileName = file.name; const reader = new FileReader(); reader.onload = function(event) { const data = new Uint8Array(event.target.result); workbook = XLSX.read(data, { type: 'array' }); alert("原Excel文件已加载,可添加数据"); }; reader.readAsArrayBuffer(file); }); // 保存按钮点击事件 document.getElementById('save').addEventListener('click', async function saveStudent() { const XLSX = window.XLSX; // 校验是否已加载原文件 if (!workbook) { alert("请先上传原Excel文件"); return; } // 获取并校验表单数据 const fullname = document.getElementById('fullname').value.trim(); const grade = document.getElementById('grade').value.trim(); const birthdate = document.getElementById('birthdate').value.trim(); const address = document.getElementById('address').value.trim(); const phonenumber = document.getElementById('phonenumber').value.trim(); if (!fullname || !grade || !birthdate || !address || !phonenumber) { alert('请填写所有信息'); return; } // 读取工作表并转成JSON数组 const worksheet = workbook.Sheets["Sheet1"]; const jsonData = XLSX.utils.sheet_to_json(worksheet); // 添加新数据 jsonData.push({ fullname, grade, birthdate: new Date(birthdate).toLocaleDateString(), address, phonenumber }); // 将更新后的JSON转回工作表,替换原工作簿中的Sheet1 const newWorksheet = XLSX.utils.json_to_sheet(jsonData); workbook.Sheets["Sheet1"] = newWorksheet; // 生成并下载更新后的文件 XLSX.writeFile(workbook, originalFileName); // 清空表单 clearInputs(); }); // 清空表单函数 function clearInputs() { document.getElementById('fullname').value = ''; document.getElementById('grade').value = ''; document.getElementById('birthdate').value = ''; document.getElementById('address').value = ''; document.getElementById('phonenumber').value = ''; } </script>
解决方案2:后端配合实现直接修改文件
如果需要直接修改固定路径的本地/服务器文件,必须通过后端语言(如Node.js)处理文件读写,前端通过API发送请求。
后端代码(Node.js)
const express = require('express'); const XLSX = require('xlsx'); const cors = require('cors'); const app = express(); app.use(cors()); // 解决跨域问题 app.use(express.json()); const filePath = './students.xlsx'; // 服务器上的Excel文件路径 // 添加新学生接口 app.post('/api/add-student', (req, res) => { const { fullname, grade, birthdate, address, phonenumber } = req.body; // 读取原Excel文件 const workbook = XLSX.readFile(filePath); const worksheet = workbook.Sheets["Sheet1"]; const jsonData = XLSX.utils.sheet_to_json(worksheet); // 追加新数据 jsonData.push({ fullname, grade, birthdate, address, phonenumber }); // 将更新后的数据写回文件 const newWorksheet = XLSX.utils.json_to_sheet(jsonData); workbook.Sheets["Sheet1"] = newWorksheet; XLSX.writeFile(workbook, filePath); res.json({ success: true, msg: "数据已成功添加" }); }); app.listen(3000, () => console.log('服务器运行在 http://localhost:3000'));
前端代码修改
document.getElementById('save').addEventListener('click', async function saveStudent() { // 获取表单数据 const fullname = document.getElementById('fullname').value.trim(); const grade = document.getElementById('grade').value.trim(); const birthdate = document.getElementById('birthdate').value.trim(); const address = document.getElementById('address').value.trim(); const phonenumber = document.getElementById('phonenumber').value.trim(); if (!fullname || !grade || !birthdate || !address || !phonenumber) { alert('请填写所有信息'); return; } try { // 发送请求到后端接口 const response = await fetch('http://localhost:3000/api/add-student', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fullname, grade, birthdate, address, phonenumber }) }); const result = await response.json(); if (result.success) { alert("数据已成功写入Excel文件"); clearInputs(); } } catch (error) { console.error('请求失败:', error); alert("添加失败,请检查服务器状态"); } }); // 清空表单函数不变 function clearInputs() { document.getElementById('fullname').value = ''; document.getElementById('grade').value = ''; document.getElementById('birthdate').value = ''; document.getElementById('address').value = ''; document.getElementById('phonenumber').value = ''; }
内容的提问来源于stack exchange,提问作者Mm Yy
相关产品推荐
相关产品推荐

