编程综合网:天梦星科技官网
小编:张贵顺
在此之前先下载依赖:
npm install -S file-saver xlsx
npm install -D script-loader
npm install js-table2excel
-- 安装 docxtemplater
npm install docxtemplater pizzip --save
-- 安装 jszip-utils
npm install jszip-utils --save
-- 安装 jszip
npm install jszip --save
-- 安装 FileSaver
npm install file-saver --save
-- 安装 angular-expressions
npm install angular-expressions --save
-- 安装 image-size
npm install image-size --save
接下来上代码:
- 导出Word表格,支持多张图片 ,人狠话不多说,直接上代码
文件名:exportWordImage.js
/**
* 导出word文档(带图片)
*
*/
import Docxtemplater from 'docxtemplater'
import PizZip from 'pizzip'
import JSZipUtils from 'jszip-utils'
import { saveAs } from 'file-saver'
/**
* 将base64格式的数据转为ArrayBuffer
* @param {Object} dataURL base64格式的数据
*/
function base64DataURLToArrayBuffer(dataURL) {
const base64Regex = /^data:image\/(png|jpg|jpeg|svg|svg\+xml);base64,/;
if (!base64Regex.test(dataURL)) {
return false;
}
const stringBase64 = dataURL.replace(base64Regex, "");
let binaryString;
if (typeof window !== "undefined") {
binaryString = window.atob(stringBase64);
} else {
binaryString = Buffer.from(stringBase64, "base64").toString("binary");
}
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
const ascii = binaryString.charCodeAt(i);
bytes[i] = ascii;
}
return bytes.buffer;
}
export const ExportBriefDataDocx = (tempDocxPath, data, fileName, imgSize) => {
//这里要引入处理图片的插件
var ImageModule = require('docxtemplater-image-module-free');
var expressions = require('angular-expressions')
var assign = require('lodash/assign')
var last = require("lodash/last")
expressions.filters.lower = function (input) {
if (!input) return input
return input.toLowerCase()
}
function angularParser(tag) {
tag = tag
.replace(/^\.$/, 'this')
.replace(/(’|‘)/g, "'")
.replace(/(“|”)/g, '"')
const expr = expressions.compile(tag)
return {
get: function (scope, context) {
let obj = {}
const index = last(context.scopePathItem)
const scopeList = context.scopeList
const num = context.num
for (let i = 0, len = num + 1; i < len; i++) {
obj = assign(obj, scopeList[i])
}
//word模板中使用 $index+1 创建递增序号
obj = assign(obj, { $index: index })
return expr(scope, obj)
}
}
}
JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
if (error) {
console.log(error)
}
expressions.filters.size = function (input, width, height) {
return {
data: input,
size: [width, height],
};
};
let opts = {}
opts = {
//图像是否居中
centered: false
};
opts.getImage = (chartId) => {
//将base64的数据转为ArrayBuffer
return base64DataURLToArrayBuffer(chartId);
}
opts.getSize = function (img, tagValue, tagName) {
//自定义指定图像大小
if (imgSize.hasOwnProperty(tagName)) {
return imgSize[tagName];
} else {
return [100, 100];
}
}
// 创建一个JSZip实例,内容为模板的内容
const zip = new PizZip(content)
// 创建并加载 Docxtemplater 实例对象
// 设置模板变量的值
let doc = new Docxtemplater();
doc.attachModule(new ImageModule(opts));
doc.loadZip(zip);
doc.setOptions({parser:angularParser});
doc.setData(data)
try {
// 呈现文档,会将内部所有变量替换成值,
doc.render()
} catch (error) {
const e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
}
console.log('err',{ error: e })
// 当使用json记录时,此处抛出错误信息
throw error
}
// 生成一个代表Docxtemplater对象的zip文件(不是一个真实的文件,而是在内存中的表示)
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
})
// 将目标文件对象保存为目标类型的文件,并命名
saveAs(out, fileName)
})
}
/**
* 将图片的url路径转为base64路径
* 可以用await等待Promise的异步返回
* @param {Object} imgUrl 图片路径
*/
export function getBase64Sync(imgUrl) {
return new Promise(function (resolve, reject) {
// 一定要设置为let,不然图片不显示
let image = new Image();
//图片地址
image.src = imgUrl;
// 解决跨域问题
image.setAttribute("crossOrigin", '*'); // 支持跨域图片
// image.onload为异步加载
image.onload = function () {
let canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
let context = canvas.getContext("2d");
context.drawImage(image, 0, 0, image.width, image.height);
//图片后缀名
let ext = image.src.substring(image.src.lastIndexOf(".") + 1).toLowerCase();
//图片质量
let quality = 0.8;
//转成base64
let dataurl = canvas.toDataURL("image/" + ext, quality);
//返回
resolve(dataurl);
};
})
}
调用函数:
async expotWord(){
let data:{
isTable:[
{
id: 1,
created_at: "2023-05-19",
organ_name: "测试",
title: "测试",
url: "测试",
region_text: "测试",
involved: "测试",
dissemination:"测试",
standpoint: "测试",
risk_content: "测试",
eidt_role: "测试",
files_json: [
{imgUrl:'http://172.16.72.27:32114/group1/hzyn/ynwx/feedback/20230516/1684207872385.jpeg'},
{imgUrl:'http://172.16.72.27:32114/group1/hzyn/ynwx/feedback/20230516/1684207872385.jpeg'},
]
}
]
};
for (const item of data.isTable) {
for (let i in item.files_json) {
item.files_json[i].imgUrl = await getBase64Sync(item.files_json[i].imgUrl)
}
}
if (wordData.isTable.length>=1){
let imgSize = {
imgurl:[200, 200],//控制导出的word图片大小
};
ExportBriefDataDocx(`${"/yqypexportdata"}.docx`, data, "信息测试.docx", imgSize);
}else {
this.$message.warning("导出数据不能为空!");
}
},
表格模版:文件名: yqypexportdata.docx 位置放public 目录下
预期效果:
2.导出Excel表格,同样支持多张图片
封装的js:
/* eslint-disable */
let idTmr;
const getExplorer = () => {
let explorer = window.navigator.userAgent;
//ie
if (explorer.indexOf("MSIE") >= 0) {
return 'ie';
}
//firefox
else if (explorer.indexOf("Firefox") >= 0) {
return 'Firefox';
}
//Chrome
else if (explorer.indexOf("Chrome") >= 0) {
return 'Chrome';
}
//Opera
else if (explorer.indexOf("Opera") >= 0) {
return 'Opera';
}
//Safari
else if (explorer.indexOf("Safari") >= 0) {
return 'Safari';
}
}
const exportToExcel = (data,name) => {
// 判断是否为IE
if (getExplorer() == 'ie') {
tableToIE(data, name)
} else {
tableToNotIE(data,name)
}
}
const Cleanup = () => {
window.clearInterval(idTmr);
}
const tableToIE = (data, name) => {
let curTbl = data;
let oXL = new ActiveXObject("Excel.Application");
//创建AX对象excel
let oWB = oXL.Workbooks.Add();
//获取workbook对象
let xlsheet = oWB.Worksheets(1);
//激活当前sheet
let sel = document.body.createTextRange();
sel.moveToElementText(curTbl);
//把表格中的内容移到TextRange中
sel.select;
//全选TextRange中内容
sel.execCommand("Copy");
//复制TextRange中内容
xlsheet.Paste();
//粘贴到活动的EXCEL中
oXL.Visible = true;
//设置excel可见属性
try {
let fname = oXL.Application.GetSaveAsFilename("Excel.xls", "Excel Spreadsheets (*.xls), *.xls");
} catch (e) {
print("Nested catch caught " + e);
} finally {
oWB.SaveAs(fname);
oWB.Close(savechanges = false);
//xls.visible = false;
oXL.Quit();
oXL = null;
// 结束excel进程,退出完成
window.setInterval("Cleanup();", 1);
idTmr = window.setInterval("Cleanup();", 1);
}
}
const tableToNotIE = (function() {
// 编码要用utf-8不然默认gbk会出现中文乱码
let uri = 'data:application/vnd.ms-excel;base64,',
template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta charset="UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>{table}</table></body></html>',
base64 = function(s) {
return window.btoa(unescape(encodeURIComponent(s)));
},
format = (s, c) => {
return s.replace(/{(\w+)}/g,
(m, p) => {
return c[p];
})
}
return (table, name) => {
let ctx = {
worksheet: name,
table
}
//创建下载
let link = document.createElement('a');
link.setAttribute('href', uri + base64(format(template, ctx)));
link.setAttribute('download', name);
// window.location.href = uri + base64(format(template, ctx))
link.click();
}
})()
// 导出函数
const export2Excel = (theadData, tbodyData, dataname) => {
let re = /https?:\\.(png|gif|jpg|jpeg|bmp)/ig // 字符串中包含http,则默认为图片地址(正则)
let th_len = theadData.length // 表头的长度
let tb_len = tbodyData.length // 记录条数
let width = 40 // 设置图片大小
let height = 60
// 添加表头信息
let thead = '<thead><tr>'
for (let i = 0; i < th_len; i++) {
thead += '<th>' + theadData[i] + '</th>'
}
thead += '</tr></thead>'
// 添加每一行数据
let tbody = '<tbody>'
for (let i = 0; i < tb_len; i++) {
tbody += '<tr>'
let row = tbodyData[i] // 获取每一行数据
for (let key in row) {
if (re.test(row[key])) { // 如果为图片,则需要加div包住图片
let listDiv=''
for (const keyElement of row[key]) {
listDiv+= '<div>'+'<img src=\'' + keyElement + '\' ' + ' ' + 'width=' + '\"' + width + '\"' + ' ' + 'height=' + '\"' + height + '\"' + '/>'+'</div>'
}
tbody += '<td style="width:auto; height:auto; text-align: center; vertical-align: middle">' + listDiv + '</td>'
} else {
tbody += '<td style="text-align:center">' + row[key] + '</td>'
}
}
tbody += '</tr>'
}
tbody += '</tbody>'
let table = thead + tbody
// 导出表格
exportToExcel(table, dataname)
}
export {
export2Excel
}
调用:
expotExcel(e){
let tbody =[
{
id:'',//序号
created_at:null,//创建时间
organ_name:null,//上报单位
title:null,//标题
url:null,//链接
region_text:null,//事件属地
involved:null,//涉事单位
dissemination:null,//传播情况
standpoint:null,//网民观点
risk_content:null,//风险研判
eidt_role:null,
files_json:['http://172.16.72.27:32114/group1/hzyn/ynwx/feedback/20230516/1684207872385.jpeg','http://172.16.72.27:32114/group1/hzyn/ynwx/feedback/20230516/1684207872385.jpeg'],//附件
}
]
let tHeader =['序号','创建时间','上报单位','标题','链接','事件属地','涉事单位','传播情况','网民观点','风险研判','选用人','附件']
let dataTime=this.$moment().format('YYYY-MM-DD HH');
if (tbody.length>=1){
export2Excel(tHeader, tbody, '舆情信息汇总'+'('+dataTime+')')
}else {
this.$message.warning("导出数据不能为空!");
}
},
预期效果:
收到over over!