必须用 readasarraybuffer 且显式指定 type: 'array';sheet_to_json 需加 {defval: null, blankrows: true, range: worksheet['!ref']};日期处理须用 celldates + datenf 或 parse_date_code;大文件须用 web worker 分片解析。

直接用 SheetJS(即 xlsx 库)解析,别碰 readAsBinaryString、别手写 XML 解析、也别依赖后端——浏览器里就能搞定,但必须按新版规范走。
为什么 FileReader 必须用 readAsArrayBuffer
Chrome 98+ 和 Firefox 100+ 已彻底废弃 readAsBinaryString,调用会直接抛 DOMException: Failed to execute 'readAsBinaryString'。而 SheetJS 的 XLSX.read() 只认 ArrayBuffer 或 Uint8Array,传字符串或 base64 会导致日期错乱、公式丢失、合并单元格塌陷。
- ✅ 正确:用
reader.readAsArrayBuffer(file) - ❌ 错误:用
reader.readAsBinaryString(file)或reader.readAsDataURL(file) - ⚠️ 注意:
XLSX.read(data, { type: 'array' })中的type: 'array'必须显式指定,不能省略
sheet_to_json 怎么保留空行和合并结构
默认调用 XLSX.utils.sheet_to_json(worksheet) 会过滤掉全空行,且把 A1:B1 这类合并单元格拆成两个独立单元格(右单元格值为 null),和 Excel 视图完全对不上。
- 加
{ defval: null }:让空单元格输出null而不是被跳过 - 加
{ blankrows: true }:强制保留全空行 - 加
{ range: worksheet['!ref'] }:按实际表格范围读取,避免自动截断(比如 Excel 里写了 100 行,但只填到第 50 行,!ref能确保读到第 100 行) - ⚠️ 合并单元格坐标存在
worksheet['!merges']里,sheet_to_json不处理它,需单独提取并映射
日期字段为什么总差一天,怎么安全处理
Excel 日期本质是序列号(如 44927 = 2023-01-01),SheetJS 默认转成 JS Date 对象,但会按浏览器本地时区解释 —— UTC+8 用户打开一个没带时区信息的文件,就容易少算 8 小时,显示成前一天。
- 读取时加
{ cellDates: true, dateNF: 'yyyy-mm-dd' },让日期字段优先走格式化路径 - 后续判断类型别依赖
cell.t === 'd',改用cell.w(显示文本)或cell.v(原始数值)更稳 - 真要参与计算,用
XLSX.SSF.parse_date_code(cell.v)手动转,别直接new Date(cell.v)
大文件卡死?主线程必须甩给 Web Worker
几万行的 .xlsx 文件解析过程包含 ZIP 解压、XML 流读取、类型推断、共享字符串表重建等 CPU 密集操作,主线程一卡就是 2 秒以上,页面假死、滚动失灵、甚至触发浏览器“终止脚本”提示。
- 主线程只做:获取
file.arrayBuffer(),调用worker.postMessage(buffer, [buffer])零拷贝移交 - Worker 内:用
XLSX.read(buffer, { type: 'array', cellDates: true })解析,禁用cellStyles/bookVBA等无关选项 - 超 5 万行时,用
sheet_to_json({ raw: true, defval: null })得到原始数组,再按每 1 万行切片postMessage回主线程分批渲染 - ⚠️ Worker 里不能用
FileReader、不能访问document、不能调alert,所有异常都靠postMessage({ error: 'xxx' })通知
真正难的不是“能不能读出来”,而是“读出来的数据跟 Excel 里看到的一致吗”——空行、合并、日期、时区、大文件响应,每个点都得按新版规范硬对齐,漏一个就出视觉或业务逻辑偏差。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











