我正在尝试使用 pdfMake 和 Angular 从 HTML 创建 PDF(我也尝试过 jsPDF,但也无法使其工作)。我尝试在我的 Angular 控制器中使用以下代码:
var blob = new Blob([document.getElementById('exportable').innerHTML])
var docDefinition = {
content: [blob]
}
pdfMake.createPdf(docDefinition).open();
但我收到以下错误:
无法识别的文档结构:{"_margin":null}"。
我的 HTML 由 div 中的两个简单表格组成
exportable
。
如何解决此错误?
好吧,我明白了。
您将需要html2canvas和pdfmake。 您不需要在 app.js 中进行任何注入,只需包含在脚本标签中
在要创建 PDF 的 div 上,添加 ID 名称,如下所示:
<div id="exportthis">
在 Angular 控制器中,在调用 html2canvas 时使用 div 的 id:
使用 toDataURL() 将画布更改为图像
然后在 pdfmake 的 docDefinition 中将图像分配给内容。
控制器中完整的代码将如下所示:
html2canvas(document.getElementById('exportthis'), {
onrendered: function (canvas) {
var data = canvas.toDataURL();
var docDefinition = {
content: [{
image: data,
width: 500,
}]
};
pdfMake.createPdf(docDefinition).download("Score_Details.pdf");
}
});
我希望这对其他人有帮助。 快乐编码!
我知道它与这篇文章无关,但可能会帮助其他人在客户端将 HTML 转换为 PDF。如果您使用剑道,这是一个简单的解决方案。它还保留了 css(大多数情况下)。
var generatePDF = function() {
kendo.drawing.drawDOM($("#formConfirmation")).then(function(group) {
kendo.drawing.pdf.saveAs(group, "Converted PDF.pdf");
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="//kendo.cdn.telerik.com/2016.3.914/js/kendo.all.min.js"></script>
</head>
<body>
<br/>
<button class="btn btn-primary" onclick="generatePDF()"><i class="fa fa-save"></i> Save as PDF</button>
<br/>
<br/>
<div id="formConfirmation">
<div class="container theme-showcase" role="main">
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>Theme example</h1>
<p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p>
</div>
<div class="page-header">
<h1>Buttons</h1>
</div>
<p>
<button type="button" class="btn btn-lg btn-default">Default</button>
<button type="button" class="btn btn-lg btn-primary">Primary</button>
<button type="button" class="btn btn-lg btn-success">Success</button>
<button type="button" class="btn btn-lg btn-info">Info</button>
<button type="button" class="btn btn-lg btn-warning">Warning</button>
<button type="button" class="btn btn-lg btn-danger">Danger</button>
<button type="button" class="btn btn-lg btn-link">Link</button>
</p>
<p>
<button type="button" class="btn btn-default">Default</button>
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-link">Link</button>
</p>
<p>
<button type="button" class="btn btn-sm btn-default">Default</button>
<button type="button" class="btn btn-sm btn-primary">Primary</button>
<button type="button" class="btn btn-sm btn-success">Success</button>
<button type="button" class="btn btn-sm btn-info">Info</button>
<button type="button" class="btn btn-sm btn-warning">Warning</button>
<button type="button" class="btn btn-sm btn-danger">Danger</button>
<button type="button" class="btn btn-sm btn-link">Link</button>
</p>
<p>
<button type="button" class="btn btn-xs btn-default">Default</button>
<button type="button" class="btn btn-xs btn-primary">Primary</button>
<button type="button" class="btn btn-xs btn-success">Success</button>
<button type="button" class="btn btn-xs btn-info">Info</button>
<button type="button" class="btn btn-xs btn-warning">Warning</button>
<button type="button" class="btn btn-xs btn-danger">Danger</button>
<button type="button" class="btn btn-xs btn-link">Link</button>
</p>
<div class="page-header">
<h1>Tables</h1>
</div>
<div class="row">
<div class="col-md-6">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-md-6">
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2">1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>Mark</td>
<td>Otto</td>
<td>@TwBootstrap</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<table class="table table-condensed">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="page-header">
<h1>Thumbnails</h1>
</div>
<img data-src="holder.js/200x200" class="img-thumbnail" alt="A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera">
<div class="page-header">
<h1>Labels</h1>
</div>
<h1>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h1>
<h2>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h2>
<h3>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h3>
<h4>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h4>
<h5>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h5>
<h6>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h6>
<p>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</p>
<div class="page-header">
<h1>Badges</h1>
</div>
<p>
<a href="#">Inbox <span class="badge">42</span></a>
</p>
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="active"><a href="#">Home <span class="badge">42</span></a>
</li>
<li role="presentation"><a href="#">Profile</a>
</li>
<li role="presentation"><a href="#">Messages <span class="badge">3</span></a>
</li>
</ul>
<div class="page-header">
<h1>Dropdown menus</h1>
</div>
<div class="dropdown theme-dropdown clearfix">
<a id="dropdownMenu1" href="#" class="sr-only dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li class="active"><a href="#">Action</a>
</li>
<li><a href="#">Another action</a>
</li>
<li><a href="#">Something else here</a>
</li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a>
</li>
</ul>
</div>
<div class="page-header">
<h1>Navs</h1>
</div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#">Home</a>
</li>
<li role="presentation"><a href="#">Profile</a>
</li>
<li role="presentation"><a href="#">Messages</a>
</li>
</ul>
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="active"><a href="#">Home</a>
</li>
<li role="presentation"><a href="#">Profile</a>
</li>
<li role="presentation"><a href="#">Messages</a>
</li>
</ul>
<div class="page-header">
<h1>Navbars</h1>
</div>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a>
</li>
<li><a href="#about">About</a>
</li>
<li><a href="#contact">Contact</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a>
</li>
<li><a href="#">Another action</a>
</li>
<li><a href="#">Something else here</a>
</li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="#">Separated link</a>
</li>
<li><a href="#">One more separated link</a>
</li>
</ul>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a>
</li>
<li><a href="#about">About</a>
</li>
<li><a href="#contact">Contact</a>
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a>
</li>
<li><a href="#">Another action</a>
</li>
<li><a href="#">Something else here</a>
</li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="#">Separated link</a>
</li>
<li><a href="#">One more separated link</a>
</li>
</ul>
</li>
</ul>
</div>
<!--/.nav-collapse -->
</div>
</nav>
<div class="page-header">
<h1>Alerts</h1>
</div>
<div class="alert alert-success" role="alert">
<strong>Well done!</strong> You successfully read this important alert message.
</div>
<div class="alert alert-info" role="alert">
<strong>Heads up!</strong> This alert needs your attention, but it's not super important.
</div>
<div class="alert alert-warning" role="alert">
<strong>Warning!</strong> Best check yo self, you're not looking too good.
</div>
<div class="alert alert-danger" role="alert">
<strong>Oh snap!</strong> Change a few things up and try submitting again.
</div>
<div class="page-header">
<h1>Progress bars</h1>
</div>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"><span class="sr-only">60% Complete</span>
</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 40%"><span class="sr-only">40% Complete (success)</span>
</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%"><span class="sr-only">20% Complete</span>
</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete (warning)</span>
</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%"><span class="sr-only">80% Complete (danger)</span>
</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete</span>
</div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 35%"><span class="sr-only">35% Complete (success)</span>
</div>
<div class="progress-bar progress-bar-warning" style="width: 20%"><span class="sr-only">20% Complete (warning)</span>
</div>
<div class="progress-bar progress-bar-danger" style="width: 10%"><span class="sr-only">10% Complete (danger)</span>
</div>
</div>
<div class="page-header">
<h1>List groups</h1>
</div>
<div class="row">
<div class="col-sm-4">
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
</div>
<!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="list-group">
<a href="#" class="list-group-item active">
Cras justo odio
</a>
<a href="#" class="list-group-item">Dapibus ac facilisis in</a>
<a href="#" class="list-group-item">Morbi leo risus</a>
<a href="#" class="list-group-item">Porta ac consectetur ac</a>
<a href="#" class="list-group-item">Vestibulum at eros</a>
</div>
</div>
<!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="list-group">
<a href="#" class="list-group-item active">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
</a>
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
</a>
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
</a>
</div>
</div>
<!-- /.col-sm-4 -->
</div>
<div class="page-header">
<h1>Panels</h1>
</div>
<div class="row">
<div class="col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div>
<!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div>
<!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="panel panel-warning">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div>
<!-- /.col-sm-4 -->
</div>
</div>
</body>
</html>
我用这种方式 - 也许它对某人有用
import pdfMake from 'pdfmake/build/pdfmake';
import htmlToPdfmake from 'html-to-pdfmake';
saveReport() {
//Learning the html code of the table
let pdfTable = document.querySelector('#tableDataVM').innerHTML;
var html = htmlToPdfmake(pdfTable);
pdfMake.createPdf({
info: {
title: "Disposal Report",
author:'mikka',
subject:'Theme',
keywords:'Report'
},
footer: function (currentPage, pageCount) {
return {
margin: 10,
columns: [
{
fontSize: 9,
text: [
{
text: 'Page ' + currentPage.toString() + ' of ' + pageCount,
}
],
alignment: 'center'
}
]
};
},
content: [
{
text: "Disposal report for the period " + this.lastPeriod + " by average\n\n",
style: 'header',
alignment: 'center',
fontSize: 14
},
{
text:
"Param1: " + this.dataTableReport.host + " (" + this.dataTableReport.hostdescription + ")\n" +
"Param2: " + this.dataTableReport.claster + " (" + this.dataTableReport.clasterdescription + ")\n" +
"Param3: " + this.dataTableReport.pull + " (" + this.dataTableReport.pulldescription + ")\n",
fontSize: 10,
margin: [0, 0, 0, 20],
alignment: 'left'
},
html
],
pageOrientation: 'landscape'//'portrait'
}).open();
}
这对我有用 我正在使用 Angular2 应用程序中的 html2pdf,因此我在控制器中引用了此函数
var html2pdf = (function(html2canvas, jsPDF) {
在 html2pdf.js 中声明。
所以我在我的角度控制器中的导入声明之后添加了这个声明:
declare function html2pdf(html2canvas, jsPDF): any;
然后,从我的角度控制器的方法中调用此函数:
generate_pdf(){
this.someService.loadContent().subscribe(
pdfContent => {
html2pdf(pdfContent, {
margin: 1,
filename: 'myfile.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { dpi: 192, letterRendering: true },
jsPDF: { unit: 'in', format: 'A4', orientation: 'portrait' }
});
}
);
}
希望有帮助
已在 service-now 平台中实施。无需使用其他库 - makepdf 拥有您需要的一切!
我的 html 部分(包括 preloder gif):
<div class="pdf-preview" ng-init="generatePDF(true)">
<object data="{{c.content}}" type="application/pdf" style="width:58vh;height:88vh;" ng-if="c.content" ></object>
<div ng-if="!c.content">
<img src="https://support.lenovo.com/esv4/images/loading.gif" width="50" height="50">
</div>
</div>
这是客户端脚本(js部分)
$scope.generatePDF = function (preview) {
docDefinition = {} //you rootine to generate pdf content
//...
if (preview) {
pdfMake.createPdf(docDefinition).getDataUrl(function(dataURL) {
c.content = dataURL;
});
}
}
因此,在页面加载时,我触发生成 pdf 内容的 init 函数,如果需要预览(设置为 true)结果将分配给 c.content 变量。在 html 端,直到 c.content 获得一个值后才会显示对象,这样就会显示正在加载的 gif。