前端导出表格技术总结

前端导出表格技术总结

本文档基于我司需要导出的各种项目和邯郸项目,此文档包含两种导出方法,一种为固定表格导出,一种为自定义表格导出。区别在于固定导出仅可定义宽度,不可定义高度。自定义表格可随意定义宽高。

项目中自定义表格导出为少数,且技术代码复杂。固定表格导出为多数,应用广泛。

1.固定表格导出

VScode项目的终端下,安装两个插件

npm install file-saver xlsx -S      导出表格
npm install --save [email protected]      导出表格

修改:node_modules/xlsx-style/dist/cpexcel.js-----807行

var cpt = './cptable';

在需要用到导出的页面种引入

import XLSX2 from "xlsx";
import XLSX from "xlsx-style";

接下来的html部分和正常的el-table一样,只需要在el-table标签中加上一个自定义id。

然后设置一个按钮,写点击导出事件,再次省略按钮代码

 //导出报表---自定义按钮的点击方法
    setExport2Excel() {
    
    
      let fix = document.querySelector(".el-table__fixed");
      let wb;
      var xlsxParam = {
    
     raw: true };
      if (fix) {
    
    
        wb = XLSX2.utils.table_to_book(
          document.querySelector("#自定义id").removeChild(fix),
          xlsxParam
        );
        document.querySelector("#自定义id").appendChild(fix);
      } else {
    
    
        wb = XLSX2.utils.table_to_book(
          document.querySelector("#自定义id"),
          xlsxParam
        );
      }
        
      //宽度,可以把wb.Sheets.Sheet1打印出来,来了解
      //打印后可以发现  "!cols"  属性是一个数组,所以第一行的宽度其实是 i=0  
      //wpx == width px   此为个人理解,也可能这就是正确理解
      //高度无法设置,如果有文档解决高度,希望补全,,修改方法:改源码
      //很难,本人之前试过三种方法,但都失败了,node_modeles改崩了,只能删掉重新npm install
      for (var i = 0; i < 14; i++) {
    
    
        if (i <= 2) {
    
    
          wb.Sheets.Sheet1["!cols"][i] = {
    
     wpx: 100 };
        } else {
    
    
          wb.Sheets.Sheet1["!cols"][i] = {
    
     wpx: 180 };
        }
      }
      for (const key in wb.Sheets.Sheet1) {
    
    
        if (key.indexOf("!") === -1 && wb.Sheets.Sheet1[key].v) {
    
    
          wb.Sheets.Sheet1[key].s = {
    
    
            font: {
    
    
              sz: 13,
              bold: false,
              color: {
    
    
                rgb: "000000",
              },
            },
            alignment: {
    
    
              horizontal: "center",
              vertical: "center",
              wrap_text: true,
            },
            border: {
    
    
              top: {
    
     style: "thin" },
              bottom: {
    
     style: "thin" },
              left: {
    
     style: "thin" },
              right: {
    
     style: "thin" },
            },
          };
        }
      }
      var data = wb.Sheets.Sheet1;
      var filedata = this.sheet2blob(data);
      this.openDownloadDialog(filedata, "文件名-可自定义.xlsx");
    },
    //第二个方法 修饰第一个函数
    sheet2blob(sheet, sheetName) {
    
    
      sheetName = sheetName || "sheet1";
      var workbook = {
    
    
        SheetNames: [sheetName],
        Sheets: {
    
    },
      };
      workbook.Sheets[sheetName] = sheet;
      var wopts = {
    
    
        bookType: "xlsx",
        bookSST: false,
        type: "binary",
      };
      var wbout = XLSX.write(workbook, wopts);
      var blob = new Blob([s2ab(wbout)], {
    
    
        type: "application/octet-stream",
      });
      function s2ab(s) {
    
    
        var buf = new ArrayBuffer(s.length);
        var view = new Uint8Array(buf);
        for (var i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
        return buf;
      }
      return blob;
    },
    //第三个方法  修饰第一个函数
    openDownloadDialog(url, saveName) {
    
    
      if (typeof url == "object" && url instanceof Blob) {
    
    
        url = URL.createObjectURL(url);
      }
      var aLink = document.createElement("a");
      aLink.href = url;
      aLink.download = saveName || "";
      var event;
      if (window.MouseEvent) event = new MouseEvent("click");
      else {
    
    
        event = document.createEvent("MouseEvents");
        event.initMouseEvent(
          "click",
          true,
          false,
          window,
          0,
          0,
          0,
          0,
          0,
          false,
          false,
          false,
          false,
          0,
          null
        );
      }
      aLink.dispatchEvent(event);
    },

2.自定义表格导出(可定义宽高及各种样式)

此方法是本人修改邯郸项目时,甲方提的需求,自定义表格样式

大致介绍:此方法为单纯的js方式导出,跟页面的展示没有任何关系,仅需要一个导出按钮,点击导出即可。

我的应用思路:页面展示时单纯写一套html代码,用来让甲方看预览,真正的导出数据,导出样式全在js中

所以,省略html代码,详细介绍js方面

项目的终端下 参考链接

npm install xlsx-js-style        导出表格(新方法)

页面中

import XLSXS from "xlsx-js-style";

js部分–本人把导出预览做成了组件,在弹框中预览,点击确认就会下载

  data() {
    
    
    return {
    
    
      dialogVisible: false,  //控制弹框是否显示
      row: {
    
    },		//从父级那里拿到的数据
      body: [],		//表格导出的主体内容
      sheet: [],	//表格的内容、样式等各种东西
    };
  },
    showDianlog(row) {
    
    
      this.dialogVisible = true;
      this.row = row;
      this.playdata(row);//渲染表格的方法
    },
playdata(row) {
    
    
    //表格中的数据,常量data,
    //这里需要注意的点:data中每一个对象的属性值需要一样,data[0]中有value0,则data[1-max]中也要有value0、、、、、需要注意占位符,即键值对的 “空键”,即写上“空键”之后在表格中,它仍然独占一格。
    //这里不是正规的实现方法,我是运用此种方法来画出 我想要的表格样式,如果想要导出表格的数据,直接赋值即可。
    //当然如果想要导出固定表格的数据,用上面的第一种方法即可。
    //此种方法,主要是画出自己或者甲方需要的表格,下面的两行,就是画出来的“假”表头
    //额外说明  "\n" =  换行     "    " =  缩进
    const data = [
        {
    
    
          value0: "报修工单",
          value1: "",
          value2: "",
          value3: "",
          value4: "",
          value5: "档案编号:",
          value6: row.file_no,
        },
        {
    
    
          value0: "设备名称",
          value1: "设备编号",
          value2: "设备地点",
          value3: "报修人",
          value4: "报修时间",
          value5: "维修时效",
          value6: "",
        },
        {
    
    
          value0: row.dev_name,
          value1: row.dev_no,
          value2: row.dev_position,
          value3: row.author,
          value4: row.create_at,
          value5: row.finish_at,
          value6: "",
        },
        ......
    ]//不知道是什么,不过这么写就行
    this.body = data.map((x) => [
        x.value0,
        x.value1,
        x.value2,
        x.value3,
        x.value4,
        x.value5,
        x.value6,
    ]);
    
    //第一行真正的表头
     const header = [
        // 第一行,需要样式,则数组中元素为对象,进行定义样式。
        [
          {
    
    
            v: "附件:",
            t: "s",
            s: {
    
    
              // font 字体属性
              font: {
    
    
                bold: false,
                sz: 12,
                name: "宋体",
              },
              // alignment 对齐方式
              alignment: {
    
    
                vertical: "top", // 垂直居中
                horizontal: "left", // 水平居中
              },
              // border: {
    
    
              //   top: { style: "thin" },
              //   bottom: { style: "thin" },
              //   left: { style: "thin" },
              //   right: { style: "thin" },
              // },
              // fill 颜色填充属性
              // fill: {
    
    
              //   fgColor: { rgb: "ffffff" },
              // },
            },
          },
        ],
      ];
    
    this.body.unshift(...header);  //加入数组的第一项
    this.sheet = XLSXS.utils.aoa_to_sheet(this.body);
    
    //合并单元格:数组,其中每一个对象都需要独立理解
    //s=开始(start)  e=结束(end)  r=行(row)  l=列(clounm)
    //以第一的对象来解释:第4行的第1个标签合并到第4行的第6个单元格
      const merges = [
        {
    
     s: {
    
     r: 4, c: 0 }, e: {
    
     r: 4, c: 6 } },
        {
    
     s: {
    
     r: 5, c: 0 }, e: {
    
     r: 5, c: 6 } },
        {
    
     s: {
    
     r: 8, c: 0 }, e: {
    
     r: 8, c: 6 } },
        {
    
     s: {
    
     r: 9, c: 0 }, e: {
    
     r: 9, c: 6 } },
      ];
      this.sheet["!merges"] = merges; // 添加到sheet中
    
    //列宽,每一列的长度,wpx = width px
      const cols = [
        {
    
     wpx: 70 },
        {
    
     wpx: 70 },
        {
    
     wpx: 75 },
        {
    
     wpx: 70 },
        {
    
     wpx: 75 },
        {
    
     wpx: 75 },
        {
    
     wpx: 75 },
      ];
      this.sheet["!cols"] = cols; // 添加到sheet中
    
    //行高,每一行的高度  hpx = height px
      const rows = [
        {
    
     hpx: 40 },
        {
    
     hpx: 20 },
        {
    
     hpx: 40 },
        {
    
     hpx: 40 },
        {
    
     hpx: 150 },
        {
    
     hpx: 40 },
        {
    
     hpx: 40 },
        {
    
     hpx: 40 },
        {
    
     hpx: 150 },
        {
    
     hpx: 120 },
      ];
      this.sheet["!rows"] = rows; // 添加到sheet中
    
    //编辑特定的某个单元格样式
    //举例
    //后面会把各种属性值都列举出来
      this.sheet["A2"].s = {
    
    
        font: {
    
    
          bold: false,
          sz: 12,
          name: "宋体",
        },
        alignment: {
    
    
          vertical: "center", // 垂直居中
          horizontal: "left", // 水平居中
        },
      };
}
样式属性 子属性 取值
fill patternType "solid" or "none"
fgColor COLOR_SPEC
bgColor COLOR_SPEC
font name "Calibri" // default
sz "11" // font size in points
color COLOR_SPEC
bold true or false
underline true or false
italic true or false
strike true or false
outline true or false
shadow true or false
vertAlign true or false
numFmt "0" // integer index to built in formats, see StyleBuilder.SSF property
"0.00%" // string matching a built-in format, see StyleBuilder.SSF
"0.0%" // string specifying a custom format
"0.00%;\\(0.00%\\);\\-;@" // string specifying a custom format, escaping special characters
"m/dd/yy" // string a date format using Excel’s format notation
alignment vertical "bottom" or "center" or "top"
horizontal "bottom" or "center" or "top"
wrapText true or false
readingOrder 2 // for right-to-left
textRotation Number from 0 to 180 or 255 (default is 0)
90 is rotated up 90 degrees
45 is rotated up 45 degrees
135 is rotated down 45 degrees
180 is rotated down 180 degrees
255 is special, aligned vertically
border top { style: BORDER_STYLE, color: COLOR_SPEC }
bottom { style: BORDER_STYLE, color: COLOR_SPEC }
left { style: BORDER_STYLE, color: COLOR_SPEC }
right { style: BORDER_STYLE, color: COLOR_SPEC }
diagonal { style: BORDER_STYLE, color: COLOR_SPEC }
diagonalUp true or false
diagonalDown true or false

上方的代码需要,created钩子函数中声明,

下面的是点击下载按钮

    setExport2Excel() {
    
    
      const workbook = XLSXS.utils.book_new(); // 创建虚拟的 workbook
      XLSXS.utils.book_append_sheet(workbook, this.sheet, "sheet名称"); // 向 workbook 中添加 sheet
      XLSXS.writeFile(workbook, this.row.file_no + ".xlsx"); // 导出 workbook
    },

猜你喜欢

转载自blog.csdn.net/qq_46207981/article/details/129552840