前端读取excel的xlsx文件,支持读取表格中的图片

本例使用react + antd 实现 核心代码没啥区别

核心步骤

  • 读取文件,拿到file对象
  • 处理file中的数据,其中分别包括文本数据以及图片数据
  1. 首先使用Upload组件拿到文件的file对象
<Upload
    accept=".xlsx"
    beforeUpload={(file) => {
   		// 这就拿到了file对象 handleUpload为处理file对象的方法
     	handleUpload(file);
       	return false;
 	}}
    showUploadList={false}
>
    添加
</Upload>
  1. 处理file中的数据

举一个简单的例子,这是一个xlsx文件
在这里插入图片描述

我们引入xlsx这个库,对读取的信息进行处理

import * as XLSX from "xlsx";
......
const handleUpload = async (file: Blob) => {
   
	// 异步读取文件
    const reader = new FileReader();
    reader.onload = (e: any) => {
   
		// 格式化数组
	    const data = new Uint8Array(e.target.result);
	    // 读取文件内容
	    const workbook = XLSX.read(data, {
    type: "array" });
	    // 如果指定了 sheetName,则将其用于查找工作表;否则,使用默认的第一个工作表。
	    const worksheet = workbook.Sheets[workbook.SheetNames[0]];
	    // 将工作表数据转换为 JSON 格式
      	const jsonData: any = XLSX.utils.sheet_to_json(worksheet, {
    header: 1 });
		// 判断所选工作区的内容是否为空
      	if (jsonData.length > 0) {
   
      		const newData: any[] = [];
        	// 第一行默认认为是表头 除开第一行以外都是数据
        	jsonData.slice(1).forEach((item, itemIndex: number) => {
   
         		if (item.length === 0) return false;
		        const obj: any = {
    key: itemIndex };
		        jsonData[0].forEach((header: any, index: any) => {
   
		          obj[header] = item[index];
		        });
		        newData.push(obj);
        	});
        	console.log(newData)
      	} else {
   
      		console.log("没数据");
      	}
	}
    reader.readAsArrayBuffer(file);
}

可以看到打印的数据中, 除了图片列,其他的文本列的数据都正常拿到了

在这里插入图片描述
而头像的数据没有返回图片的信息,仅仅是一个可能是id的字符串,既然是id,那说明这个图片一定可以根据这个id找到

根据xlsx这种类型的文件,官方给出解释
在这里插入图片描述
那么我们可以通过jszip这个库来对xlsx文件进行解析,从而可以拿到所有的xml文件。

try  {
   
	const zip = new JSZip();
	let zipLoadRes = await zip.loadAsync(file);
	console.log(zipLoadRes);
} catch (err) {
   
	console.log("err", err);
}

通过打印数据,可以看到里面出现了图片信息
在这里插入图片描述
可以看到xl文件夹下面包含了在这里插入图片描述
打开其中的cellimages.xml文件可以看到其中几条数据和我们前面拿到的id是一样的,同时各个id还对应了一个rid
在这里插入图片描述
而在 xl/_rels/cellimages.xml.rels 文件下,对应的 rid 下,又分别对应着image的名称
在这里插入图片描述
那么我们就可以一步一步的来根据id,组合出一个id对应的图片对象,代码如下:

	  let imageList: IImageInfo[] = [];
      let implantBlobList = [];
      /** @name 针对嵌入了单元格的图片 */
      const implantFile = zipLoadRes.files["xl/cellimages.xml"];
      if (implantFile) {
   
        const xmlContent = await implantFile.async("string");
        const parser = new DOMParser();
        const xmlDoc = parser.parseFromString(xmlContent, "text/xml");
        if (xmlDoc.getElementsByTagName("parsererror").length > 0) {
   
          console.error(
            "XML 解析错误:",
            xmlDoc.getElementsByTagName("parsererror")[0].textContent
          );
          return;
        }
        // 查找所有的 <etc:cellImage> 标签
        const cellImage = xmlDoc.querySelectorAll("etc\\:cellImage, cellImage");
        cellImage.forEach((cellImage) => {
   
          // 查找 <xdr:pic> 标签
          const picElement = cellImage.querySelector("xdr\\:pic, pic");
          if (picElement) {
   
            let obj: Partial<IImageInfo> = {
   };
            // 查找 <xdr:nvPicPr> 标签
            const nvPicPrElement = picElement.querySelector(
              "xdr\\:nvPicPr, nvPicPr"
            );
            // 查找 <xdr:blipFill> 标签
            const blipFillElement = picElement.querySelector(
              "xdr\\:blipFill, blipFill"
            );

            if (nvPicPrElement && blipFillElement) {
   
              // 查找 <a:blip> 标签
              const blipElement = blipFillElement.querySelector(
                "a\\:blip, blip"
              );
              if (blipElement) {
   
                const embedValue = blipElement.getAttribute("r:embed") || "";
                obj.rid = embedValue;
              }
              // 查找 <xdr:cNvPr> 标签
              const cNvPrElement = nvPicPrElement.querySelector(
                "xdr\\:cNvPr, cNvPr"
              );
              if (cNvPrElement) {
   
                const nameValue = cNvPrElement<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道门十三

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值