遇到需要设置前端导出表格的样式,包括设置表头文字样式、固定每列宽度、设置背景色,效果如下:

引入:

npm install xlsx-style --save

如果 npm 安装时出现如下报错,

需要修改源码:
1、在\node_modules\xlsx-style\dist\cpexcel.js 807行把 var cpt = require('./cpt' + 'able'); 改成 var cpt = cptable;

2、在\node_modules\xlsx-style\ods.js 10行和13行把路径改为 require('./xlsx')

import { saveAs } from 'file-saver';
import XLSX from 'xlsx-style'; //引入XLSX

示例代码:

<!--
  导出组件
  参数:text      [提示框文本]
        list      [需要导出的数据]
        headder   [表头标签]
        headderData   [表头字段]
        status     [导出状态]
-->
<template>
  <div class="com-export-box">
    <el-dialog
      title="导出"
      :visible.sync="exportShow"
      :close-on-click-modal="false"
      @close="closeFun"
    >
      <span class="export-text">是否导出当前勾选{{ text }}信息?</span>
      <div class="export-button">
        <el-button 
          @click="exportShow = false"
          type="danger"
          plain
        >
          取消
        </el-button>
        <el-button @click="exportDataToExcel">确定</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<script>
import { saveAs } from 'file-saver';
import XLSX from 'xlsx-style'; //引入XLSX
import moment from 'moment';
export default {
  name: 'ComExport',
  components: {
  },
  props: {
    text: {
      type: String,
      default: ''
    },
    list: {
      type: Array,
      default: () => {
        return [];
      }
    },
    headder: {
      type: Array,
      default: () => {
        return [];
      }
    },
    headderData: {
      type: Array,
      default: () => {
        return [];
      }
    },
    text: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      status: false,
      exportShow: false,
      fontCellStyle: {
        font: {
          name: '宋体',
          sz: 11,
          color: { rgb: '000000' }
        },
        alignment: {//对齐方式
          horizontal: 'center', //水平居中
          vertical: 'center' //竖直居中
        }
      },
      defaultCellStyle: {
        font: {
          name: '宋体',
          sz: 14,
          color: { rgb: '000000' },
          bold: true
        },
        fill: {
          fgColor: { rgb: 'c0c0c0' }
        },
        alignment: {
          horizontal: 'center',
          vertical: 'center',
          indent: 0
        },
        border: {
          bottom: { 
            style: 'thin', 
            color: { rgb: '000000' } 
          },
          left: { 
            style: 'thin', 
            color: { rgb: '000000' } 
          },
          right: { 
            style: 'thin', 
            color: { rgb: '000000' } 
          }
        }
      }
    };
  },
  computed: {
  },
  watch: {
    status: {
      immediate: true,
      handler: function(val) {
        this.status = val;
        if(this.status === true) this.exportShow = true;
      }
    }
  },
  mounted() {
    this.init();
  },
  methods: {
    init() {
    },

    //前端导出配置
    /* eslint-disable */

    generateArray (table) {
      var out = [];
      var rows = table.querySelectorAll('tr');
      var ranges = [];
      for (var R = 0; R < rows.length; ++R) {
        var outRow = [];
        var row = rows[R];
        var columns = row.querySelectorAll('td');
        for (var C = 0; C < columns.length; ++C) {
          var cell = columns[C];
          var colspan = cell.getAttribute('colspan');
          var rowspan = cell.getAttribute('rowspan');
          var cellValue = cell.innerText;
          if (cellValue !== "" && cellValue == +cellValue) cellValue = +cellValue;

          //Skip ranges
          ranges.forEach(function (range) {
            if (R >= range.s.r && R <= range.e.r && outRow.length >= range.s.c && outRow.length <= range.e.c) {
              for (var i = 0; i <= range.e.c - range.s.c; ++i) outRow.push(null);
            }
          });

          //Handle Row Span
          if (rowspan || colspan) {
            rowspan = rowspan || 1;
            colspan = colspan || 1;
            ranges.push({
              s: {
                r: R,
                c: outRow.length
              },
              e: {
                r: R + rowspan - 1,
                c: outRow.length + colspan - 1
              }
            });
          };

          //Handle Value
          outRow.push(cellValue !== "" ? cellValue : null);

          //Handle Colspan
          if (colspan)
            for (var k = 0; k < colspan - 1; ++k) outRow.push(null);
        }
        out.push(outRow);
      }
      return [out, ranges];
    },

    datenum (v, date1904) {
      if (date1904) v += 1462;
      var epoch = Date.parse(v);
      return (epoch - new Date(Date.UTC(1899, 11, 30))) / (24 * 60 * 60 * 1000);
    },

    sheet_from_array_of_arrays (data, opts, fontStyle) {
      var ws = {};
      var range = {
        s: {
          c: 10000000,
          r: 10000000
        },
        e: {
          c: 0,
          r: 0
        }
      };
      let _opts = []
      if (opts) {
        _opts = opts
      }
      console.log('data==', data)
      for (var R = 0; R != data.length; ++R) {
        for (var C = 0; C != data[R].length; ++C) {
          if (range.s.r > R) range.s.r = R;
          if (range.s.c > C) range.s.c = C;
          if (range.e.r < R) range.e.r = R;
          if (range.e.c < C) range.e.c = C;
          var cell = {
            v: data[R][C]
          };
          //设置表头样式
          if (_opts) {
            if (R === _opts[0]) {
              cell = {
                v: data[R][C],
                s: this.defaultCellStyle
              }
            }
          }
          //设置默认样式
          if (_opts) {
            if (R !== _opts[0]) {
              cell = {
                v: data[R][C],
                s: this.fontCellStyle
              }
            }
          }


          if (cell.v == null) continue;
          var cell_ref = XLSX.utils.encode_cell({
            c: C,
            r: R
          });

          if (typeof cell.v === 'number') cell.t = 'n';
          else if (typeof cell.v === 'boolean') cell.t = 'b';
          else if (cell.v instanceof Date) {
            cell.t = 'n';
            cell.z = XLSX.SSF._table[14];
            cell.v = datenum(cell.v);
          } else cell.t = 's';

          ws[cell_ref] = cell;
        }
      }
      if (range.s.c < 10000000) ws['!ref'] = XLSX.utils.encode_range(range);
      return ws;
    },

    Workbook () {
      // if (!(this instanceof Workbook)) return new Workbook();
      this.SheetNames = [];
      this.Sheets = {};
    },

    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;
    },

    export_table_to_excel (id) {
      var theTable = document.getElementById(id);
      var oo = generateArray(theTable);
      var ranges = oo[1];

      /* original data */
      var data = oo[0];
      var ws_name = "SheetJS";

      var wb = {
        SheetNames: [],
        Sheets: []
      }
      var ws = this.sheet_from_array_of_arrays(data);
      
      ws['!merges'] = ranges;

      /* add worksheet to workbook */
      wb.SheetNames.push(ws_name);
      wb.Sheets[ws_name] = ws;

      var wbout = XLSX.write(wb, {
        bookType: 'xlsx',
        bookSST: false,
        type: 'binary'
      });

      saveAs(new Blob([this.s2ab(wbout)], {
        type: "application/octet-stream"
      }), "test.xlsx")
    },

    export_json_to_excel ({
      multiHeader = [],
      header,
      data,
      filename,
      merges = [],
      maxWidth = '',
      autoWidth = true,
      bookType = 'xlsx',
      diagonal = [],//斜线
      fontStyle = false,
    } = {}) {
      /* original data */
      filename = filename || 'excel-list'
      data = [...data]
      data.unshift(header);

      for (let i = multiHeader.length - 1; i > -1; i--) {
        data.unshift(multiHeader[i])
      }

      var ws_name = "SheetJS";
      var wb = {
        SheetNames: [],
        Sheets: []
      }
      //加样式
      if (diagonal) {
        var ws = this.sheet_from_array_of_arrays(data, diagonal, fontStyle);
      } else {
        var ws = this.sheet_from_array_of_arrays(data);
      }
      //此处可根据自己习惯做判断应用


      if (merges.length > 0) {
        if (!ws['!merges']) ws['!merges'] = [];
        merges.forEach(item => {
          ws['!merges'].push(XLSX.utils.decode_range(item))
        })
      }

      if (autoWidth) {
        /*设置worksheet每列的最大宽度*/
        const colWidth = data.map(row => row.map(val => {
          /*先判断是否为null/undefined*/
          return {
            'wch': 20
          };
        }))
        /*以第一行为初始值*/
        let result = colWidth[0];

        for (let i = 1; i < colWidth.length; i++) {
          for (let j = 0; j < colWidth[i].length; j++) {
            if (result[j]['wch'] < colWidth[i][j]['wch']) {
              result[j]['wch'] = colWidth[i][j]['wch'];
            }
          }
        }
        ws['!cols'] = result;
      }

      if (fontStyle) {

      }

      /* add worksheet to workbook */
      wb.SheetNames.push(ws_name);
      wb.Sheets[ws_name] = ws;

      var wbout = XLSX.write(wb, {
        bookType: bookType,
        bookSST: false,
        type: 'binary'
      });
      saveAs(new Blob([this.s2ab(wbout)], {
        type: "application/octet-stream"
      }), `${filename}.${bookType}`);
    },


    exportDataToExcel() {
      // let table = this.$refs.itemDetailTable
      let tHeader = this.headder; // 列头名称
      let filterVal = this.headderData; // 列头字段
      let index = 0;
      for(index in this.list) {
        this.$set(this.list[index], 'index', Number(index) + 1);
      }
      const list = this.list; // 把要导出的数据tableData存到list
      tHeader.unshift('序号');
      filterVal.unshift('index');

      let merges = [];
      const merges_arr = [this.A_row_merge, this.B_row_merge];
      const data = this.formatJson(filterVal, list);
      this.export_json_to_excel({
        header: tHeader, //表头 必填
        data, //具体数据 必填
        merges,
        diagonal: [0, 3],//斜线位置(第一行第四列)
        filename: moment().format('YYYY-MM-DD') + this.text + '导出表', //非必填
      });


      this.exportShow = false;
      this.$emit('statusChangeFun', false);
      this.$message.success('导出当前' + this.text + '成功!');
    },
    // 格式化json数据
    formatJson(filterVal, jsonData) {
      return jsonData.map(v => filterVal.map(j => v[j]));
    },
    closeFun() {
      this.exportShow = false;
      this.$emit('statusChangeFun', false);
    },
    closeAllFun() {
      this.exportAllShow = false;
      this.$emit('statusChangeFun', false);
    }
  }
};
</script>

<style scoped lang="less">
/deep/ .el-dialog{
  width: 400px;
  height: 300px;
}
/deep/ .el-dialog__body {
  padding-top: 100px;
  text-align: center;
}
.export-button {
  position: absolute;
  right: 20px;
  bottom: 20px;
}
</style>

其他设置可参考:JavaScript导出excel文件,并修改文件样式 - SegmentFault 思否

Logo

前往低代码交流专区

更多推荐