1. 技术概述
使用js-xlsx实现纯前端导入excel表格
2.技术详述
出于自动化记账的需求,此次项目要求能够完成对用户的excel账单的导入和读取,出于分工和功能划分的考虑,最后决定由前端web来实现这个功能。
通过在网上查找了几种纯前端实现excel表格导入的实现方法之后,最后我选择了js-xlsx来实现。
由SheetJS出品的js-xlsx是一款非常方便的只需要纯JS即可读取和导出excel的工具库,功能强大,支持格式众多,支持xls、xlsx、ods等十几种格式。官方github里提供了各种电子表格格式的解析器和编写器,需要jquery依赖,通过Pure-JS cleanroom实现,强调解析和编写的健壮性,跨格式功能与统一的JS表示兼容,以及ES3/ES5浏览器与IE6的兼容性。
3.技术使用中遇到的问题和解决过程。
js-xlsx导入CSV文件的时候会遇到中文乱码的问题,以下是使用官方提供的转换测试网站结果:
可以看到其中的中文全部变成了乱码。
在网上搜索相关问题,查阅相关资料之后发现这是由于文件的编码不对造成的,通过记事本打开,将excel文件另存为,并将编码改为带有BOM的UTF-8即可。
当然用户是上帝,不可能让用户来做转码工作,经过查找,发现官方是有一个叫https://github.com/sheetjs/js-codepage的库来专门处理文件编码的,以下是导入功能的代码:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <script src="http://oss.sheetjs.com/js-xlsx/xlsx.core.min.js"></script> <script src="./js-codepage-master/dist/cptable.full.js"></script> <!-- 引入库文件 --> </head> <body> <input type="file" onchange="importf(this)" /> <div id="demo"></div> <script> var wb;//读取完成的数据 var rABS = false; //是否将文件读取为二进制字符串 var isCSV; function importf(obj) {//导入 if (!obj.files) return; var f = obj.files[0]; var reader = new FileReader(); reader.onload = function (e) { var data = e.target.result; wb = null; if (isCSV) { data = rABS ? new Uint8Array(data) : data; var str = cptable.utils.decode(936, data); wb = XLSX.read(str, { type: "string" }); } if (!wb) { wb = rABS ? XLSX.read(btoa(fixdata(data)), { type: 'base64' }) : XLSX.read(data, { type: 'binary' }); } //wb.SheetNames[0]是获取Sheets中第一个Sheet的名字 //wb.Sheets[Sheet名]获取第一个Sheet的数据 document.getElementById("demo").innerHTML = JSON.stringify(XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]])); }; isCSV = f.name.split(".").reverse()[0] == "csv";//判断是否是 CSV if (rABS) { reader.readAsArrayBuffer(f); } else { reader.readAsBinaryString(f); } obj.value = ""; } function fixdata(data) { //文件流转BinaryString var o = "", l = 0, w = 10240; for (; l < data.byteLength / w; ++l) o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w, l * w + w))); o += String.fromCharCode.apply(null, new Uint8Array(data.slice(l * w))); return o; } </script> </body> </html>
4. 总结
事实证明一个插件之所以广受欢迎不是没有道理的,官方总是为你准备好了各种解决方案,还是要多去自己查阅官方文档。