当前位置: 首页 > news >正文

Vue3 + Vite + TS,使用 ExcelJS导出excel文档,生成水印,添加背景水印,dom转图片,插入图片,全部代码

Vue3 + Vite + TS,使用 ExcelJS导出excel文档,生成水印,添加背景水印,dom转图片,插入图片,全部代码

  • ExcelJS
    • 生成文档并导出
      • 导出表头其他函数
    • 生成水印
    • 设置文档的背景水印
    • dom 转图片
    • 插入图片
    • 全部代码

ExcelJS

读取,操作并写入电子表格数据和样式到 XLSX 和 JSON 文件。
一个 Excel 电子表格文件逆向工程项目。
exceljs 中文API 传送门

生成文档并导出

import * as ExcelJS from "exceljs";// 创建文档对象
const workbook = new ExcelJS.Workbook();
// 创建工作本
const worksheet = workbook.addWorksheet('Sheet 1');
// 冻结表头
worksheet.views = [{state: 'frozen', // 可以设置为 'frozen' 来固定首行或首列,模拟滚动条效果xSplit: 0, // 从第二列开始冻结(模拟滚动条效果)ySplit: 9, // 从第二行开始冻结(模拟滚动条效果)topLeftCell: 'A1' // 设置起始位置为 B2,模拟滚动效果从第二行第二列开始
}];
// 1. 构建表头结构
const headerDepth = buildHeaders(filterColumns,7);
// 递归生成表头行
generateHeaderRows(worksheet,headerDepth,filterColumns,7);
// 2. 填充数据
// salesTable.value.tableData.forEach(item => {
//     worksheet.addRows(item);
// })
// 触发下载
const buffer = await workbook.xlsx.writeBuffer();
const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
link.download = name+'.xlsx';
link.click();

导出表头其他函数

// 递归生成表头行
export const generateHeaderRows = (worksheet:Worksheet,headerDepth:number,cols:tableColumn[], currentRow = 0, startCol = 0) => {cols.forEach(col => {const cell = {header: col.label,key: col.dataIndex,width: col.minWidth?parseInt(col.minWidth)/8 : 20,colSpan: col.childrens ? col.childrens.length : 1,rowSpan: col.childrens ? 1 : headerDepth - currentRow + 1};const tempCell = worksheet.getCell(currentRow + 1, startCol + 1);// 设置单元格文案tempCell.value = col.label;// 设置单元格字体与大小tempCell.font = { name: 'Arial', size: 10 }// 设置列宽度worksheet.getColumn(startCol+1).width = cell.width;// 设置行高worksheet.getRow(currentRow+1).height = 20;// 合并单元格worksheet.mergeCells(currentRow + 1,startCol + 1,currentRow + (cell.rowSpan || currentRow+1), startCol + (cell.colSpan || 1));// 有子级递归if (col.childrens) {generateHeaderRows(worksheet,headerDepth,col.childrens, currentRow + 1, startCol);}startCol += cell.colSpan;});
}// 递归处理表头层级
export const buildHeaders = (columns:tableColumn[], depth = 0, parentSpan = 0) => {let maxDepth = depth;columns.forEach((col:tableColumn) => {if (col.childrens) {const childDepth = buildHeaders(col.childrens, depth + 1, parentSpan + (col.colSpan|| 0));maxDepth = Math.max(maxDepth, childDepth);}});return maxDepth;
};

生成水印

export const createWatermark = () => {// 创建 Canvas 元素并绘制水印const canvas = document.createElement('canvas');const context:CanvasRenderingContext2D | null  = canvas.getContext('2d');canvas.width = 500;canvas.height = 200;context?context.font = '14px Arial':'';// 旋转角度context?context.rotate(-25 * Math.PI / 180):'';// 设置文本内容的当前对齐方式context?context.textAlign = 'center':'';context?context.fillStyle = 'rgba(0, 0, 0, 0.1)':''; // 半透明水印context?context.fillText('midea', canvas.width / 2 - 100, canvas.height / 2):'';// 将 Canvas 转换为图片数据 URLreturn canvas.toDataURL('image/png');
}

设置文档的背景水印

// 将 Canvas 水印 转换为图片数据 URL
const imageDataUrl = createWatermark();
// 添加图片到工作簿中
const imageId = workbook.addImage({base64: imageDataUrl.replace(/^data:image\/[a-z]+;base64,/, ''),extension: 'png',
});
// 设置文档水印
worksheet.addBackgroundImage(imageId)

dom 转图片

import domToImage from 'dom-to-image';// 把查询条件转为图片
domToImage.toPng(captureRef.value).then(async (dataUrl) => {const image = new Image();image.src = dataUrl;})
.catch(function (error) {console.error('Failed to generate image:', error);
});

插入图片

const imageId2 = workbook.addImage({ base64: dataUrl, extension: 'png' });
// 工作本插入查询条件图片
worksheet.addImage(imageId2, {tl: { col: 0, row: 0 },ext: { width: 1900 / 1.3, height: 800 / 6 }
});

全部代码


// 递归生成表头行
export const generateHeaderRows = (worksheet:Worksheet,headerDepth:number,cols:tableColumn[], currentRow = 0, startCol = 0) => {cols.forEach(col => {const cell = {header: col.label,key: col.dataIndex,width: col.minWidth?parseInt(col.minWidth)/8 : 20,colSpan: col.childrens ? col.childrens.length : 1,rowSpan: col.childrens ? 1 : headerDepth - currentRow + 1};const tempCell = worksheet.getCell(currentRow + 1, startCol + 1);// 设置单元格文案tempCell.value = col.label;// 设置单元格字体与大小tempCell.font = { name: 'Arial', size: 10 }// 设置列宽度worksheet.getColumn(startCol+1).width = cell.width;// 设置行高worksheet.getRow(currentRow+1).height = 20;// 合并单元格worksheet.mergeCells(currentRow + 1,startCol + 1,currentRow + (cell.rowSpan || currentRow+1), startCol + (cell.colSpan || 1));// 有子级递归if (col.childrens) {generateHeaderRows(worksheet,headerDepth,col.childrens, currentRow + 1, startCol);}startCol += cell.colSpan;});
}// 递归处理表头层级
export const buildHeaders = (columns:tableColumn[], depth = 0, parentSpan = 0) => {let maxDepth = depth;columns.forEach((col:tableColumn) => {if (col.childrens) {const childDepth = buildHeaders(col.childrens, depth + 1, parentSpan + (col.colSpan|| 0));maxDepth = Math.max(maxDepth, childDepth);}});return maxDepth;
};
export const createWatermark = () => {// 创建 Canvas 元素并绘制水印const canvas = document.createElement('canvas');const context:CanvasRenderingContext2D | null  = canvas.getContext('2d');canvas.width = 500;canvas.height = 200;context?context.font = '14px Arial':'';// 旋转角度context?context.rotate(-25 * Math.PI / 180):'';// 设置文本内容的当前对齐方式context?context.textAlign = 'center':'';context?context.fillStyle = 'rgba(0, 0, 0, 0.1)':''; // 半透明水印context?context.fillText('midea', canvas.width / 2 - 100, canvas.height / 2):'';// 将 Canvas 转换为图片数据 URLreturn canvas.toDataURL('image/png');
}// 点击下载const downLoadList = () => {// 创建文档对象const workbook = new ExcelJS.Workbook();// 创建工作本const worksheet = workbook.addWorksheet('Sheet 1');// 冻结表头worksheet.views = [{state: 'frozen', // 可以设置为 'frozen' 来固定首行或首列,模拟滚动条效果xSplit: 0, // 从第二列开始冻结(模拟滚动条效果)ySplit: 9, // 从第二行开始冻结(模拟滚动条效果)topLeftCell: 'A1' // 设置起始位置为 B2,模拟滚动效果从第二行第二列开始}];// 1. 构建表头结构const headerDepth = buildHeaders(filterColumns,7);// 递归生成表头行generateHeaderRows(worksheet,headerDepth,filterColumns,7);emit('downLoadList',workbook,worksheet);}const downLoadListFn = async (workbook:Workbook,worksheet:Worksheet,name:string) => {// 把查询条件转为图片domToImage.toPng(captureRef.value).then(async (dataUrl) => {const image = new Image();image.src = dataUrl;const imageId2 = workbook.addImage({ base64: dataUrl, extension: 'png' });// 工作本插入查询条件图片worksheet.addImage(imageId2, {tl: { col: 0, row: 0 },ext: { width: 1900 / 1.3, height: 800 / 6 }});// 2. 填充数据// salesTable.value.tableData.forEach(item => {//     worksheet.addRows(item);// })// 将 Canvas 水印 转换为图片数据 URLconst imageDataUrl = createWatermark();// 添加图片到工作簿中const imageId = workbook.addImage({base64: imageDataUrl.replace(/^data:image\/[a-z]+;base64,/, ''),extension: 'png',});// 设置文档水印worksheet.addBackgroundImage(imageId)// 触发下载const buffer = await workbook.xlsx.writeBuffer();const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });const link = document.createElement('a');link.href = URL.createObjectURL(blob);link.download = name+'.xlsx';link.click();}).catch(function (error) {console.error('Failed to generate image:', error);});}

相关文章:

  • Java中的方法重写(Override)与方法重载(Overload)详解
  • 位运算练习:起床困难综合征(贪心,位运算)(算法竞赛进阶指南学习笔记)
  • 关于ubuntu密码正确但是无法登录的情况
  • 互联网大厂Java面试:从基础到进阶的技术点探讨
  • 短信验证码安全实战:三网API+多语言适配开发指南
  • C语言学习记录(17)编译和链接
  • vue3 + element-plus中el-drawer抽屉滚动条回到顶部
  • Scenario Dreamer:用于生成驾驶模拟环境的矢量化潜扩散模型
  • 【Linux禁用历史命令】
  • 从零开始配置 Zabbix 数据库监控:MySQL 实战指南
  • SSH 互信被破坏能导致 RAC 异常关闭吗
  • 脚本备份数据
  • 热敏电阻的应用说明
  • Centos虚拟机远程连接缓慢
  • 数据结构与算法-顺序表应用
  • 网络原理 - 4(TCP - 1)
  • AI深度伪造视频用于诈骗的法律定性与风险防范
  • Mysql的redolog
  • React:<></>的存在是为了什么
  • VMwaer虚拟机复制粘贴、ROS系统安装
  • 主刀完成3万余例手术,81岁神经外科学专家徐启武逝世
  • 北京朝阳法院:未经许可使用他人剧本语句和情节构成侵权
  • 广州远洋宾馆负一层配电房发生火情:明火已扑灭,无人员伤亡
  • 世界读书日|阅读在上海
  • 云南城投去年营收约19.29亿元,亏损4945万元
  • 女子遭前男友泼汽油烧伤致残案二审庭审:检方抗诉称一审量刑不当