当我使用以下HTML+CSS生成具有页眉和页脚的表时,它会在打印和通过iText 7 pdfHTML库转换为pdfHTML时重复每个页面上的页眉和页脚。在浏览器打印和输出中,文档的外观/行为都与来自iText的PDF相同。我试图使页眉和页脚被固定到每个页面的顶部和底部,没有表格中的行数。
Java/iText将html文档转换为pdf.
var mediaDeviceDescription = new MediaDeviceDescription(MediaType.PRINT);
var props = new ConverterProperties();
props.setMediaDeviceDescription(mediaDeviceDescription);
HtmlConverter.convertToPdf(html, new FileOutputStream(pdfTempFile.toFile()), props);
html..。
<html>
<head>
<title>Invoice</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
@page {
margin: 0;
}
.label-font {
font-size: 18px;
letter-spacing: 3.6px;
word-spacing: 2.2px;
color: #000000;
font-weight: 700;
font-style: normal;
text-transform: none;
}
.companySection {
margin-top: 10px;
width: 100%;
display: flex;
justify-content: space-between;
}
.logoBusinessDetails {
flex-grow: 1;
}
.headerBusinessFont {
font-size: 32px;
letter-spacing: 3.6px;
word-spacing: 2.2px;
color: #000000;
font-weight: 700;
text-decoration: overline solid rgb(68, 68, 68);
font-style: normal;
font-variant: small-caps;
text-transform: none;
}
table.invoiceItems {
margin-top: 10px;
border: 2px solid #000000;
width: 100%;
text-align: left;
border-collapse: collapse;
}
table.invoiceItems td,
table.invoiceItems th {
border: 1px solid #000000;
padding: 6px 5px;
}
table.invoiceItems tbody td {
font-size: 13px;
}
table.invoiceItems tr:nth-child(even) {
/*background: #667FFF;*/
}
table.invoiceItems thead {
background: #667FFF;
background: -moz-linear-gradient(top, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
background: -webkit-linear-gradient(top, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
background: linear-gradient(to bottom, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
border-bottom: 3px solid #000000;
}
table.invoiceItems thead th {
font-size: 15px;
font-weight: bold;
color: #000000;
text-align: left;
}
invoiceItems.table.invoiceItems tfoot td {
font-size: 14px;
}
.customerSection {
width: 100%;
display: flex;
align-items: flex-start;
}
.billTo {
border-left: 15px solid #808080;
flex-grow: 1;
}
.shipTo {
border-left: 15px solid #808080;
flex-grow: 1;
}
.documentDetails {
/*border-left: 15px solid #667FFF;*/
flex-grow: 1;
}
.message {
flex-basis: 65%
}
.totals {
flex-basis: 35%;
}
.totalColumns {
width: 100%;
display: flex;
}
.totalLabels {
flex-basis: 50%
}
.totalAmounts {
flex-basis: 50%
}
/* Total labels column*/
table.totalLabels {
border-width: 0px 1px 0px 2px;
border-style: solid;
border-color: #000000;
width: 100%;
text-align: right;
border-collapse: collapse;
}
table.totalLabels td,
table.totalLabels th {
border: 1px solid #000000;
padding: 5px 4px;
}
table.totalLabels tbody td {
font-size: 13px;
}
table.totalLabels tfoot {
font-size: 14px;
font-weight: bold;
color: #000000;
border-top: 3px solid #000000;
}
table.totalLabels tfoot td {
font-size: 14px;
}
/* Amounts Column*/
table.totalAmounts {
border-width: 0px 2px 0px 1px;
border-style: solid;
border-color: #000000;
width: 100%;
text-align: right;
border-collapse: collapse;
}
table.totalAmounts td,
table.totalAmounts th {
border: 1px solid #000000;
padding: 5px 4px;
}
table.totalAmounts tbody td {
font-size: 13px;
}
table.totalAmounts tfoot {
font-size: 14px;
font-weight: bold;
color: #000000;
border-top: 3px solid #000000;
}
table.totalAmounts tfoot td {
font-size: 14px;
}
table.documentInfo {
width: 100%;
text-align: right;
}
table.documentInfo td,
table.documentInfo th {}
.footer {
border: 2px #000000;
}
tbody.invoiceItems tr td {
border: 1px solid #000000;
text-align: left;
border-collapse: collapse;
width: 100%;
}
table {
border-spacing: 0px;
width: 100%;
}
@media print, screen{
.headerSection {
width: 100%;
}
.summarySection {
width: 100%;
display: flex;
align-items: flex-start;
}
}
}
</style>
</head>
<body>
<div>
<table>
<thead>
<tr>
<td colspan="8">
<!--<div class="header-space"></div>-->
<div class="headerSection">
<div class="companySection">
<div class="headerBusinessLogo headerBusinessFont logoBusinessDetails">
Acme Paper Co LLC
</div>
</div>
<div class="customerSection">
<div class="billTo"><span style="font-weight: bold;">Bill To:</span><br>${billTo}</div>
<div class="shipTo"><span style="font-weight: bold;">Ship To:</span><br>${shipTo}</div>
<div class="documentDetails">
<table class="documentInfo">
<tbody>
<tr>
<td>Invoice Number</td>
<td>${invoice.invoiceNumber}</td>
</tr>
<tr>
<td>Invoice Date: </td>
<td>2022-03-12</td>
</tr>
<tr>
<td>Due Date</td>
<td>2022-03-12</td>
</tr>
<tr>
<td>Tax Id</td>
<td>D288658797</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</td>
</tr>
<tr>
<th>Quantity</th>
<th>Code</th>
<th>Description</th>
<th>Unit Price</th>
<th>Tax1</th>
<th>Tax2</th>
<th>Line Total</th>
</tr>
</thead>
<tbody class="invoiceItems">
<!-- <#list items as item> -->
<tr>
<td style="width: 10%;">${item.quantity}</td>
<td style="width: 15%;">
<#if item.code?has_content>
${item.code}
</#if>
</td>
<td style="width: 45%;">${item.description}</td>
<td style="text-align: right; width: 10%;">${item.unitPrice}</td>
<td style="text-align: center; width: 5%;">${item.taxable1?string('yes','no')}</td>
<td style="text-align: center; width: 5%;">${item.taxable2?string('yes','no')}</td>
<td style="text-align: right; width: 10%;">${item.getItemSubtotal()}</td>
</tr>
<!-- other rows ommitted to reduce body size for SO-->
<!-- </#list> -->
</tbody>
<tfoot>
<tr>
<td colspan="8">
<!--<div class="summary-space"></div>-->
<div class="summarySection">
<div class="message">
<p>The 13-letter motto was suggested in 1776 by Pierre Eugene du Simitiere to the
committee responsible for
developing the seal. At the time of the American Revolution, the phrase appeared
regularly on the title page
of the London-based Gentleman's Magazine, founded in 1731,[10][11] which collected
articles from many
sources into one periodical. This usage in turn can be traced back to the
London-based Huguenot Peter
Anthony Motteux, who had employed the adage for his The Gentleman's Journal, or the
Monthly Miscellany
(1692-1694). The phrase is similar to a Latin translation of a variation of
Heraclitus's tenth fragment,
"The one is made up of all things, and all things issue from the one".</p>
</div>
<div class="totals">
<div class="totalColumns">
<table class="totalLabels">
<tbody>
<tr>
<td>Item Total</td>
</tr>
<tr>
<td>Discounts</td>
</tr>
<tr>
<td>Taxable1</td>
</tr>
<tr>
<td>Taxable2</td>
</tr>
<tr>
<td>Tax1</td>
</tr>
<tr>
<td>Tax2</td>
</tr>
<tr>
<td>Payments</td>
</tr>
<tr>
<td>Amount Due</td>
</tr>
</tbody>
</table>
<table class="totalAmounts">
<tbody>
<tr>
<td>${subTotal}</td>
</tr>
<tr>
<td>${discountsTotal}</td>
</tr>
<tr>
<td>${taxable1Subtotal}</td>
</tr>
<tr>
<td>${taxable2Subtotal}</td>
</tr>
<tr>
<td>${tax1Total}</td>
</tr>
<tr>
<td>${tax2Total}</td>
</tr>
<tr>
<td>${payments}</td>
</tr>
<tr>
<td>${amountDue}</td>
</tr>
</tbody>
</table>
</div>
</div>
</td>
</tr>
</div>
</tfoot>
</table>
</div>
</body>
</html>
浏览器打印输出。(注意页脚(用红色标记)是如何在最后一页的表内容结束后直接出现的-如果没有足够的行来填充整个页面,则是第一页。)
iText PDF输出。(与从浏览器打印HTML版本相同。这里的一致性很好,但我希望页脚与每个页面的底部挂钩,而不管表行的数量如何。)
我找到了一种方法,使页眉和页脚被卡在每个页面的顶部和底部,而不管使用CSS计算表行数,而且它在从浏览器打印时工作,但是iText是一场灾难。
使用此方法在此处详细说明:https://medium.com/@Idan_Co/the-ultimate-print-html-template-with-header-footer-568f415f6d2a
这个HTML+CSS..。
<html>
<head>
<title>Invoice</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
margin: 0;
padding: 0;
}
@page {
margin: 0;
}
.label-font {
font-size: 18px;
letter-spacing: 3.6px;
word-spacing: 2.2px;
color: #000000;
font-weight: 700;
font-style: normal;
text-transform: none;
}
.companySection {
margin-top: 10px;
width: 100%;
display: flex;
justify-content: space-between;
}
.logoBusinessDetails {
flex-grow: 1;
}
.headerBusinessFont {
font-size: 32px;
letter-spacing: 3.6px;
word-spacing: 2.2px;
color: #000000;
font-weight: 700;
text-decoration: overline solid rgb(68, 68, 68);
font-style: normal;
font-variant: small-caps;
text-transform: none;
}
table.invoiceItems {
margin-top: 10px;
border: 2px solid #000000;
width: 100%;
text-align: left;
border-collapse: collapse;
}
table.invoiceItems td,
table.invoiceItems th {
border: 1px solid #000000;
padding: 6px 5px;
}
table.invoiceItems tbody td {
font-size: 13px;
}
table.invoiceItems tr:nth-child(even) {
/*background: #667FFF;*/
}
table.invoiceItems thead {
background: #667FFF;
background: -moz-linear-gradient(top, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
background: -webkit-linear-gradient(top, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
background: linear-gradient(to bottom, #dbdbdb 0%, #d3d3d3 66%, #CFCFCF 100%);
border-bottom: 3px solid #000000;
}
table.invoiceItems thead th {
font-size: 15px;
font-weight: bold;
color: #000000;
text-align: left;
}
invoiceItems.table.invoiceItems tfoot td {
font-size: 14px;
}
.customerSection {
width: 100%;
display: flex;
align-items: flex-start;
}
.billTo {
border-left: 15px solid #808080;
flex-grow: 1;
}
.shipTo {
border-left: 15px solid #808080;
flex-grow: 1;
}
.documentDetails {
/*border-left: 15px solid #667FFF;*/
flex-grow: 1;
}
.message {
flex-basis: 65%
}
.totals {
flex-basis: 35%;
}
.totalColumns {
width: 100%;
display: flex;
}
.totalLabels {
flex-basis: 50%
}
.totalAmounts {
flex-basis: 50%
}
/* Total labels column*/
table.totalLabels {
border-width: 0px 1px 0px 2px;
border-style: solid;
border-color: #000000;
width: 100%;
text-align: right;
border-collapse: collapse;
}
table.totalLabels td,
table.totalLabels th {
border: 1px solid #000000;
padding: 5px 4px;
}
table.totalLabels tbody td {
font-size: 13px;
}
table.totalLabels tfoot {
font-size: 14px;
font-weight: bold;
color: #000000;
border-top: 3px solid #000000;
}
table.totalLabels tfoot td {
font-size: 14px;
}
/* Amounts Column*/
table.totalAmounts {
border-width: 0px 2px 0px 1px;
border-style: solid;
border-color: #000000;
width: 100%;
text-align: right;
border-collapse: collapse;
}
table.totalAmounts td,
table.totalAmounts th {
border: 1px solid #000000;
padding: 5px 4px;
}
table.totalAmounts tbody td {
font-size: 13px;
}
table.totalAmounts tfoot {
font-size: 14px;
font-weight: bold;
color: #000000;
border-top: 3px solid #000000;
}
table.totalAmounts tfoot td {
font-size: 14px;
}
table.documentInfo {
width: 100%;
text-align: right;
}
table.documentInfo td,
table.documentInfo th {}
.footer {
border: 2px #000000;
}
tbody.invoiceItems tr td {
border: 1px solid #000000;
text-align: left;
border-collapse: collapse;
width: 100%;
}
table {
border-spacing: 0px;
width: 100%;
}
@media print, screen{
.headerSection {
width: 100%;
position: fixed;
top: 0;
}
.summarySection {
width: 100%;
display: flex;
align-items: flex-start;
}
.headerSection,
.header-space {
height: 200px;
}
.summarySection,
.summary-space {
height: 230px;
}
.summarySection {
position: fixed;
bottom: 0;
}
}
</style>
</head>
<body>
<div>
<table>
<thead>
<tr>
<td colspan="8">
<div class="header-space"></div>
</td>
</tr>
<tr>
<th>Quantity</th>
<th>Code</th>
<th>Description</th>
<th>Unit Price</th>
<th>Tax1</th>
<th>Tax2</th>
<th>Line Total</th>
</tr>
</thead>
<tbody class="invoiceItems">
<!-- <#list items as item> -->
<tr>
<td style="width: 10%;">${item.quantity}</td>
<td style="width: 15%;">
<#if item.code?has_content>
${item.code}
</#if>
</td>
<td style="width: 45%;">${item.description}</td>
<td style="text-align: right; width: 10%;">${item.unitPrice}</td>
<td style="text-align: center; width: 5%;">${item.taxable1?string('yes','no')}</td>
<td style="text-align: center; width: 5%;">${item.taxable2?string('yes','no')}</td>
<td style="text-align: right; width: 10%;">${item.getItemSubtotal()}</td>
</tr>
<!-- other rows ommitted to reduce body size for SO-->
<!-- </#list> -->
</tbody>
<tfoot>
<tr>
<td colspan="8">
<div class="summary-space"></div>
</td>
</tr>
</div>
</tfoot>
</table>
<div class="headerSection">
<div class="companySection">
<div class="headerBusinessLogo headerBusinessFont logoBusinessDetails">
ACME Gaming Co LLC
</div>
</div>
<div class="customerSection">
<div class="billTo"><span style="font-weight: bold;">Bill To:</span><br>${billTo}</div>
<div class="shipTo"><span style="font-weight: bold;">Ship To:</span><br>${shipTo}</div>
<div class="documentDetails">
<table class="documentInfo">
<tbody>
<tr>
<td>Invoice Number</td>
<td>${invoice.invoiceNumber}</td>
</tr>
<tr>
<td>Invoice Date: </td>
<td>2022-03-12</td>
</tr>
<tr>
<td>Due Date</td>
<td>2022-03-12</td>
</tr>
<tr>
<td>Tax Id</td>
<td>D288658797</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="summarySection">
<div class="message">
<p>The 13-letter motto was suggested in 1776 by Pierre Eugene du Simitiere to the
committee responsible for
developing the seal. At the time of the American Revolution, the phrase appeared
regularly on the title page
of the London-based Gentleman's Magazine, founded in 1731,[10][11] which collected
articles from many
sources into one periodical. This usage in turn can be traced back to the
London-based Huguenot Peter
Anthony Motteux, who had employed the adage for his The Gentleman's Journal, or the
Monthly Miscellany
(1692-1694). The phrase is similar to a Latin translation of a variation of
Heraclitus's tenth fragment,
"The one is made up of all things, and all things issue from the one".</p>
</div>
<div class="totals">
<div class="totalColumns">
<table class="totalLabels">
<tbody>
<tr>
<td>Item Total</td>
</tr>
<tr>
<td>Discounts</td>
</tr>
<tr>
<td>Taxable1</td>
</tr>
<tr>
<td>Taxable2</td>
</tr>
<tr>
<td>Tax1</td>
</tr>
<tr>
<td>Tax2</td>
</tr>
<tr>
<td>Payments</td>
</tr>
<tr>
<td>Amount Due</td>
</tr>
</tbody>
</table>
<table class="totalAmounts">
<tbody>
<tr>
<td>${subTotal}</td>
</tr>
<tr>
<td>${discountsTotal}</td>
</tr>
<tr>
<td>${taxable1Subtotal}</td>
</tr>
<tr>
<td>${taxable2Subtotal}</td>
</tr>
<tr>
<td>${tax1Total}</td>
</tr>
<tr>
<td>${tax2Total}</td>
</tr>
<tr>
<td>${payments}</td>
</tr>
<tr>
<td>${amountDue}</td>
</tr>
</tbody>
</table>
</div>
</div>
<!--<div class="footer" style="border: 2px solid black;">Page 1 of 1</div>-->
</div>
</body>
</html>
浏览器打印输出..。(每一页顶部/底部的页眉/页脚都是完美的)
iText pdfHTML输出。(除非end...just忽略固定位置CSS并在表内容之后转储页眉和页脚div,否则不会打印页眉/页脚)
发布于 2022-04-23 20:48:22
HTML4.0.2允许您从pdfHTML文件中生成PDF,并以完全声明式的风格轻松地添加页眉和页脚(因此只使用HTML+CSS组合,而不必编写大量样板代码)。
您甚至可以将页面编号添加到输出PDF中,所有这些都是由pdfHTML处理的纯CSS指令。
下面是一个HTML文件的示例:
<!DOCTYPE html>
<html>
<body>
<style>
#header {
position: running(header);
}
#footer {
position: running(footer);
}
@page {
margin-top: 100px;
margin-bottom: 100px;
@top-center {
content: element(header);
}
@bottom-center {
content: element(footer);
}
}
#current-page-placeholder::before {
content: counter(page);
}
#total-pages-placeholder::before {
content: counter(pages);
}
</style>
<div id="header"><p style="color: green">This is a header</p></div>
<div id="footer"><p style="color: red">This is a footer. Page <span id="current-page-placeholder"></span>/<span id="total-pages-placeholder"></span></p></div>
<h2>An ordered HTML list</h2>
<ol>
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
<ol type="1">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
<ol type="A">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
<ol type="a">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
<ol type="I">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
<ol type="i">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ol>
</body>
</html>
视觉输出结果:
这是通过单行呼叫实现的:
HtmlConverter.convertToPdf(new File("in.html"), new File("out.pdf"));
https://stackoverflow.com/questions/71670809
复制相似问题