js 通过 exceljs 和 canvas 实现导出带水印的 excel 表

因公司需求改动, 但是因为到的地方比较多,所以单独写一个单工作表导出,实际可用多工作表的代码部分


interface IHeader {
  k: string;
  v: string;
}
export interface IParams<D extends any> {
  header: IHeader[];
  data: D[];
  sheetName: string;
}

/**
 *
 * 导出 excel(带水印) 公共方法
 * @param header v 为头,k 为对应 data 数据的 name
 * 例:
    const header = [
      {
        k: 'region',
        v: '所属区域',
      }
    ]
 * @param data 要导出的数据
    例:
    const data = [
      {
        region:'广州'
      },
      {
        region:'深圳'
      }
    ]
 * @param filename 导出的 excel 文件名称
 * @param sheetName 指定第一个工作表的名称
 * @param staff 水印名称
 * @param params 导出多个工作表
 * 格式为:
 * [{header:[],data:[],sheetName:''}]
 * @returns
 */
export const createWsSheet = <T, D>(
  header: IHeader[],
  data: T[],
  filename: string,
  sheetName = 'sheet1',
  params: IParams<D>[] = [],
  staff: string = '水印名称',
): void => {
  Message.loading('正在导出...');
  if (!((header && data) && (header.length && data.length))) {
    Message.error('导出失败');
    return;
  }
  // 创建工作簿
  const workbook = new ExcelJS.Workbook();
  // 获取水印
  const base64 = setWatermark(staff);
  const imageId1 = workbook.addImage({ base64, extension: 'png' });
  // 创建带有红色标签颜色的工作表
  const worksheet = workbook.addWorksheet(sheetName, { properties: { tabColor: { argb: 'FFC0000' } } });
  // 生成 columns
  const columns = header.map((col: IHeader): { name: string } => ({ name: col.v }));
  // 生成 rows
  const rows = data.map((row: T): T[] => {
    return header.map(itm => isNull(row[itm.k]) ? row[itm.k] : '');
  });
  // 添加背景图片
  worksheet.addBackgroundImage(imageId1);
  // 添加数据
  worksheet.addTable({
    name: filename,
    ref: 'A1',// 表格左上角位置
    columns,
    rows
  });
  // 多工作表
  if (params && params.length) {
    params.forEach((el: IParams<D>) => {
      if (!((el.header && el.data) && (el.header.length && el.data.length))) {
        Message.error('导出失败');
        return;
      }
      const worksheetM = workbook.addWorksheet(el.sheetName, { properties: { tabColor: { argb: 'FFC0000' } } });
      // 生成 columns
      const columnsM = el.header.map((col: IHeader): { name: string } => ({ name: col.v }));
      // 生成 rows
      const rowsM = el.data.map((row: D): D[] => {
        return el.header.map(itm => isNull(row[itm.k]) ? row[itm.k] : '');
      });
      // 添加背景图片
      worksheetM.addBackgroundImage(imageId1);
      // 添加数据
      worksheetM.addTable({
        name: el.sheetName,
        ref: 'A1',// 表格左上角位置
        columns: columnsM,
        rows: rowsM
      });
    })
  }

  workbook.xlsx.writeBuffer().then((res) => {
    saveAs(new Blob([res], { type: 'application/octet-stream' }), filename)
  });
  Message.success('导出成功');
};
/**
 * 判断该数据是否为空
 * @param data 要判断的数据
 * @returns 布尔值:true/false
 */
const isNull = (data: any): boolean => {
  return (data ?? '') !== '';
}

/**
 * 绘画水印
 * @param str 要做出水印的文字
 * @returns Base64
 */
const setWatermark = (str: string): string => {
  let id = '1.23452384164.123412416';

  if (document.getElementById(id) !== null) {
    document.body.removeChild(document.getElementById(id) as any);
  }
  // 创建一个画布
  let can = document.createElement('canvas');
  // 设置画布的长宽
  can.width = 500;
  can.height = 420;
  let cans = can.getContext('2d') as any;
  // 旋转角度
  cans.rotate(-25 * Math.PI / 180);
  // 设置字体大小
  cans.font = "800 40px Microsoft JhengHei";
  // 设置填充绘画的颜色、渐变或者模式
  cans.fillStyle = "rgba(130, 142, 162, 0.2)";
  // 设置文本内容的当前对齐方式
  cans.textAlign = 'center';
  // 设置在绘制文本时使用的当前文本基线
  cans.textBaseline = 'Middle';
  cans.fillText(str, 180, 350);

  const dataURL = can.toDataURL('image/png');
  return dataURL;
}

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值