PDF是一种我们在工作中一种常见的文件格式,在打印一些单据或者传输数据,需要使用到它。
工程目录如下:
com.itextpdf
itextpdf
5.4.2
com.itextpdf
itext-asian
5.2.0
在项目中使用了一个Document对象,该对象可以用来设置文件页面的相关属性。一个document表示一个文件,一个文件由多个table组成,一个table由多个cell组合,每个cell均可以指定内容,字体,大小,对齐方式,指定边界,add的顺序决定document 的table的显示顺序。
在设置格子前,需要指定一个页面的大小,页面的样式和实例,将后续的内容写入到指定的file里面。
Document document=new Document();
public CreateOrDeleteFile(File file) { // 设置页面大小
document.setPageSize(PageSize.A4);
document.setPageCount(3);
try {
PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
} catch (Exception e) {
e.printStackTrace();
}
}
如下表示一个table,由若干行cell组成,其中cell可以通过colspan属性表示所跨的单元格数目。如下为一个指定6列的table,单据编号占2格 ,申请人占2格,申请日期占2格:
|
|
|
|
|
|
单据编号 |
申请人 |
申请日期 |
|||
|
|
|
|
|
|
|
|
|
|
|
|
每个格子占几列,在代码中的写法为:
cell.setColspan(列数);
PdfPCell cell = new PdfPCell();
cell.setColspan(2);
指定一个table为6列:
PdfPTable table0 = createTable(6);
在pdf上的效果就是这样啦!
如果只添加一行,只包含内容和字体:
public boolean createPDFReport(){
document.open();
PdfPTable table0 = createTable(7);
table0.addCell(createCell("报账单",headfont));
// PdfPTable table1 = createTable(7);
// //addPicture(expenseReportPrintDto,QR_CODE_IMAGE_PATH,table,url);
// table1.addCell(createCell("单据编号:", textfont,Element.ALIGN_LEFT,7,false));
//
// PdfPTable table2 = createTable(7);
//
// table2.addCell(createCell("费用事项:", keyfont, Element.ALIGN_LEFT,7,true));
//
// PdfPTable table3 = createTable(4);
//
// table3.addCell(createCell("保单费用行:", keyfont, Element.ALIGN_LEFT,7,true));
try{
document.add(table0);
// document.add(table1);
// document.add(table2);
// document.add(table3);
}catch (DocumentException E){
throw new RuntimeException("PDF写入文件报错");
}
document.close();
return true;
}
会出现以下错误,原因是因document.close()这行代码出的问题:
java.io.IOException: The document has no pages.
at com.itextpdf.text.pdf.PdfPages.writePageTree(PdfPages.java:113) ~[itextpdf-5.4.2.jar:5.4.2]
at com.itextpdf.text.pdf.PdfWriter.close(PdfWriter.java:1243) ~[itextpdf-5.4.2.jar:5.4.2]
at com.itextpdf.text.pdf.PdfDocument.close(PdfDocument.java:849) ~[itextpdf-5.4.2.jar:5.4.2]
at com.itextpdf.text.Document.close(Document.java:416) ~[itextpdf-5.4.2.jar:5.4.2]
at com.example.cn.util.CreateOrDeleteFile.createPDFReport(CreateOrDeleteFile.java:145) ~[classes/:na]
at com.example.cn.service.PrintService.printpdf(PrintService.java:28) ~[classes/:na]
at com.example.cn.web.PrintController.makePdf(PrintController.java:21) ~[classes/:na]
如果去掉document.close()这行代码,则打开生成的pdf文件,会出现格式问题,打不开此pdf文件。
只要有一个table有设置格式和对齐方式,该pdf就可以打开:
public boolean createPDFReport(){
document.open();
PdfPTable table0 = createTable(7);
table0.addCell(createCell("报账单",headfont,Element.ALIGN_CENTER,7,false));
PdfPTable table1 = createTable(7);
//addPicture(expenseReportPrintDto,QR_CODE_IMAGE_PATH,table,url);
table1.addCell(createCell("单据编号:", textfont,Element.ALIGN_LEFT,7,false));
PdfPTable table2 = createTable(7);
table2.addCell(createCell("费用事项:", keyfont, Element.ALIGN_LEFT,7,true));
PdfPTable table3 = createTable(4);
table3.addCell(createCell("保单费用行:", keyfont, Element.ALIGN_LEFT,7,true));
try{
document.add(table0);
document.add(table1);
document.add(table2);
document.add(table3);
}catch (DocumentException E){
throw new RuntimeException("PDF写入文件报错");
}
document.close();
return true;
}
service类:
public void printpdf() throws Exception {
System.out.println("打印service");
String path="print\\picture.png";
String pdf="print\\报账单.pdf";
//第一个参数为二维码的描述
QRCodeGenerator.generateQRCodeImage("erweima", 50, 25, path);
System.out.println("生成二维码成功!!");
//打印pdf
File file=new File(pdf);
//1.创建文件
CreateOrDeleteFile.doCreateFile(file);
//创建一个
CreateOrDeleteFile createOrDeleteFile=new CreateOrDeleteFile(file);
createOrDeleteFile.createPDFReport();
System.out.println("生成pdf成功!");
}
效果如下:
public class PdfPCell extends Rectangle implements IAccessibleElement {
private ColumnText column;
private int verticalAlignment;
private float paddingLeft;
private float paddingRight;
private float paddingTop;
private float paddingBottom;
private float fixedHeight;
private float minimumHeight;
private boolean noWrap;
private PdfPTable table;
private int colspan;
private int rowspan;
private Image image;
private PdfPCellEvent cellEvent;
private boolean useDescender;
private boolean useBorderPadding;
protected Phrase phrase;
private int rotation;
protected PdfName role;
protected HashMap accessibleAttributes;
protected UUID id;
protected ArrayList headers;
}
package com.example.cn.util;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class CreateOrDeleteFile {
Document document=new Document();
// 设置字体大小
static Font headfont;
// 设置字体大小
static Font keyfont;
// 设置字体大小
static Font linefont;
// 设置字体大小
static Font textfont;
private static int maxWidth = 520;
static {
BaseFont bfChinese;
try {
bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.NOT_EMBEDDED);
// 标题字体大小
headfont = new Font(bfChinese, 20, Font.NORMAL);
// 关键标题字体大小
keyfont = new Font(bfChinese, 14, Font.NORMAL);
// 行标题字体大小
linefont = new Font(bfChinese, 12, Font.NORMAL);
// 字段字体大小
textfont = new Font(bfChinese, 10, Font.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
public CreateOrDeleteFile(File file) { // 设置页面大小,联系文件
document.setPageSize(PageSize.A4);
document.setPageCount(3);
try {
PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
} catch (Exception e) {
e.printStackTrace();
}
}
// 设置每个格子的属性
public static PdfPCell createCell(String value, Font font, int align){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setPhrase(new Phrase(value,font));
return cell;
}
public static PdfPCell createCell(String value, Font font){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,font));
return cell;
}
public static PdfPCell createCell(String value, Font font,boolean boderFlag){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setPhrase(new Phrase(value,font));
if(boderFlag){
cell.setBorderWidthLeft(0);
cell.setBorderWidthRight(0);
cell.setBorderWidthTop(0);
cell.setBorderWidthBottom(1);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}
return cell;
}
public static PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value,font));
cell.setPadding(3.0f);
if(boderFlag){
cell.setBorderWidthLeft(0);
cell.setBorderWidthRight(0);
cell.setBorderWidthTop(0);
cell.setBorderWidthBottom(1);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}else{
cell.setBorder(0);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}
return cell;
}
public static PdfPCell createCell(Image image, int align, int colspan){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setImage(image);
cell.setPadding(3.0f);
cell.setBorderWidthLeft(0);
cell.setBorderWidthRight(0);
cell.setBorderWidthTop(0);
cell.setBorderWidthBottom(1);
return cell;
}
// 创建一个几列的Table
public static PdfPTable createTable(int colNumber){
PdfPTable table = new PdfPTable(colNumber);
try{
table.setTotalWidth(maxWidth);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(1);
}catch(Exception e){
e.printStackTrace();
}
return table;
}
public boolean createPDFReport(){
document.open();
PdfPTable table0 = createTable(7);
table0.addCell(createCell("报账单",headfont,Element.ALIGN_CENTER,7,false));
PdfPTable table1 = createTable(7);
//addPicture(expenseReportPrintDto,QR_CODE_IMAGE_PATH,table,url);
table1.addCell(createCell("单据编号:", textfont,Element.ALIGN_LEFT,7,false));
PdfPTable table2 = createTable(7);
table2.addCell(createCell("费用事项:", keyfont, Element.ALIGN_LEFT,7,true));
PdfPTable table3 = createTable(4);
table3.addCell(createCell("保单费用行:", keyfont, Element.ALIGN_LEFT,7,true));
try{
document.add(table0);
document.add(table1);
document.add(table2);
document.add(table3);
}catch (DocumentException E){
throw new RuntimeException("PDF写入文件报错");
}
document.close();
return true;
}
public static void doCreateFile(File file) {
if (!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
//如果有自定义错误的话,可以使用BizException,比如创建文件出错!
}
}
}
}
1. 定义单据头:
document.open();
PdfPTable table = createTable(6); // 新建一个6列的表格(tale)。
public static PdfPTable createTable(int colNumber){
PdfPTable table = new PdfPTable(colNumber);
try{
table.setTotalWidth(maxWidth);
table.setLockedWidth(true);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(1);
}catch(Exception e){
e.printStackTrace();
}
return table;
}
2. 使用colspan 属性定义每个格子的宽度
table.addCell(createCell("单据编号:"+expenseReportPrintDto.getApplyNum(), textfont,Element.ALIGN_LEFT,2,false));
public static PdfPCell createCell(String value, Font font, int align, int colspan, boolean boderFlag){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setPhrase(new Phrase(value,font));
cell.setPadding(3.0f);
if(boderFlag){
cell.setBorderWidthLeft(0);
cell.setBorderWidthRight(0);
cell.setBorderWidthTop(0);
cell.setBorderWidthBottom(1);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}else{
cell.setBorder(0);
cell.setPaddingTop(15.0f);
cell.setPaddingBottom(8.0f);
}
return cell;
}
3. 同时可以添加picture, 文本,二维码在一行:
添加图像:
URL urls = new URL(url+"/tf-logo.png");
image = Image.getInstance(urls);
table.addCell(createCell(image,Element.ALIGN_CENTER,2));
然后使用工具类的代码:
public static PdfPCell createCell(Image image,int align,int colspan){
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setImage(image);
cell.setPadding(3.0f);
cell.setBorderWidthLeft(0);
cell.setBorderWidthRight(0);
cell.setBorderWidthTop(0);
cell.setBorderWidthBottom(1);
return cell;
}
最终实现的一个效果如下: