此封装可以自定义图片大小,在excel中换行
一、开发背景
有了上一次的excel导出文字,客户还是不满足,又要把所有图片放到excel里,一目了然。
还好,上一次的插件exceljs支持导出图片。
二、封装
1、放在全局
// exceljs// github: https://github.com/exceljs/exceljs/tree/v3.10.0const ExcelJS = require("exceljs");import FileSaver from "file-saver";const { i18n } = require("@/utils/i18n.js");import BUSINESS_CONFIG from "@/business_config.js";require("script-loader!xlsx/dist/xlsx.core.min");import { searchFileByTrans } from "@/api/receipts/receiptsCommon.js";const twoHeaderRows = 65534;const oneHeaderRows = 65535;export default { install(Vue) { Vue.prototype.$exportImage = async function ( trans_no, trans_type, fileName, fileType ) { // 工作表下标 var sheetIndex = 0; // 图片占左边距离 var width = 0; // 创建工作簿 var workbook = new ExcelJS.Workbook(); // 设置工作簿属性 workbook.creator = "Me"; workbook.lastModifiedBy = "Her"; workbook.created = new Date(1985, 8, 30); workbook.modified = new Date(); workbook.lastPrinted = new Date(2016, 9, 27); // 将工作簿日期设置为 1904 年日期系统 workbook.properties.date1904 = true; // 所有工作表 var worksheetAll = []; // 添加工作表 worksheetAll.push(workbook.addWorksheet(`Sheet${sheetIndex + 1}`)); let imageList = await getImageAssets(trans_no, trans_type); console.log("获取图片资源", imageList); imageList = await downLoadAll(workbook, imageList); console.log("获取图片属性", imageList); addImageToExcel(worksheetAll, sheetIndex, imageList, width); exportExcelImage(workbook, fileName, fileType); this.$store.commit("saveLoadShow", false); }; },};
2、获取图片资源
这里一定要用同步代码async await等图片回来了,我们再去操作导出。
sort就是数组排序,要按后端返回的document_name字段排序,各位看官可以根据自己的业务需求自行处理。
// 获取图片资源function getImageAssets(trans_no, trans_type) { return new Promise((resolve, reject) => { searchFileByTrans(trans_no, trans_type).then(async (res) => { if (res.success) { let imageList = res.data.sort((a, b) => a.document_name.localeCompare(b.document_name) ); resolve(imageList); } else { this.$message.error(res.message); } }); });}
3、并行下载所有图片
// 并行下载所有图片async function downLoadAll(workbook, imageList) { await Promise.all( imageList.map(async (item, index) => { return downLoadImage(workbook, item); }) ); return imageList;}// 下载图片async function downLoadImage(workbook, item) { let imageUrl = `${window.location.origin}/api/common/download?resource=${item.file_path}`; // 通过网络请求拿到图片buffer let imageId = await fetch(imageUrl) .then((res) => res.arrayBuffer()) .then((buffer) => { const imageBuffer = Buffer.from(buffer); var imageId = workbook.addImage({ buffer: imageBuffer, extension: item.file_path.split(".")[1], }); return imageId; }); let image = await scaleImg(imageUrl); // 把id和宽高记录在item item.imageId = imageId; item.width = image.width; item.height = image.targetHeightPx;}
4、设置图片的大小
这里我设置的是5cm高,宽度自适应
// 拿到图片宽高、然后设置高度5cmfunction scaleImg(imageUrl) { const img = new Image(); img.src = imageUrl; return new Promise((resolve) => { img.onload = async () => { let targetHeightPx = (5 * 96) / 2.54; // 四舍五入取整 targetHeightPx = Math.round(targetHeightPx); // 计算缩放比例 const scale = targetHeightPx / img.height; const width = img.width * scale; console.log("宽:", width, "高", targetHeightPx, "比例", scale); resolve({ width, targetHeightPx }); }; });}
5、把图片放进excel
根据插件描述,需要一个每个图片都要一个imageId,这里我们在下载图片的时候已顺便获取
// 把图片添加到excelfunction addImageToExcel(worksheetAll, sheetIndex, imageList, width) { let rowIndex = 0; imageList.forEach((item) => { // 开始列 item.startCol = width; // 一个单元格的宽度约为72,加多一列 width = width + Math.ceil(item.width / 72) + 1; // 名称开始行,从A2开始,5cm高度占10行,所以名称放在12 24 行 let nameRow = (rowIndex + 1) * 12; // 添加图片,图片放在2,14,26行,对应下标1,13,25 worksheetAll[sheetIndex].addImage(item.imageId, { tl: { col: item.startCol, row: 12 * rowIndex + 1 }, ext: { width: item.width, height: item.height }, }); // 换行 if (width > 15) { width = 0; rowIndex += 1; } // 名称开始列 let start = String.fromCharCode("A".charCodeAt() + item.startCol); // 添加图片名称 document_name var cell = worksheetAll[sheetIndex].getCell(`${start}${nameRow}`); cell.value = item.document_name.split(".")[0]; cell.style.font = { name: "宋体", family: 4, size: 10, }; });}
6、下载excel
转成bold,用FileSaver插件下载,和之前的导出excel一样的操作
// 导出async function exportExcelImage(workbook, fileName, fileType) { // 转成buffer const buffer = await workbook.xlsx.writeBuffer(); // MIME 类型 var type = "application/vnd.openxmlformats"; if (fileType == ".xls") { type = "application/vnd.ms-excel"; } // file-saver在保存文件时,需要把Buffer/Blob转换为Blob URL const blob = new Blob([buffer], { type }); var defaultTitle = fileName || i18n.t("列表"); if (fileType == ".xls") { FileSaver.saveAs(blob, `${defaultTitle}.xls`); } else { FileSaver.saveAs(blob, `${defaultTitle}.xls`); }}