此封装可以自定义图片大小,在excel中换行
一、开发背景
有了上一次的excel导出文字,客户还是不满足,又要把所有图片放到excel里,一目了然。
还好,上一次的插件exceljs支持导出图片。
二、封装
1、放在全局
// exceljs
// github: https://github.com/exceljs/exceljs/tree/v3.10.0
const 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高,宽度自适应
// 拿到图片宽高、然后设置高度5cm
function 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,这里我们在下载图片的时候已顺便获取
// 把图片添加到excel
function 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`);
}
}
版权归原作者 程序员_Hjw 所有, 如有侵权,请联系我们删除。