前端实现导出Excel

前端开发中最常见的功能就是导出列表为excel文件,下面是开发中常见的实现方式

后端文件流

文件下载方法

const sourceBlobType = {
  bin: "application/octet-stream",
  avi: "video/x-msvideo",
  wav: "audio/wav",
  mp3: "audio/mpeg",
  gif: "image/gif",
  jpg: "image/jpeg",
  jpeg: "image/jpeg",
  png: "image/png",
  webp: "image/webp",
  htm: "text/html",
  html: "text/html",
  css: "text/css",
  js: "text/javascript",
  json: "application/json",
  pdf: "application/pdf",
  txt: "text/plain",
  doc: "application/msword",
  docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
  xls: "application/vnd.ms-excel",
  xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
  ppt: "application/vnd.ms-powerpoint",
  pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
  rar: "application/x-rar-compressed",
  zip: "application/zip",
  "7z": "application/x-7z-compressed",
};

/**
 * @param {*} data:文件二进制数据流
 * @param {*} filename 文件名
 */
const downloadResources = (data, type, filename) => {
  // 1.设置Blob数据
  const blob = new Blob([data], {
    //文件类型
    type: `${sourceBlobType[type]};charset=utf-8;`,
  });

  //兼容IE11
  if (navigator.appVersion.toString().indexOf(".NET") > 0) {
    window.navigator.msSaveBlob(blob, filename);
  } else {
    const url = window.URL.createObjectURL(blob);
    const link = document.createElement("a");
    link.style.display = "none";
    link.href = url;
    link.setAttribute("download", filename); // 重命名文件
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    window.URL.revokeObjectURL(url); // 释放掉blob对象
  }
};

接口请求

Axios.post(`${IP}/getListData`,data,{
	responseType:'blob',//二进制文件流添加
}).then(res=>{
	const data = res.data
	downloadResources(data,'xlsx','文件下载')
})

纯前端

js类实现

将table标签,tr、td等对json数据进行拼接,然后table输出到表格上实现,这种方法的弊端在于输出的是伪excel,虽说生成xls为后缀的文件,但文件形式上还是html

class JsonToTable {
  constructor(config) {
    this.config = config ? config : {};
    // 允许的header类型,header权重类型
    this.allowHeaderType = ["tr", "th"];
    this.allowHeaderWeightType = ["block", "inline"]; //block为单独的style优先级高 inline为行内样式优先级高
    this.setHeader(this.config);
    this.setBody(this.config);
  }
  //   设置表头
  setHeader(config) {
    const { columns, type, headerStyle, headerStyleWeight } = config;
    const headerType = this.allowHeaderType.includes(type)
      ? type
      : this.allowHeaderType[0];
    const headerWeightType = this.allowHeaderWeightType.includes(
      headerStyleWeight
    )
      ? headerStyleWeight
      : this.allowHeaderWeightType[0];
    const style = headerStyle || {};
    this.headerType = headerType; // header类型
    this.headerWeightType = headerWeightType; // header权重类型
    this.headerStyle = style; // header样式
    this.columns = columns || []; //header列
    this.worksheet = config?.worksheet || "sheet1"; //表格名称
    this.uri = config?.uri || "data:application/vnd.ms-excel;base64,"; //表格前缀
  }
  //   设置表体
  setBody(config) {
    this.dataSource = config?.data || []; //数据
    this.fileName = config?.fileName || this.fileName || "下载"; //文件名
    this.dataStyle = config?.dataStyle || this.dataStyle || {}; //通用的数据样式
    this.dataComputedStyle =
      config?.dataComputedStyle || this.dataComputedStyle || {}; //数据计算样式
  }
  //   获取头部样式
  getHeaderStyle(lineStyle = {}) {
    let style = {};
    if (this.headerWeightType === "inline") {
      style = {
        ...this.headerStyle,
        ...lineStyle,
      };
    } else if (this.headerWeightType === "block") {
      style = {
        ...lineStyle,
        ...this.headerStyle,
      };
    }
    let styleStr = "";
    for (const key in style) {
      styleStr += `${key}:${style[key]};`;
    }
    return styleStr;
  }

  //   处理表体样式
  getBodyStyle(setStyle) {
    let style = {
      ...this.dataStyle,
      ...setStyle,
    };
    let styleStr = "";
    for (const key in style) {
      styleStr += `${key}:${style[key]};`;
    }
    return styleStr;
  }

  getTemplate(tableStr) {
    // 下载的表格模板数据
    const template = `
     <html xmlns:o="urn:schemas-microsoft-com:office:office" 
           xmlns:x="urn:schemas-microsoft-com:office:excel" 
           xmlns="http://www.w3.org/TR/REC-html40">
         <head>
             <meta charset='utf-8' />
             <!--[if gte mso 9]>
                 <xml>
                     <x:ExcelWorkbook>
                         <x:ExcelWorksheets>
                             <x:ExcelWorksheet>
                                 <x:Name>${this.worksheet}</x:Name>
                                 <x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions>
                             </x:ExcelWorksheet>
                         </x:ExcelWorksheets>
                     </x:ExcelWorkbook>
                 </xml>
             <![endif]-->
         </head>
         <body>
            ${tableStr}
         </body>
     </html>`;
    return this.uri + window.btoa(unescape(encodeURIComponent(template)));
  }

  export() {
    let tableStr = `<table><${this.headerType}>`;
    // 添加表头
    for (let i = 0; i < this.columns.length; i++) {
      const item = this.columns[i];
      tableStr += `<td style="${this.getHeaderStyle(item.style)}">${
        item.value
      }</td>`;
    }
    tableStr += `</${this.headerType}>`;
    // 添加表体
    for (let i = 0; i < this.dataSource.length; i++) {
      tableStr += `<tr>`;
      const info = this.dataSource[i];
      for (let j = 0; j < this.columns.length; j++) {
        const item = this.columns[j];
        // 检查是否有样式
        const bodyStyle = this.dataComputedStyle[item.key]
          ? this.dataComputedStyle[item.key](info[item.key])
            ? this.dataComputedStyle[item.key](info[item.key])
            : {}
          : {};
        const style = this.getBodyStyle(bodyStyle);
        tableStr += `<td style=${style}>${info[item.key]}</td>`;
      }
      tableStr += `</tr>`;
    }
    tableStr += `</table>`;
    const template = this.getTemplate(tableStr);
    // 创建下载
    const link = document.createElement("a");
    link.download = this.fileName;
    link.href = template;
    link.click();
    link.remove();
  }
}
类配置
参数说明默认值可选值
columns表头数组[]
type表头的类型trtr,td
headerStyle应用于所有表头的样式{}
headerStyleWeight表头样式采取的权重inlineinline列里样式为主,block通用样式为主
data数据[]
dataStyle应用于所有数据的样式{}
dataComputedStyle应用具体某一列的特殊处理样式{}
worlsheet表格名称(非文件名称)sheet1
uri前缀data:application/vnd.ms-excel;base64
fileName文件名测试表格
columns配置
参数说明是否必传备注
key字段值
value表头显示的文字
style针对这一个表头的样式显示的权重根据headStyleWeight进行判断
dataComputedStyle

注:dataComputedStyle的里面的方法字段是表头的key字段,需要返回样式对象

dataComputedStyle:{
  age(value){
  	return value>25 ? {color:'red'} : {}
  }
}

使用

方式一:直接初始化使用

const dataJson =  [
	{name: "路人甲",phone: "123456",email: "123@123456.com",ge: 20},
	{name: "路人甲",phone: "123456",email: "123@123456.com",ge: 28},
	{name: "路人甲",phone: "123456",email: "123@123456.com",ge: 29},
]
const tableJs = new JsonToTable({
  columns: [
      { key: "name", value: "姓名", style: { color: "red" } },
      { key: "phone", value: "电话" },
      { key: "email", value: "邮箱" },
      { key: "age", value: "年龄" },
    ],
    type: "tr", //tr th
    headerStyle: {
       "font-weight": "bold",
       "font-size": "25px",
       "font-family": "微软雅黑",
       "font-style": "italic",
     },
     headStyleWeight: "inline", //inline,block
     data: dataJson ,
     fileName: "测试文件下载",
     dataStyle: {
       "font-weight": "bold",
     },
     dataComputedStyle: {
       age(value) {
         return value>25 ? {color:'red'} : {}
       },
     },
});
tableJs.export()

方式二:分别注入表头,表体

const dataJson =  [
	{name: "路人甲",phone: "123456",email: "123@123456.com",ge: 20},
	{name: "路人甲",phone: "123456",email: "123@123456.com",ge: 28},
	{name: "路人甲",phone: "123456",email: "123@123456.com",ge: 29},
]
//初始化类
const tableJs = new JsonToTable();
//注入表头配置
tableJs.setHeader({
   columns: [
      { key: "name", value: "姓名", style: { color: "red" } },
      { key: "phone", value: "电话" },
      { key: "email", value: "邮箱" },
      { key: "age", value: "年龄" },
    ],
    type: "tr", //tr th
    headerStyle: {
      "font-weight": "bold",
      "font-size": "25px",
      "font-family": "微软雅黑",
      "font-style": "italic",
    },
    headStyleWeight: "inline", //inline,block
});
//注入表体
tableJs.setBody({
	data:dataJson,
	fileName: "步骤测试",
    dataStyle: {
      "font-weight": "bold",
    },
    dataComputedStyle: {
     age(value) {
        return value>25 ? {color:'red'} : {}
      },
    },
})
//导出
tableJs.export();
  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值