vue + xlsx 动态生成Excel,合并单元格

根据数据动态生成一个Excel导出文件,这个公共相对简单一些,引入 xlsx就可以了。

但是根据需求,动态合并单元格,貌似难度不小,这里需要对 xlsx的属性和方法有一定的了解才可以,那么一起学习一下。

安装 xlsx 和 xlsx-style

cnpm i xlsx xlsx-style --save

excel 示例

在这里插入图片描述

A、B、C、D、E、F … 代表的是
1、2、3、4、5、6、… 代表的是

每一个单元格是一个对象(Cell Object),主要有t、v、r、h、w等字段:

注释
t表示内容类型
s表示string类型
n表示number类型
b表示boolean类型
d表示date类型
等等
v表示原始值;
f表示公式,如B2+B3;
hHTML内容
w格式化后的内容
r富文本内容rich text

封装 Export2Excel


import XLSX from 'xlsx'

/**
 * xlsx-style 引入会报错,需要 添加下边代码
 * // var cpt = require('./cpt' + 'able');
   var cpt = cptable
 */
import XLSXStyle from 'xlsx-style'


/**
	 * 通用的打开下载对话框方法,没有测试过具体兼容性
	 * @param url 下载地址,也可以是一个blob对象,必选
	 * @param saveName 保存文件名,可选
*/
function openDownloadDialog(url, saveName)
 {
   if(typeof url == 'object' && url instanceof Blob)
   {
     url = URL.createObjectURL(url); // 创建blob地址
   }
   var aLink = document.createElement('a');
   aLink.href = url;
   aLink.download = saveName || ''; // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,file:///模式下不会生效
   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);
}


// 字符串转ArrayBuffer
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;
}

// 将一个sheet转成最终的excel文件的blob对象,然后利用URL.createObjectURL下载
function sheet2blob(sheet, sheetName) {
  sheetName = sheetName || 'sheet1';
  var workbook = {
    SheetNames: [sheetName],
    Sheets: {}
  };
  workbook.Sheets[sheetName] = sheet;
  // 生成excel的配置项
  var wopts = {
    bookType: 'xlsx', // 要生成的文件类型
    bookSST: false, // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性
    type: 'binary'
  };
  var wbout = XLSXStyle.write(workbook, wopts);
  var blob = new Blob([s2ab(wbout)], {type:"application/octet-stream"});


  return blob;
}

/**
e: {//e结束
  c: 3,//结束列
  r: 4//结束行
},
s: {//s为开始
  c: 0,//开始列
  r: 0//可以看成开始行,实际是取值范围
}
*/
function aoa_to_sheet_fn (th,data){
	//需要导出的数据
	var aoa = [],
		// 需要合并的单元格
       mergeArr =[],
       // 需要更改样式的单元格
       colArr = {},
       // 字母 代表列
       letter =['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O'];
       
	  // 表头样式
      th.map((m,i)=>{
        colArr[letter[i]+'1'] = {
          font: {
            sz: 15,
            bold: true,
            color: {
              rgb: "FFFFAA00"
            }
          },
          alignment: {
            horizontal: "center",
            vertical: "center",
            wrap_text: true
          }
        }
      })
  // 将表头数据,添加到数组第一项
  aoa.unshift(th);


// 遍历需要显示的数据,规则根据需求,自行封装
data.map((m)=>{

...

// 需要合并的单元格
mergeArr.push({
   s: {r:xxx, c: 0}, 
   e: {r: xxx, c: 0}
 })

// 此处代表A2行,字体为14px 居中显示
colArr['A2'] = {
      font: {
        sz: 14
      },
      alignment: {
        horizontal: "center",
        vertical: "center"
      }
    }


aoa.push('这里添加需要展示的数据')
...

})



 var sheet = XLSX.utils.aoa_to_sheet(aoa);

  /**
   * 举例:第一列到第三列合并--等于--设置A1-C1的单元格合并:[
    {s: {r: 0, c: 1}, e: {r: 0, c: 3}}
  ];
  */
  // 需要合并的单元格-- 赋值
  sheet['!merges'] = mergeArr

  //控制单元格宽度
  sheet["!cols"] = [{
    wpx: 200
  }, {
    wpx: 150
  }, {
    wpx: 150
  }, {
    wpx: 150
  }]; 

  // 样式 赋值
  for(let i in colArr){
    sheet[i].s =colArr[i]
  }
  // 输出
  return sheet
}


export function export_json_to_excel(th, data, defaultTitle) {

  var sheet = aoa_to_sheet_fn(th, data)

  openDownloadDialog(sheet2blob(sheet), defaultTitle +'.xlsx'|| '表名.xlsx');

}

知识扩展

使用xlsx 时,会报错

This relative module was not found:
* ./cptable in ./node_modules/xlsx-style/dist/cpexcel.js

解决:
修改 vue.config.js 文件 chainWebpack

...

chainWebpack: (config) => {
    config.resolve.alias
      // 移除 prefetch 插件
      // config.plugins.delete('prefetch')
      .set('@',resolve('src'))
      .set('$api', resolve('src/api'))

    config.externals({ './cptable': 'var cptable' })
  }

....

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值