Angular 使用 css 将 html 转换为 pdf
Angular convert html to pdf with css
我需要使用 css 将 html 转换为 pdf,我使用了 windows.print() 但它不包括 css 样式
Html:
<button type="submit" (click)="generatePDFDescription()">
Generate Pdf
</button>
<div id="print-section">
...
</div>
组件类别:
@Component({
selector: 'app-generate-pdf-description',
templateUrl: './generate-pdf-description.component.html',
styleUrls: ['./generate-pdf-description.component.scss']
})
export class GeneratePdfDescriptionComponent implements OnInit {
constructor() { }
ngOnInit() {
}
generatePDFDescription(): void {
const element: Element = document.getElementById('print-section');
let myWindows = window.open('', 'PRINT', 'height=400,with=600');
myWindows.document.write("<!DOCTYPE html><html><head><meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='IE=edge'>"+
+ "<meta name='viewport' content='width=device-width, initial-scale=1'>"
+ "<link rel='stylesheet' type='text/css' media='screen' href='./generate-pdf-description.component.scss'>");
myWindows.document.write('</head><body>');
myWindows.document.write(element.innerHTML);
myWindows.document.write('</body></html>');
myWindows.document.close();
myWindows.focus();
myWindows.print();
}
}
结果:
预期结果:
我通过两件事解决了这个问题:
- 添加缩小 css:
您可以使用此网站 CSS Formatter 来缩小您的 css。
- 我通过添加基础url:
解决了图像问题
首先,您需要在 angular 应用程序中安装一些软件包。因此,打开您的终端并执行以下命令:
npm install --save pdfmake
npm install html-to-pdfmake
npm install jspdf --save
在View文件中添加代码,例如:
<div class="container">
<div id="pdfTable" #pdfTable>
<h2>Angular HTML To PDF Generator Example</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Website</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sam</td>
<td>Sam</td>
<td>tutsmake.com</td>
</tr>
<tr>
<td>john</td>
<td>dam</td>
<td>w3school.com</td>
</tr>
<tr>
<td>jonhy</td>
<td>hid</td>
<td>geeks.com</td>
</tr>
</tbody>
</table>
</div>
<button class="btn btn-primary" (click)="downloadAsPDF()">Export To PDF</button>
</div>
在组件.ts文件中添加代码,例如:
import { Component, ViewChild, ElementRef } from '@angular/core';
import jsPDF from 'jspdf';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;
import htmlToPdfmake from 'html-to-pdfmake';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'htmlToPDF';
@ViewChild('pdfTable') pdfTable: ElementRef;
public downloadAsPDF() {
const doc = new jsPDF();
const pdfTable = this.pdfTable.nativeElement;
var html = htmlToPdfmake(pdfTable.innerHTML);
const documentDefinition = { content: html };
pdfMake.createPdf(documentDefinition).open();
}
}
最后,测试您的应用程序。
我解决了导出 HTML 到多页 PDF 的问题。我为每个 div 创建了 canvas。或许这对大家有所帮助。
private canvas: any = {
monthYearCanvas: null,
monthYearHeight: 0,
periodCanvas: null,
periodHeight: 0,
assetCanvas: null,
assetHeight: 0,
badActorCanvas: null,
badActorHeight: 0,
eventCanvas: null,
eventHeight: 0,
tenLowOffCanvas: null,
tenLowOffHeight: 0,
};
public triggerPrintReport(): void {
if (
this.isLoadingMonthYear ||
this.isLoadingOnPeriod ||
this.isLoadingOnAsset ||
this.isLoadingOnBadActor ||
this.isLoadingOnEvent ||
this.isLoadingTenLowOff
) {
alert('Wait for load data');
return;
}
this.messageReport = true;
const monthYearHTML = document.getElementById('htmlData-monthYear');
const periodHTML = document.getElementById('htmlData-period');
const assetHTML = document.getElementById('htmlData-asset');
const badActorHTML = document.getElementById('htmlData-badActor');
const eventHTML = document.getElementById('htmlData-event');
const tenLowOffHTML = document.getElementById('htmlData-tenLowOff');
this.createCanvasURL(monthYearHTML, 'monthYear');
this.createCanvasURL(periodHTML, 'period');
this.createCanvasURL(assetHTML, 'asset');
this.createCanvasURL(badActorHTML, 'badActor');
this.createCanvasURL(eventHTML, 'event');
this.createCanvasURL(tenLowOffHTML, 'tenLowOff');
}
private createCanvasURL(element: any, type: string): void {
html2canvas(element).then(canvas => {
const width = 208;
if (type === 'monthYear') {
this.canvas.monthYearHeight = canvas.height * width / canvas.width;
this.canvas.monthYearCanvas = canvas.toDataURL('image/png');
} else if (type === 'period') {
this.canvas.periodHeight = canvas.height * width / canvas.width;
this.canvas.periodCanvas = canvas.toDataURL('image/png');
} else if (type === 'asset') {
this.canvas.assetHeight = canvas.height * width / canvas.width;
this.canvas.assetCanvas = canvas.toDataURL('image/png');
} else if (type === 'badActor') {
this.canvas.badActorHeight = canvas.height * width / canvas.width;
this.canvas.badActorCanvas = canvas.toDataURL('image/png');
} else if (type === 'event') {
this.canvas.eventHeight = canvas.height * width / canvas.width;
this.canvas.eventCanvas = canvas.toDataURL('image/png');
} else if (type === 'tenLowOff') {
this.canvas.tenLowOffHeight = canvas.height * width / canvas.width;
this.canvas.tenLowOffCanvas = canvas.toDataURL('image/png');
}
this.exportPDF();
});
}
private exportPDF(): void {
const PDF = new jsPDF('p', 'mm', 'a4');
if (
this.canvas.monthYearCanvas &&
this.canvas.periodCanvas &&
this.canvas.assetCanvas &&
this.canvas.badActorCanvas &&
this.canvas.badActorCanvas &&
this.canvas.tenLowOffCanvas
) {
PDF.addImage(this.canvas.monthYearCanvas, 'PNG', 1, 10, 208, this.canvas.monthYearHeight);
PDF.addImage(this.canvas.periodCanvas, 'PNG', 1, 125, 208, this.canvas.periodHeight);
PDF.addPage();
PDF.addImage(this.canvas.assetCanvas, 'PNG', 1, 10, 208, this.canvas.assetHeight);
PDF.addPage();
PDF.addImage(this.canvas.badActorCanvas, 'PNG', 1, 10, 208, this.canvas.badActorHeight);
PDF.addPage();
PDF.addImage(this.canvas.eventCanvas, 'PNG', 1, 10, 208, this.canvas.eventHeight);
PDF.addPage('l');
PDF.addImage(this.canvas.tenLowOffCanvas, 'PNG', 1, 10, 208, this.canvas.tenLowOffHeight);
this.messageReport = false;
PDF.save('angular-demo.pdf');
}
}
我需要使用 css 将 html 转换为 pdf,我使用了 windows.print() 但它不包括 css 样式
Html:
<button type="submit" (click)="generatePDFDescription()">
Generate Pdf
</button>
<div id="print-section">
...
</div>
组件类别:
@Component({
selector: 'app-generate-pdf-description',
templateUrl: './generate-pdf-description.component.html',
styleUrls: ['./generate-pdf-description.component.scss']
})
export class GeneratePdfDescriptionComponent implements OnInit {
constructor() { }
ngOnInit() {
}
generatePDFDescription(): void {
const element: Element = document.getElementById('print-section');
let myWindows = window.open('', 'PRINT', 'height=400,with=600');
myWindows.document.write("<!DOCTYPE html><html><head><meta charset='utf-8'><meta http-equiv='X-UA-Compatible' content='IE=edge'>"+
+ "<meta name='viewport' content='width=device-width, initial-scale=1'>"
+ "<link rel='stylesheet' type='text/css' media='screen' href='./generate-pdf-description.component.scss'>");
myWindows.document.write('</head><body>');
myWindows.document.write(element.innerHTML);
myWindows.document.write('</body></html>');
myWindows.document.close();
myWindows.focus();
myWindows.print();
}
}
结果:
预期结果:
我通过两件事解决了这个问题:
- 添加缩小 css:
您可以使用此网站 CSS Formatter 来缩小您的 css。
- 我通过添加基础url: 解决了图像问题
首先,您需要在 angular 应用程序中安装一些软件包。因此,打开您的终端并执行以下命令:
npm install --save pdfmake
npm install html-to-pdfmake
npm install jspdf --save
在View文件中添加代码,例如:
<div class="container">
<div id="pdfTable" #pdfTable>
<h2>Angular HTML To PDF Generator Example</h2>
<table class="table table-bordered">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Website</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sam</td>
<td>Sam</td>
<td>tutsmake.com</td>
</tr>
<tr>
<td>john</td>
<td>dam</td>
<td>w3school.com</td>
</tr>
<tr>
<td>jonhy</td>
<td>hid</td>
<td>geeks.com</td>
</tr>
</tbody>
</table>
</div>
<button class="btn btn-primary" (click)="downloadAsPDF()">Export To PDF</button>
</div>
在组件.ts文件中添加代码,例如:
import { Component, ViewChild, ElementRef } from '@angular/core';
import jsPDF from 'jspdf';
import pdfMake from 'pdfmake/build/pdfmake';
import pdfFonts from 'pdfmake/build/vfs_fonts';
pdfMake.vfs = pdfFonts.pdfMake.vfs;
import htmlToPdfmake from 'html-to-pdfmake';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'htmlToPDF';
@ViewChild('pdfTable') pdfTable: ElementRef;
public downloadAsPDF() {
const doc = new jsPDF();
const pdfTable = this.pdfTable.nativeElement;
var html = htmlToPdfmake(pdfTable.innerHTML);
const documentDefinition = { content: html };
pdfMake.createPdf(documentDefinition).open();
}
}
最后,测试您的应用程序。
我解决了导出 HTML 到多页 PDF 的问题。我为每个 div 创建了 canvas。或许这对大家有所帮助。
private canvas: any = {
monthYearCanvas: null,
monthYearHeight: 0,
periodCanvas: null,
periodHeight: 0,
assetCanvas: null,
assetHeight: 0,
badActorCanvas: null,
badActorHeight: 0,
eventCanvas: null,
eventHeight: 0,
tenLowOffCanvas: null,
tenLowOffHeight: 0,
};
public triggerPrintReport(): void {
if (
this.isLoadingMonthYear ||
this.isLoadingOnPeriod ||
this.isLoadingOnAsset ||
this.isLoadingOnBadActor ||
this.isLoadingOnEvent ||
this.isLoadingTenLowOff
) {
alert('Wait for load data');
return;
}
this.messageReport = true;
const monthYearHTML = document.getElementById('htmlData-monthYear');
const periodHTML = document.getElementById('htmlData-period');
const assetHTML = document.getElementById('htmlData-asset');
const badActorHTML = document.getElementById('htmlData-badActor');
const eventHTML = document.getElementById('htmlData-event');
const tenLowOffHTML = document.getElementById('htmlData-tenLowOff');
this.createCanvasURL(monthYearHTML, 'monthYear');
this.createCanvasURL(periodHTML, 'period');
this.createCanvasURL(assetHTML, 'asset');
this.createCanvasURL(badActorHTML, 'badActor');
this.createCanvasURL(eventHTML, 'event');
this.createCanvasURL(tenLowOffHTML, 'tenLowOff');
}
private createCanvasURL(element: any, type: string): void {
html2canvas(element).then(canvas => {
const width = 208;
if (type === 'monthYear') {
this.canvas.monthYearHeight = canvas.height * width / canvas.width;
this.canvas.monthYearCanvas = canvas.toDataURL('image/png');
} else if (type === 'period') {
this.canvas.periodHeight = canvas.height * width / canvas.width;
this.canvas.periodCanvas = canvas.toDataURL('image/png');
} else if (type === 'asset') {
this.canvas.assetHeight = canvas.height * width / canvas.width;
this.canvas.assetCanvas = canvas.toDataURL('image/png');
} else if (type === 'badActor') {
this.canvas.badActorHeight = canvas.height * width / canvas.width;
this.canvas.badActorCanvas = canvas.toDataURL('image/png');
} else if (type === 'event') {
this.canvas.eventHeight = canvas.height * width / canvas.width;
this.canvas.eventCanvas = canvas.toDataURL('image/png');
} else if (type === 'tenLowOff') {
this.canvas.tenLowOffHeight = canvas.height * width / canvas.width;
this.canvas.tenLowOffCanvas = canvas.toDataURL('image/png');
}
this.exportPDF();
});
}
private exportPDF(): void {
const PDF = new jsPDF('p', 'mm', 'a4');
if (
this.canvas.monthYearCanvas &&
this.canvas.periodCanvas &&
this.canvas.assetCanvas &&
this.canvas.badActorCanvas &&
this.canvas.badActorCanvas &&
this.canvas.tenLowOffCanvas
) {
PDF.addImage(this.canvas.monthYearCanvas, 'PNG', 1, 10, 208, this.canvas.monthYearHeight);
PDF.addImage(this.canvas.periodCanvas, 'PNG', 1, 125, 208, this.canvas.periodHeight);
PDF.addPage();
PDF.addImage(this.canvas.assetCanvas, 'PNG', 1, 10, 208, this.canvas.assetHeight);
PDF.addPage();
PDF.addImage(this.canvas.badActorCanvas, 'PNG', 1, 10, 208, this.canvas.badActorHeight);
PDF.addPage();
PDF.addImage(this.canvas.eventCanvas, 'PNG', 1, 10, 208, this.canvas.eventHeight);
PDF.addPage('l');
PDF.addImage(this.canvas.tenLowOffCanvas, 'PNG', 1, 10, 208, this.canvas.tenLowOffHeight);
this.messageReport = false;
PDF.save('angular-demo.pdf');
}
}