写点什么

「趣学前端」读取 Excel 文件内容

作者:叶一一
  • 2022 年 9 月 05 日
    北京
  • 本文字数:4691 字

    阅读完需:约 15 分钟

「趣学前端」读取Excel文件内容

前言

我们在做业务需求的时候,会遇到展示表格的页面,如果只有一个表格,我们可以直接把内容填充到我们的代码中,有时候业务需要不同的分类展示不同的表格,而表格内容是静态的,这类需求,我之前的处理是写个本地 json 文件,每次新增让产品直接把数据录到 json 文件中。有时候业务会把 Excel 表格发给我,我自己进行录入。闲暇的时候我在想,可否通过解析 Excel 文件直接拿到内容呢?


于是我进行了后面的尝试。

Excel 文件的读取

目标功能

我想实现的功能主要有几部分:读取 Excel 文件,识别多个工作表,每个工作表按行将数据放入数组中。最终解析输入如下:


Excel 文件数据


两个工作表:鞋子和裤子




读取的完整数据


{  "fileName": "测试读取.xlsx",  "list": [      {          "sheetName": "鞋子",          "list": [              {                  "goodName": "鞋子A版",                  "size": "37",                  "color": "白色"              },              {                  "goodName": "鞋子B版",                  "size": "38",                  "color": "米色"              },              {                  "goodName": "鞋子C版",                  "size": "38",                  "color": "黑色"              }          ]      },      {          "sheetName": "裤子",          "list": [              {                  "goodName": "裤子A版",                  "size": "S",                  "color": "白色"              },              {                  "goodName": "裤子B版",                  "size": "M",                  "color": "黑色"              },              {                  "goodName": "裤子C版",                  "size": "L",                  "color": "红色"              },              {                  "goodName": "裤子D版",                  "size": "XL",                  "color": "紫色"              }          ]      }  ]}
复制代码


下面我将功能进行细分。

读取 Excel 文件

解析插件


插件:xlsx.core.min.js


官网:https://github.com/sheetjs/sheetjs


读取方法


FileReader 可以读取 Excel 文件内容,它的详细知识点可以查看MDN


我这里使用的 FileReader.readAsBinaryString(file) :开始读取指定的 Blob 中的内容。一旦完成,result 属性中将包含所读取文件的原始二进制数据。

HTML 部分

包括文件上传和数据内容展示两部分,其中文件上传有限制文件类型必须是.xls 或.xlsx 后缀的。


<!DOCTYPE html><html>  <head>    <title>读取excel文件解析内容</title>    <script src="https://cdn.bootcss.com/xlsx/0.11.5/xlsx.core.min.js"></script>    <style>      .warp {        width: 100%;        display: flex;        justify-content: flex-start;        margin-top: 10px;      }      span {        display: block;      }      textarea {        width: 80%;        display: block;      }      .file {        margin-bottom: 15px;      }      .tip {        margin-bottom: 15px;      }    </style>  </head>  <body>    <h3 class="tip">目前只能解析简单的纵向列表数据,支持多个工作表</h3>    <div class="file">      <input type="file" accept=".xls,.xlsx" onchange="uploadFile(this)" id="myFile" />    </div>    <div class="warp">      <span>内容展示:</span>      <textarea id="content" rows="30"></textarea>    </div>  </body></html>
复制代码

上传操作

/** * 文件上传操作 * @param {Element} obj 选择的文件元素 * @return {void} 无 */function uploadFile(obj) {  //导入  if (!obj.files) {    return;  }  let f = obj.files[0];  readExcelFile(obj, f);}
复制代码

文件读取

XLSX 为 sheetjs 插件提供的方法


  • XLSX.read(data, read_opts):尝试解析 data;

  • workbook.SheetNames 是工作簿中工作表的有序列表;

  • wb.Sheets[sheetname] 返回一个代表工作表的对象;

  • XLSX.utils.sheet_to_json 生成不同类型的 JS 对象;


/** @name 读取完成的数据 */var jsonContent;
/** * Excel文件处理方法 * @param {Element} obj 选择的文件元素 * @param {File} f 文件对象 * @return {void} 无 */function readExcelFile(obj, f) { var reader = new FileReader(); reader.onload = function (e) { var data = e.target.result; jsonContent = XLSX.read(data, { type: 'binary', }); /** @name 工作簿中工作表的有序列表 */ const sheetNamesList = jsonContent.SheetNames; const sheetsList = []; sheetNamesList.map(sheetItem => { //jsonContent.Sheets[Sheet名]获取该Sheet的数据 const sheetItemData = jsonContent.Sheets[sheetItem]; sheetsList.push({ sheetName: sheetItem, list: XLSX.utils.sheet_to_json(sheetItemData), // 数据转成json格式 }); }); pageShow(sheetsList, f); }; reader.readAsBinaryString(f);}
复制代码

重组 Excel 文件数据

1、现在的数据 key 为工作表表头的值,是中文名称,可以根据定义的变量名进行数据重组,所以我加了一个变量枚举 renameObj。注:如果多个工作表的表头不一致,可重置 renameObj 对象,并改造 resetTableData 方法内的代码即可;


2、resetTableData 方法会将数据的所有 key 替换成枚举中的变量值;


3、变量 arrayData 为最终的处理之后的 Excel 数据,这时已经将 Excel 文件中的数据处理成了方便前端在页面回显的数据。


/** * 重组key-value * @param {Array} list 需要操作的数组 * @param {Object} renameObj 重命名变量对象 * @return {Array} 合并成的新数组 */function resetTableData(list, renameObj) {  let newList = [].concat(list);  newList.map(item => {    for (let k in item) {      const renameKey = renameObj[k];      item[renameKey] = item[k];      delete item[k];    }  });  return newList; // 最终输出}
/** * 数据回显 * @param {Array} list 数据数组对象 * @param {File} f 文件对象 * @return {void} 无 */function pageShow(list, f) { let jsonData = '';
/** @name 列表展示的变量名枚举 */ const renameObj = { 商品名: 'goodName', 大小: 'size', 颜色: 'color', }; let newList = [].concat(list); newList.map(item => { item.list = resetTableData(item.list, renameObj); }); /** @name 最终的数据 */ let arrayData = { fileName: f.name, list: [].concat(newList), }; const content = document.getElementById('content'); jsonData = JSON.stringify(arrayData, null, 4); content.innerHTML = jsonData;}
复制代码

浏览器展示


完整代码

<!DOCTYPE html><html>  <head>    <title>读取excel文件解析内容</title>    <script src="https://cdn.bootcss.com/xlsx/0.11.5/xlsx.core.min.js"></script>    <style>      .warp {        width: 100%;        display: flex;        justify-content: flex-start;        margin-top: 10px;      }      span {        display: block;      }      textarea {        width: 80%;        display: block;      }      .file {        margin-bottom: 15px;      }      .tip {        margin-bottom: 15px;      }    </style>  </head>  <body>    <h3 class="tip">目前只能解析简单的纵向列表数据,支持多个工作表</h3>    <div class="file">      <input type="file" accept=".xls,.xlsx" onchange="uploadFile(this)" id="myFile" />    </div>    <div class="warp">      <span>内容展示:</span>      <textarea id="content" rows="30"></textarea>    </div>  </body>
<script type="text/javascript"> /** *FileReader读取方法:readAsBinaryString(file):开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。 *@return {void} 无 **/
/** @name 读取完成的数据 */ var jsonContent;
/** * 文件上传操作 * @param {Element} obj 选择的文件元素 * @return {void} 无 */ function uploadFile(obj) { //导入 if (!obj.files) { return; } let f = obj.files[0]; readExcelFile(obj, f); }
/** * Excel文件处理方法 * @param {Element} obj 选择的文件元素 * @param {File} f 文件对象 * @return {void} 无 */ function readExcelFile(obj, f) { var reader = new FileReader(); reader.onload = function (e) { var data = e.target.result; jsonContent = XLSX.read(data, { type: 'binary', }); /** @name 工作簿中工作表的有序列表 */ const sheetNamesList = jsonContent.SheetNames; const sheetsList = []; sheetNamesList.map(sheetItem => { //jsonContent.Sheets[Sheet名]获取该Sheet的数据 const sheetItemData = jsonContent.Sheets[sheetItem]; sheetsList.push({ sheetName: sheetItem, list: XLSX.utils.sheet_to_json(sheetItemData), // 数据转成json格式 }); }); pageShow(sheetsList, f); }; reader.readAsBinaryString(f); }
/** * 重组key-value * @param {Array} list 需要操作的数组 * @param {Object} renameObj 重命名变量对象 * @return {Array} 合并成的新数组 */ function resetTableData(list, renameObj) { let newList = [].concat(list); newList.map(item => { for (let k in item) { const renameKey = renameObj[k]; item[renameKey] = item[k]; delete item[k]; } }); return newList; // 最终输出 }
/** * 数据回显 * @param {Array} list 数据数组对象 * @param {File} f 文件对象 * @return {void} 无 */ function pageShow(list, f) { let jsonData = ''; /** @name 列表展示的变量名枚举 */ const renameObj = { 商品名: 'goodName', 大小: 'size', 颜色: 'color', }; let newList = [].concat(list); newList.map(item => { item.list = resetTableData(item.list, renameObj); }); /** @name 最终的数据 */ let arrayData = { fileName: f.name, list: [].concat(newList), }; const content = document.getElementById('content'); jsonData = JSON.stringify(arrayData, null, 4); content.innerHTML = jsonData; } </script></html>
复制代码

总结

日常开发中,如果觉得哪些不方便、不顺手的,不妨写个小工具协助开发,避免简单的重复的工作占用我们过多的时间。

发布于: 刚刚阅读数: 3
用户头像

叶一一

关注

苍生涂涂,天下缭燎,诸子百家,唯我纵横。 2022.09.01 加入

非职业传道受业解惑前端程序媛,华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。

评论

发布
暂无评论
「趣学前端」读取Excel文件内容_JavaScript_叶一一_InfoQ写作社区