小工具知识网

当前位置: 首页 > 行业知识 > 前端解析包含图片的excel文件

行业知识

前端解析包含图片的excel文件

2026-11-07 21:17:43 来源:互联网转载

一、前言

1、问题描述

有时候难免会遇到解析excel的情况,现在前端的很多插件都可以实现excel文件中文本内容的解析;但是很多时候excel文件中是带有图片文件的,这个图片文件的提取着实是让人有点头疼的;

本人查阅了很多资料,试了很多方法,结果都是以失败告终!

现决定使用一个迂回战术,完成一次曲线救国,哈哈哈,方法可能不太好,但勉强能够使用,如果有哪位大佬看见,还望指点迷津,跪谢~

2、excel文件

3、实现效果

二、实现思路

  • 第一步,使用XLSX插件,解析excel中的文本内容;
  • 第二步,使用JSZip插件,解析excel中的图片内容;
  • 第三步,将图片数据和文本数据进行整理,封装成我们最终需要的数据格式;

    三、完整代码

                    导入excel                                                        import { ref } from "vue";import JSZip from "jszip"; // 引入jszipimport * as XLSX from "xlsx"; // 引入xlsxconst tableColumnLabel = ref([]); // 获取表头内容const tableData = ref([]); // 表格数据const imageList = ref([]); // 表格图片// 加载按钮的回调async function beforeUpload(file) {  // 解析图片  imageList.value = await getExcelImage(file);  // 解析数据  getExcelData(file);}// 解析数据function getExcelData(file) {  let fileReader = new FileReader(); // 构建fileReader对象  fileReader.readAsArrayBuffer(file); // 读取指定文件内容  // 读取操作完成时  fileReader.onload = function (e) {    try {      let data = e.target.result; // 取得数据data      // console.log(data);      let workbook = XLSX.read(data, { type: "binary" }); // 将data转换成excel工作表数据      // console.log("Excel工作簿", workbook);      const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个工作表      // console.log("第一张工作表", worksheet);      /*       * XLSX.utils.sheet_to_json 输出JSON格式数据       * 获取指定工作表中的数据sheetlist[],整个表中的数据存放在一个数组sheetlist中;       * sheetlist数组中的每个元素均为一个数组rowlist,是每一行的数据;       */      const sheetlist = XLSX.utils.sheet_to_json(worksheet, { header: 1 });      //console.log('sheetlist', sheetlist);      // 封装数据      formatDate(sheetlist);    } catch (e) {      console.log("文件类型不正确");      return;    }  };}// 封装数据function formatDate(sheetlist) {  try {    if (sheetlist.length  {            imageList.push(res); // 将解析出的图片的base64编码值 先存入imageList数组中;          });      }    }  } catch (error) {    console.log(error);  }  // console.log('imageList', imageList);  return imageList;}

    四、准备工作

    1、excel文件

    先准备一个test.xlsx文件,内容如下图所示,主要带上图片就行;

    2、上传组件

    添加一个上传组件,用来上传excel文件;这里采用的是element-plus中的el-upload组件;

       导入excel

    这个上传组件并不是用来做上传,只是利用它来读取我们的excel文件;

    后续我们将在beforeUpload()方法中处理导入的excel文件;

    3、展示组件

    添加一个数据展示组件,用来展示我们解析好的数据;这里采用的是el-table组件;

    注意这里的列是动态生成的,如果是图片的列,则添加img标签显示图片; 

                

    表格需要用到的数据; 

    import { ref } from "vue";const tableColumnLabel = ref([]); // 获取表头内容const tableData = ref([]);        // 表格数据const imageList = ref([]); // 表格图片

    4、安装依赖 

    安装jszip依赖;

    npm install jszip或yarn add jszip

    安装xlsx依赖;

    npm install xlsx或yarn xlsx

    5、引入插件

    在页面中引入需要用的jszip和xlsx两个依赖,可以使用其中的一些方法解析excel文件;

    import JSZip from "jszip";import * as XLSX from "xlsx";

    6、现有效果 

    到此,准备工作完成,现有代码与页面效果如下所示:

                    导入excel                                                        import { ref } from "vue";import JSZip from "jszip";    // 引入jszipimport * as XLSX from "xlsx"; // 引入xlsxconst tableColumnLabel = ref([]); // 获取表头内容const tableData = ref([]);        // 表格数据const imageList = ref([]);        // 表格图片// 加载按钮的回调function beforeUpload(file){  console.log(file);} 

     可以在页面看到一个导入按钮和一个没有任何数据的表格;

    五、实现过程

    1、加载excel

    点击导入excel按钮,选择我们之前准备好的测试excel【test.xlsx】文件,

    导入按钮的回调:

    可以在控制台查看打印输出的结果:

    到这里呢,表示我们的excel已经加载成功了,接下来继续解析读取到的内容即可;

    2、解析图片文件

    (1)解析思路

    • 使用jszip将xlsx文件转成zip文件;
    • 获取zip文件中的图片内容;
    • 将图片信息转base64编码存储;

      解析图片文件我们需要用到jszip这个插件,至于为什么呢?因为我自己试了其他的方法都没有成功;

      首先,我们先将【test.xlsx】转成【test.zip】文件;这里复制一份文件后 直接修改文件扩展名;压缩是看不到效果的;

      点开这个【test.zip】文件,可以看到以下内容,

      打开这个【xl】文件夹,在【media】下存放的是图片文件,worksheets下存放的是文本文件;

      所以,我们想要获取excel中的图片文件,只需访问这个zip文件,然后获取其中【media】文件夹中的内容即可;

      这个zip文件只是简单查看,有助于我们理解的,并没有解析的实际作用,后续删除即可;

      (2)解析过程

        在beforeUpload()回调函数中,编写解析代码;

      // 加载按钮的回调async function beforeUpload(file){  // console.log(file);  let imageList = [];       // 用来存放图片  const zip = new JSZip();  // 创建jszip实例  try {    let zipLoadResult = await zip.loadAsync(file);    // 将xlsx文件转zip文件    console.log("zipLoadResult", zipLoadResult);    // ......  } catch (error) {    console.log(error);  }  return imageList;} 

      在打印输出的结果中,我们可以看到跟之前自行手动转zip后的结果是一致的;图片文件在【xl/media】 路径文件夹中;

      继续解析获取到的files对象,

      // 加载按钮的回调async function beforeUpload(file){  // console.log(file);  let imageList = [];       // 用来存放图片  const zip = new JSZip();  // 创建jszip实例  try {    let zipLoadResult = await zip.loadAsync(file);    // 将xlsx文件转zip文件    // console.log("zipLoadResult", zipLoadResult);    for (const key in zipLoadResult["files"]) {   // 遍历结果中的files对象      if (key.indexOf("media/image") != -1 && !key.dir) {            await zip          .file(zipLoadResult["files"][key].name)          .async("base64")          .then((res) => {            imageList.push(res); // 将解析出的图片的base64编码值 先存入imageList数组中;          });      }    }  } catch (error) {    console.log(error);  }  console.log('imageList', imageList);  return imageList;} 

      可以看到已经成功获取到了两个图片的base64编码值;

      在下方链接中,可以检测取到的bae64是否正确:

      在线Base64转图片

      到此,我们已经取到了excel文件中的图片信息imageList!!

      最后,我们将这段解析excel中图片的代码进行封装,后续在其他地方也可以使用;

      // 加载按钮的回调async function beforeUpload(file){  // 解析图片  imageList.value = await getExcelImage(file);} // 获取图片async function getExcelImage(file){  // console.log(file);  let imageList = [];       // 用来存放图片  const zip = new JSZip();  // 创建jszip实例  try {    let zipLoadResult = await zip.loadAsync(file);    // 将xlsx文件转zip文件    // console.log("zipLoadResult", zipLoadResult);    for (const key in zipLoadResult["files"]) {   // 遍历结果中的files对象      if (key.indexOf("media/image") != -1 && !key.dir) {            await zip          .file(zipLoadResult["files"][key].name)          .async("base64")          .then((res) => {            imageList.push(res); // 将解析出的图片的base64编码值 先存入imageList数组中;          });      }    }  } catch (error) {    console.log(error);  }  // console.log('imageList', imageList);  return imageList;}

      3、解析文本内容

      (1)解析思路

      • 使用FileReader对象来读取excel文件数据data;
      • 使用xlsx获取excel表格数据;
      • 封装sheetlist数据为el-table绑定的数据格式;

        (2)解析过程

        首先,查看FileReader的读取结果;

        async function beforeUpload(file){  // 解析图片  imageList.value = await getExcelImage(file);  // ==================================================================================== //  // 解析数据  let fileReader = new FileReader(); // 构建fileReader对象  fileReader.readAsArrayBuffer(file); // 读取指定文件内容  // 读取操作完成时  fileReader.onload = function (e) {    try {      console.log('data', e);      // ......    } catch (e) {      console.log("文件类型不正确");      return;    }  };}

        其次,使用XLSX.utils.sheet_to_json(worksheet, { header: 1 })方法,处理FileReader读取到的数据data;

        该方法的第一个参数woksheet是必须要传的,值为工作表数据;

        第二个参数可选,用于指定输出excel的格式;

        // 加载按钮的回调async function beforeUpload(file){  // 解析图片  imageList.value = await getExcelImage(file);  // ==================================================================================== //  // 解析数据  let fileReader = new FileReader(); // 构建fileReader对象  fileReader.readAsArrayBuffer(file); // 读取指定文件内容  // 读取操作完成时  fileReader.onload = function (e) {    try {      let data = e.target.result; // 取得数据data      // console.log(data);      let workbook = XLSX.read(data, { type: "binary" }); // 将data转换成excel工作表数据      // console.log("Excel工作簿", workbook);      const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个工作表      // console.log("第一张工作表", worksheet);      /*       * XLSX.utils.sheet_to_json 输出JSON格式数据       * 获取指定工作表中的数据sheetlist[],整个表中的数据存放在一个数组sheetlist中;       * sheetlist数组中的每个元素均为一个数组rowlist,是每一行的数据;       */      const sheetlist = XLSX.utils.sheet_to_json(worksheet, { header: 1 });      console.log(sheetlist,'sheetlist');    } catch (e) {      console.log("文件类型不正确");      return;    }  };} 

        到此为止,我们已经获取到了excel中的文本数据sheetlist,可以在控制台查看如下所示结果;

        外层是一个数组[ ],存放整个excel中的文本数据;

        其中的每个元素均为一个数组[ ],存放的是每一行的数据;

         最后,我们将这段解析excel中文本的代码进行抽离;

        // 加载按钮的回调async function beforeUpload(file){  // 解析图片  imageList.value = await getExcelImage(file);  // 解析数据  getExcelData(file);} // 解析数据function getExcelData(file) {    let fileReader = new FileReader(); // 构建fileReader对象  fileReader.readAsArrayBuffer(file); // 读取指定文件内容  // 读取操作完成时  fileReader.onload = function (e) {    try {      let data = e.target.result; // 取得数据data      // console.log(data);      let workbook = XLSX.read(data, { type: "binary" }); // 将data转换成excel工作表数据      // console.log("Excel工作簿", workbook);      const worksheet = workbook.Sheets[workbook.SheetNames[0]]; // 获取第一个工作表      // console.log("第一张工作表", worksheet);      /*       * XLSX.utils.sheet_to_json 输出JSON格式数据       * 获取指定工作表中的数据sheetlist[],整个表中的数据存放在一个数组sheetlist中;       * sheetlist数组中的每个元素均为一个数组rowlist,是每一行的数据;       */      const sheetlist = XLSX.utils.sheet_to_json(worksheet, { header: 1 });      // console.log('sheetlist', sheetlist);    } catch (e) {      console.log("文件类型不正确");      return;    }  };}

        4、封装数据 

        根据上述内容,excel文件中的图片和文本内容均已取得,如何封装称自己想要的数据格式,可以自行解决了;这里给出我自己在el-table中需要的数据格式封装方法;

        (1)封装思路

        获取到的sheetlist的数据格式如下:

        sheetlist = [  ["name", "age", "avatar"],  ["张三", 18],  ["李四", 20],]

        这并不是我们想要的,期望的格式应该是如下所示:

        最外层是一个数组[ ],里面是每个数据对象itemObj;

        [  {    name:'张三',    age:18,    avatar:"imageUrl"  },  {    name:'李四',    age:20,    avatar:"imageUrl"  },]
        • 首先,我们可以看出sheetlist[0],就是我们想要的el-table的列名;
        • 其次,使用双重循环拆解重组数据;

                  创建一个对象obj,在我们取到sheetlist[0][0],也就是“name”的时候,让obj[“name”] = “张三”,obj[“age”] = “18”,obj[“avatar”] = “”,也就是obj[sheetlist[0][0]] = sheetlist[1][0]、obj[sheetlist[0][1]] = sheetlist[1][1],obj[sheetlist[0][2]] = sheetlist[1][2],以此类推...;

                  这里,刚刚好在给obj[“avatar”] = “”赋值的时候我们可以赋值成imagelist中的值,也就是obj[sheetlist[0][2]] = imagelist[i];注意,imagelist中存储的是base64编码值,别忘记赋值之前进行编码转换,obj[sheetlist[0][2]]  = `data:image/png;base64,${imageList.value[i]};

          • 最后,将新建的obj对象push进el-table绑定的数据源中即可看到结果了;

            (2)实现过程

            我们编写一个封装数据的方法,并在解析好excel的文本数据后调用它;

            获取el-table的列名;

            // 封装数据function formatDate(sheetlist) {  tableColumnLabel.value = sheetlist[0];  // 获取表格列名}

            此时,页面上已经有了显示效果;

            使用双重循环拆解组合数据,这里不做过多解释,大家可以自己写个方法,能够让我参考参考,感觉自己写的也不怎么好;

            // 封装数据function formatDate(sheetlist) {  tableColumnLabel.value = sheetlist[0];  // 获取表格列名  for (let i = 0; i  

             可以在控制台查看每个obj对象的输出结果;

             最后,将这个obj对象push进el-table绑定的数据源中;

            // 封装数据function formatDate(sheetlist) {  tableColumnLabel.value = sheetlist[0];  // 获取表格列名  for (let i = 0; i  

             控制台查看打印输出结果;

            页面最终显示效果;

            5、现有问题

            第一,采取这个方法的前提是得明确知道excel中存放图片的列名;

            第二,图片是按照在excel中的顺序加载的,存在较多未知的隐患;

            第三,谨慎使用!谨慎使用!谨慎使用!

            ======================================================================================================================

            每天进步一点点,本文就做一个简单记录吧~

            暂时也没有更好的方法去读取excel,先这样完成就行;

            谢谢大家,还望哪位大佬指点指点!!

上一篇:数据库同步源码深度解析,实现数据高效一致性的关键步骤指南

下一篇:传奇服务器连不上怎么回事?