java itextpdf使用HTML模板生成pdf文件,并设置table

我们这里是maven项目,导入相应jar包:

   <dependency>
        <groupId>org.freemarker</groupId>
        <artifactId>freemarker</artifactId>
        <version>2.3.23</version>
    </dependency>
 	<dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.4.1</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext-asian</artifactId>
        <version>5.2.0</version>
    </dependency>
    <dependency>
        <groupId>com.itextpdf.tool</groupId>
        <artifactId>xmlworker</artifactId>
        <version>5.4.1</version>
     </dependency>

注意:建议 itextpdf 和 tool 包版本一致,不然有可能会出现未知错误(我遇到一次~)

第一步:

编写 freemarker模板:freemarker.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Title</title>
    <style>
        body{
            font-family:SimHei;
        }
        .red{
            color: red;
        }
    </style>
</head>
<body>
<div class="red">
    你好,${name}
</div>
</body>
</html>

  

第二步: 获取模板信息,并且合并数据

package com.springdemo.job;

import java.io.File;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.XMLWorkerFontProvider;
import com.itextpdf.tool.xml.XMLWorkerHelper;

import freemarker.template.Configuration;

public class Test {

	private static final String DEST = "H:\\test\\test.pdf";

	private static final String HTML = "freemarker.html";

	private static final String FONT = "simhei.ttf";

	private static Configuration freemarkerCfg = null;

	static {
		freemarkerCfg = new Configuration();
		// 获取freemarker的模板目录
		try {
			freemarkerCfg.setDirectoryForTemplateLoading(new File("H:\\test\\").getCanonicalFile());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * html渲染为pdf
	 *
	 * @param data
	 *            变量
	 * @param htmlTmp
	 *            模板文件名
	 * @param pdftemp
	 *            pdf导出路径
	 * @return
	 */
	public static String freeMarkerRender(Map<String, Object> data, String htmlTmp, String pdftemp) {

		// 获取模板,并设置编码方式
		Template template = freemarkerCfg.getTemplate(htmlTmp);
		template.setEncoding("UTF-8");

		StringWriter out = new StringWriter();

		// 合并模板跟数据
		template.process(data, out);

		// htmlData 模板字符流
		String htmlData = out.toString();

		// 设置文档格式,数字边距
		Document document = new Document(PageSize.A4, 30, 30, 30, 30);

		PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(pdftemp));

		// 添加页码
		PDFBuilder builder = new PDFBuilder();
		writer.setPageEvent(builder);

		// 打开文档
		document.open();

		XMLWorkerHelper.getInstance().parseXHtml(writer, document, new ByteArrayInputStream(htmlData.getBytes()), null,
				new MyFontsProvider());

		// 关闭文档
		document.close();

	}

	public static void main(String[] args) throws Exception {
		Map<String, Object> data = new HashMap();
		data.put("name", "test");
		Test.freeMarkerRender(data, HTML, DEST);

	}
}

PDF设置字符集

package com.springdemo.job;
/**
 * 设置字符集
 */
public static class MyFontsProvider extends XMLWorkerFontProvider {

    public MyFontsProvider(){
        super(null, null);
    }

    @Override
    public Font getFont(final String fontname, String encoding, float size, final int style) {
        String fntnames = fontname;
        Font FontChinese = null;
        if (fntnames == null) {
            fntnames = "宋体";
        }
        if (size == 0) {
            size = 4;
        }
        try{
            BaseFont bfChinese = BaseFont.createFont("STSong-Light",
                    "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
            FontChinese = new Font(bfChinese, 12, Font.NORMAL);
        }catch (Exception e){
            e.printStackTrace();
        }
        if(FontChinese==null){
            FontChinese = super.getFont(fntnames, encoding, size, style);
        }
        return FontChinese;
    }

}

  

设置自动分页类

package com.springdemo.job;

import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfTemplate;
import com.itextpdf.text.pdf.PdfWriter;

public class PDFBuilder extends PdfPageEventHelper {

	/**
	 * 页眉
	 */
	public String header = "";

	/**
	 * 文档字体大小,页脚页眉最好和文本大小一致
	 */
	public int presentFontSize = 12;

	/**
	 * 文档页面大小,最好前面传入,否则默认为A4纸张
	 */
	public Rectangle pageSize = PageSize.A4;

	// 模板
	public PdfTemplate total;

	// 基础字体对象
	public BaseFont bf = null;

	// 利用基础字体生成的字体对象,一般用于生成中文文字
	public Font fontDetail = null;

/**
*
* Creates a new instance of PdfReportM1HeaderFooter 无参构造方法.
*
*/
public PdfReportM1HeaderFooter() {

}

/**
*
* Creates a new instance of PdfReportM1HeaderFooter 构造方法.
*
* @param yeMei
* 页眉字符串
* @param presentFontSize
* 数据体字体大小
* @param pageSize
* 页面文档大小,A4,A5,A6横转翻转等Rectangle对象
*/
public PdfReportM1HeaderFooter(String yeMei, int presentFontSize, Rectangle pageSize) {
this.header = yeMei;
this.presentFontSize = presentFontSize;
this.pageSize = pageSize;
}

	public void setHeader(String header) {
		this.header = header;
	}

	public void setPresentFontSize(int presentFontSize) {
		this.presentFontSize = presentFontSize;
	}

	/**
	 *
	 * TODO 文档打开时创建模板
	 *
	 * @see com.itextpdf.text.pdf.PdfPageEventHelper#onOpenDocument(com.itextpdf.text.pdf.PdfWriter,
	 *      com.itextpdf.text.Document)
	 */
	public void onOpenDocument(PdfWriter writer, Document document) {
		total = writer.getDirectContent().createTemplate(50, 50);// 共 页 的矩形的长宽高
	}

	/**
	 *
	 * TODO 关闭每页的时候,写入页眉,写入‘第几页共‘这几个字。
	 *
	 * @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(com.itextpdf.text.pdf.PdfWriter,
	 *      com.itextpdf.text.Document)
	 */
	public void onEndPage(PdfWriter writer, Document document) {

		try {
			if (bf == null) {
				bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", false);
			}
			if (fontDetail == null) {
				fontDetail = new Font(bf, presentFontSize, Font.NORMAL);// 数据体字体
			}
		} catch (DocumentException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

		// 1.写入页眉
		ColumnText.showTextAligned(writer.getDirectContent(), Element.ALIGN_LEFT, new Phrase(header, fontDetail),
				document.left(), document.top() + 20, 0);
		// 2.写入前半部分的 第 X页/共
		int pageS = writer.getPageNumber();
		String foot1 = "第 " + pageS + " 页 /共";
		Phrase footer = new Phrase(foot1, fontDetail);

		// 3.计算前半部分的foot1的长度,后面好定位最后一部分的‘Y页‘这俩字的x轴坐标,字体长度也要计算进去 = len
		float len = bf.getWidthPoint(foot1, presentFontSize);

		// 4.拿到当前的PdfContentByte
		PdfContentByte cb = writer.getDirectContent();

		// 5.写入页脚1,x轴就是(右margin+左margin + right() -left()- len)/2.0F
		// 再给偏移20F适合人类视觉感受,否则肉眼看上去就太偏左了
		// ,y轴就是底边界-20,否则就贴边重叠到数据体里了就不是页脚了;注意Y轴是从下往上累加的,最上方的Top值是大于Bottom好几百开外的。
		ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, footer,
				(document.rightMargin() + document.right() + document.leftMargin() - document.left() - len) / 2.0F
						+ 20F,
				document.bottom() - 20, 0);

		// 6.写入页脚2的模板(就是页脚的Y页这俩字)添加到文档中,计算模板的和Y轴,X=(右边界-左边界 - 前半部分的len值)/2.0F +
		// len , y 轴和之前的保持一致,底边界-20
		cb.addTemplate(total,
				(document.rightMargin() + document.right() + document.leftMargin() - document.left()) / 2.0F + 20F,
				document.bottom() - 20); // 调节模版显示的位置

	}

	/**
	 *
	 * TODO 关闭文档时,替换模板,完成整个页眉页脚组件
	 *
	 * @see com.itextpdf.text.pdf.PdfPageEventHelper#onCloseDocument(com.itextpdf.text.pdf.PdfWriter,
	 *      com.itextpdf.text.Document)
	 */
	public void onCloseDocument(PdfWriter writer, Document document) {
		// 7.最后一步了,就是关闭文档的时候,将模板替换成实际的 Y 值,至此,page x of y 制作完毕,完美兼容各种文档size。
		total.beginText();
		total.setFontAndSize(bf, presentFontSize);// 生成的模版的字体、颜色
		String foot2 = " " + (writer.getPageNumber() - 1) + " 页";
		total.showText(foot2);// 模版显示的内容
		total.endText();
		total.closePath();
	}
}

  

第三步:

如果仔细度过那个超入门的朋友会知道设置表头有一个固定表头的功能,比如表格很长的时候PDF自动分页了,原生代码可以做到每一页都显示表头。

实际上看了下iText的源码发现HTML转PDF的时候也是可以的,iText支持一个CSS属性,只需要给你需要重复表头表尾的table标签设置css属性“repeat-header:yes”或“repeat-footer:yes”即可,然后将你需要重复的表头放在thead标签内,表尾放在tfoot标签内。

例:

<table style="repeat-header:yes;repeat-footer:yes;">
        <thead>
            <tr>
                <th>如果表格过长自动分页了,我是重复的表头1</th>
            </tr>
            <tr>
                <th>如果表格过长自动分页了,我是重复的表头2</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>内容....</td>
            </tr>
            <!--  .....  -->
            <tr>
                <td>内容....</td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <th>如果表格过长自动分页了,我是重复的表尾1</th>
            </tr>
            <tr>
                <th>如果表格过长自动分页了,我是重复的表尾2</th>
            </tr>
        </tfoot>
    </table>

  

使用代码写pdf的时候,如果某个小章节完毕了,我们需要另起一页直接new Page()即可。在HTML生成pdf的时候也是有特殊的css属性来控制的,分别是page-break-after:alwayspage-break-before:always还有一个page-break-inside属性,但测试没发现有什么特殊的效果

<span style="page-break-after:always;">这段文字后面会重新分页</span>
<p>正常的文字流,但是因为前面元素强制在后面分页了,后面的文字也强制在前面分页了,因此这段文字会是顶头文字,也是这一页的唯一的文字。</p>
<span style="page-break-before:always;">这段文字前面会重新分页</span>

原文地址:https://www.cnblogs.com/huangheng01/p/10338946.html

时间: 2024-10-01 02:55:41

java itextpdf使用HTML模板生成pdf文件,并设置table的相关文章

itextsharp利用模板生成pdf文件笔记

iTextSharp是一款开源的PDF操作类库,使用它可以快速的创建PDF文件. 中文参考网站:http://hardrock.cnblogs.com/ http://pdfhome.hope.com.cn/Article.aspx?CID=bf51a5b6-78a5-4fa3-9310-16e04aee8c78&AID=f5fe52dd-8419-4baa-ab1c-ea3f26952132 英文参考网站:http://itext.ugent.be/library/ ·  技术文章(http:

【Java】itext根据模板生成pdf(包括图片和表格)

1.导入需要的jar包:itext-asian-5.2.0.jar itextpdf-5.5.11.jar. 2.新建word文档,创建模板,将文件另存为pdf,并用Adobe Acrobat DC打开编辑,点击右侧[准备表单]后点击[开始] 3.在需要插入数据的空白处,右击,点击[文本域],将文本域拖放到你想要的位置,更改域名称为你传入的变量名. 4.保存文件,将文件放到项目中.生成pdf代码如下: 1 public static void creatPdf(Map<String, Objec

Spring 中 AbstractExcelView 支持根据模板生成Excel文件. 通过设置 view 的 URL 属性指定模板的路径

 注意:1. 模板需放在 WEB-INF 目录下2. 指定模板路径时不需要添加扩展名, Spring将自动添加 .xls 到URL 属性中.3. 在指定URL前需先设置 view 的 ApplicationContext 1. 控制器配置 control-context.xml 1 <bean id="beanNameViewResolver" 2 class="org.springframework.web.servlet.view.BeanNameViewResol

java调用wkhtmltopdf生成pdf文件,美观,省事

最近项目需要导出企业风险报告,文件格式为pdf,于是搜了一大批文章都是什么Jasper Report,iText ,flying sauser ,都尝试了一遍,感觉不是我想要的效果, 需要自己调整好多东西,样式,字体等等,好麻烦,毕竟博主这么懒的人,哈哈.-------jstarseven 言归正传: java生成pdf文件,方式很多,以上提到的哪几种方式具体可以参考这篇文章<讲解很详细>:http://blog.csdn.net/ouyhong123/article/details/2640

Java Itext 生成PDF文件

利用Java Itext生成PDF文件并导出,实现效果如下: PDFUtil.java package com.jeeplus.modules.order.util; import java.io.OutputStream; import java.math.BigDecimal; import java.net.URL; import java.text.DecimalFormat; import java.text.SimpleDateFormat; import java.util.Arr

java根据模板生成word文件

原文:java根据模板生成word文件 源代码下载地址:http://www.zuidaima.com/share/1550463664884736.htm AVA生成word模板程序步骤 1. 将freemarker-2.3.13.jar复制到项目\WEB-INF\lib目录下 2. 编辑模板文件 (1) 将DOC文件另存为xml文件,将xml文件在eclipse环境下打开,右键选"源"→"格式".此处注意xml文件属性是UTF-8. (2) 将xml文件中需要替

JAVA生成PDF文件

生成PDF文件是主要应用的是ITEXT插件 1 import java.awt.Color; 2 import java.io.File; 3 import java.io.FileOutputStream; 4 import java.io.IOException; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import com.lowagie.text.Cell; 9 import com.lowagie.text.

Freemarker+IText生成pdf文件

最近项目中遇到要用html生成pdf文件的需求,一开始研究了下前端插件jspdf,使用h5 canvas绘图生成图片,再把图片生成pdf文件,遇到了各种各样的问题,生成的pdf文件达到20多M,height超过5000浏览器就崩溃,有兴趣的童鞋可以尝试一下,该方案LZ最终放弃了. 接着开始尝试服务端生成,使用freemaker模板生成静态html文件,通过iext生成pdf,网上很多关于renderer.setDocument(dom,null)的用法,LZ尝试后发现效率奇低,最后放弃了,直接使

结合模板导出PDF文件

@Action("report_exportJasperPdf")    public String exportJasperPdf() throws Exception{        //查询出满足当前条件 结果数据        List<WayBill> wayBills = wayBillService.findWayBills(model);        //下载导出        //设置头信息        ServletActionContext.get