1.生成pdf:
1.使用的插件:jspdf,jspdf-autotable,html2canvas
2.插件介绍:
2.1 jspdf:前端生成和导出pdf的插件;
2.2 jspdf-autotable:可以更方便的在jspdf中生成表格,可以直接传入表格数据也可以直接传入表格dom标签;jspdf本身也有生成表格的API,只是没有jspdf-autotable方便,可以根据需要选择;
2.3 html2canvas:可以截取网页中的dom元素为canvas对象,来构建屏幕截图,如果不需要此功能,可以不使用这个插件
3.jspdf API地址、jspdf-autotable样式配置参考这两个地址可以找到jspdf的大部分使用方法和配置介绍
4.demo
使用这个demo前需要注意:
1.需要自己生成simhei-normal.js/ts文件,生成方法查看上一篇文章;
如果导出内容不包含中文可以不需要这个导入,相应的注释掉下面的 doc.setFont(‘simhei’) 以及 font: ‘simhei’,
2.html2canvas中获取了相应的dom元素,需要改成自己的标签元素。
import { jsPDF } from 'jspdf'
import 'jspdf-autotable'
import './simhei-normal' //jspdf自定义字体,生成步骤参见上一篇博文
const html2canvas = window['html2canvas']
export function exportPDF(filename: string) {
const doc = new jsPDF() as any;
doc.setFont('simhei');//simhei是自定义字体名
//获取文件单页的宽高,单位mm
var pageWidth = Math.floor(doc.internal.pageSize.width || doc.internal.pageSize.getWidth());
var pageHeight = Math.floor(doc.internal.pageSize.height || doc.internal.pageSize.getHeight());
const logoData = new Image()
logoData.src = '../../../../../public/images/product/logo.jpg'
//添加图片,参数依次为:imageData(string|HTMLImageElement|HTMLCanvasElement|Uint8Array),x(水平位置),y(垂直位置),w(宽),h(高)
//位置、宽、高的单位都为mm
doc.addImage(logoData, 10, 5, 21, 21)
doc.setFontSize(38)//字体大小配置,在需要配置的文本上方设置。
doc.setTextColor('red')//字体颜色配置
//添加文本,参数为('文本内容',x,y)
doc.text('this is a textContent', 35, 20)
doc.setFontSize(15)
doc.setTextColor('black')
doc.text('this is a textContent too', 10, 35)
doc.setLineWidth(0.5) //设置线条宽度
doc.setDrawColor('red')//设置线条颜色
//绘制线条(X1,Y1,X2,Y2)
doc.line(5, 38, 205, 38)
html2canvas(document.getElementById('chart-total'), {
background: "#ffffff",
dpi: 140
}
).then((canvas: HTMLCanvasElement) => {
doc.addImage(canvas, 10, 55, pageWidth - 30, pageHeight - 90)
//新增一页
doc.addPage()
const data = [ { time: '202103011000', address: '上海' },
{ time: '202103011000', address: '上海' },
{ time: '202103011000', address: '上海' }
]
const header = [{ header: '时间', dataKey: 'time' }, { header: '地址', dataKey: 'address' }]
doc.autoTable({
body: data,
columns: header,
//表格全局样式
styles: {
fillColor: [255, 255, 255],//背景色
font: 'simhei', //字体,如果不配置,中文仍会乱码
textColor: [0, 0, 0],//字体颜色
halign: 'center', // 文字水平布局left, center, right
valign: 'middle',//垂直布局
},
//表头样式配置
headStyles: {
fillColor: [220, 220, 220],
lineColor: 200,
lineWidth: 0.5,
},
//列的样式,key值对应header的dataKey
columnStyles: {
'time': { columnWidth: 35 },
},
theme: 'grid', // 主题
})
const pageSize = doc.getNumberOfPages()
doc.setLineWidth(0.3)
doc.setFontSize(12)
//设置页脚
for (let page = 1; page <= pageSize; page++) {
doc.setPage(page)
doc.setDrawColor('#f16c6c')
doc.line(25, pageHeight - 10, pageWidth - 25, pageHeight - 10)
doc.text('制作:某某某 审合:某某某 签发:某某某 电话:XXXXXXXXXXX', 40, pageHeight - 5)
}
doc.save(`${filename}.pdf`);
})
}
2.生成word:
1.使用的插件:docxjs
docx的安装和API、不同功能的案例demo此demo几乎包括了所有API的使用和配置。
2.demo
import {
Document,
TextRun,
Footer,
TabStopType,
AlignmentType,
TabStopPosition,
VerticalPositionRelativeFrom,
VerticalPositionAlign,
HorizontalPositionRelativeFrom,
HorizontalPositionAlign,
Media,
Packer,
Paragraph,
} from "docx";
export function exportForecastWord(filename) {
const doc = new Document();
//页脚
const footers = {
default: new Footer({
children: [new Paragraph({
children: [new TextRun('电话:010-68400565'), new TextRun('\t传真:010-58991637 ')],
//实现第一个text左对齐,第二个text右对齐
tabStops: [
{
type: TabStopType.RIGHT,
position: TabStopPosition.MAX,
},
],
border: {
top: { color: '000', value: 'dashed', size: 10, space: 5 }
}
})],
}),
}
formUrlGetDataUrl('../public/images/logo.jpg', (dataUrl) => {
const logoImge = Media.addImage(doc, dataUrl, 70, 70, {
//设置float样式主要是为了让图片和其水平相邻的文字垂直居中,可以去掉对比效果
floating: {
zIndex: 5,
horizontalPosition: {
relative: HorizontalPositionRelativeFrom.COLUMN,
align: HorizontalPositionAlign.LEFT,
},
verticalPosition: {
relative: VerticalPositionRelativeFrom.PARAGRAPH,
align: VerticalPositionAlign.CENTER,
},
},
});
doc.addSection({
children: [
new Paragraph({
children: [logoImge,
new TextRun({
text: "this is a wordTitle",
bold: true,
color: "red",
size: 60})
],
alignment: AlignmentType.RIGHT,
spacing: {
before: 150,
after: 150
}
}),
],
footers: footers
});
Packer.toBlob(doc).then(blob => {
var a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = `${filename.replace(/\s/g, '')}.docx`
setTimeout(function () {
a.click();
URL.revokeObjectURL(a.href);
a = null
}, 0);
});
})
}
/**
* 根据图片路径得到dataurl
* @param url 图片路径
* @param cb 回调函数
*/
function formUrlGetDataUrl(url, cb) {
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
var img = new Image();
img.src = url;
img.onload = () => {
canvas.width = img.width;
canvas.height = img.height;
ctx.drawImage(img, 0, 0);
cb(canvas.toDataURL())
canvas=null
};
}
使用这个demo时需要注意:文件中使用了一个图片相对路径,所以需要在对应路径下添加一个图片。
补充1:doxcjs生成表格时单元格文本的水平垂直居中实现:
function docxTable(tableData:any[]){
let data = removeNullData([...tableData])
const rows = data.map((row ,rowIndex)=> {
return new TableRow({
children: row.map((col)=>{
return new TableCell({
children: [new Paragraph({
children: [new TextRun({ text: String(col),size:20,bold:rowIndex===0?true:false })],
alignment:AlignmentType.CENTER//文本水平居中
})
],
verticalAlign: VerticalAlign.CENTER,
margins: {
//为文本上下设置相同的间距,实现垂直居中,默认文本和上下边界没有空白
top: convertInchesToTwip(0.1),
bottom: convertInchesToTwip(0.1),
left: 0,
right: 0,
},
})
})
})
})
return new Table({
rows,
width: {
size: 100,
type: WidthType.PERCENTAGE
},
});
}
const tableData=[['header1','header2'],['text1','text2']]
补充2:使用WPS打开生成的word文件部分格式不兼容问题解决:
1.包含表格时,如果设置width属性的type值为PERCENTAGE时,用WPS打开word文件,出现单元格width变窄的情况,
2.文本,border等设置的color未生效,显示都是黑色
解决:1. 可以不设置Table的width属性,如果需要固定表格的宽度可以设置Table或者TableCell的width属性的type值为WidthType.DXA
return new Table({
rows,
width: {
size: 9000,
type: WidthType.DXA
},
});
附上单位换算关系:参考:
2.color的值不要设置为red等单词而要使用16进制数值,且前面不要加#
new Paragraph({
children: [logoImge, new TextRun({
text: "天气预报",
bold: true,
color: "fa0202",
size: 60,
})],
alignment: AlignmentType.RIGHT,
spacing: {
before: 150,
after: 150
}
}),
更多推荐
前端js生成自定义内容的PDF及word文件的实现
发布评论