最近要做一个自动生成pdf文档的功能,搜索了下发现使用iText7很方便,记录一下使用的过程。
不花里胡哨,直接贴代码
相关jar包引入
测试demo代码如下
import java.util.Calendar;
import java.util.Stack;
import org.junit.Assert;
import org.junit.Test;
import com.itextpdf.io.font.FontConstants;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.io.util.DateTimeUtil;
import com.itextpdf.kernel.color.Color;
import com.itextpdf.kernel.color.DeviceCmyk;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.AffineTransform;
import com.itextpdf.kernel.geom.Matrix;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDate;
import com.itextpdf.kernel.pdf.PdfDictionary;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfName;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfStream;
import com.itextpdf.kernel.pdf.PdfString;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
import com.itextpdf.kernel.pdf.annot.PdfTextAnnotation;
import com.itextpdf.kernel.pdf.canvas.CanvasTag;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.canvas.PdfCanvasConstants;
import com.itextpdf.kernel.pdf.canvas.parser.data.TextRenderInfo;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.border.Border;
import com.itextpdf.layout.border.SolidBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.List;
import com.itextpdf.layout.element.ListItem;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.UnitValue;
/**
* IText测试
*
* @date 2019年8月7日 上午11:29:03
*/
public class ItextTest {
public static final String destFolder = System.getProperty("user.dir")+"/target/";
@Test
public void testCreatePdf() throws Exception {
String fileName = "test01.pdf";
PdfWriter write = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(write);
// Document doc = new Document(pdfDoc);
pdfDoc.getDocumentInfo().setAuthor("dayouf").setCreator("ly").setTitle("TestPdfDoc");
PdfPage page = pdfDoc.addNewPage();
// PdfCanvas canvas = new PdfCanvas(page);
page.flush();
pdfDoc.close();
PdfReader reader = new PdfReader(destFolder+fileName);
PdfDocument pdfDocument = new PdfDocument(reader);
Assert.assertEquals("Rebuilt", false, reader.hasRebuiltXref());
Assert.assertNotNull(pdfDocument.getPage(1));
String date = pdfDocument.getDocumentInfo().getPdfObject().getAsString(PdfName.CreationDate).getValue();
Calendar cl = PdfDate.decode(date);
double diff = DateTimeUtil.getUtcMillisFromEpoch(null) - DateTimeUtil.getUtcMillisFromEpoch(cl);
String message = "Unexpected creation date. Different from now is " + (float)diff/1000 + "s";
Assert.assertTrue(message, diff<5000);
pdfDocument.close();
}
@Test
public void useObjectForMultipleTime1() throws Exception {
String fileName = "useObjectForMultipleTimes1.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(writer);
PdfDictionary helloWorld = new PdfDictionary().makeIndirect(pdfDoc);
helloWorld.put(new PdfName("Hello"), new PdfString("World"));
PdfPage page = pdfDoc.addNewPage();
page.getPdfObject().put(new PdfName("HelloWorld"), helloWorld);
page.flush();
pdfDoc.getCatalog().getPdfObject().put(new PdfName("HelloWorld"), helloWorld);
pdfDoc.close();
validateUseObjectForMultipleTimesTest(destFolder+fileName);
}
private void validateUseObjectForMultipleTimesTest(String fileName) throws Exception{
PdfReader reader = new PdfReader(fileName);
PdfDocument pdfDoc = new PdfDocument(reader);
Assert.assertEquals("Rebuilt", false,reader.hasFixedXref());
PdfDictionary page = pdfDoc.getPage(1).getPdfObject();
Assert.assertNotNull(page);
PdfDictionary helloWorld = page.getAsDictionary(new PdfName("HelloWorld"));
Assert.assertNotNull(helloWorld);
PdfString world = helloWorld.getAsString(new PdfName("Hello"));
Assert.assertEquals("World", world.toString());
helloWorld = pdfDoc.getCatalog().getPdfObject().getAsDictionary(new PdfName("HelloWorld"));
Assert.assertNotNull(helloWorld);
world = helloWorld.getAsString(new PdfName("Hello"));
Assert.assertEquals("World", world.toString());
pdfDoc.close();
}
// public void boundingBoxForRotatedText() throws Exception{
// TextRenderInfo tri = initTRI("abc",Math.PI/2);
// CharacterRenderInfo charactRenderInfo = new CharacterRenderInfo(tri);
// }
//
// private static TextRenderInfo initTRI(String text,double angle) throws Exception {
// CanvasGraphicsState gs = new CanvasGraphicsState();
// gs.setFont(PdfFontFactory.createFont());
// gs.setFontSize(12);
// float[] matrix = new float[6];
// AffineTransform tansform = AffineTransform.getRotateInstance(angle);
// tansform.getMatrix(matrix);
// return new TextRenderInfo(new PdfString(text),gs,
// new Matrix(matrix[0],matrix[1],matrix[2],matrix[3],matrix[4],matrix[5]),new Stack<CanvasTag>());
// }
@Test
public void actionTest() throws Exception {
String fileName = "actionTest01.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument doc = createDocument(writer,true);
doc.getCatalog().setOpenAction(PdfAction.createURI("https://www.baidu.com/"));
doc.close();
System.out.println("Please open document "+destFolder+fileName+" and make sure that you're automatically redirected to https://www.baidu.com/ site.");
}
@Test
public void actionTest2() throws Exception{
String fileName = "actionTest02.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument doc = createDocument(writer,false);
doc.getPage(2).setAdditionalAction(PdfName.O, PdfAction.createURI("https://www.baidu.com/"));
doc.close();
System.out.println("Please open document "+destFolder+fileName+" and make sure that you're automatically redirected to https://www.baidu.com/ site.");
}
private PdfDocument createDocument(PdfWriter write,boolean flushPages) {
PdfDocument document = new PdfDocument(write);
PdfPage p1 = document.addNewPage();
PdfStream str1 = p1.getFirstContentStream();
str1.getOutputStream().writeString("1 0 0 rg 100 600 100 100 re f\n");
if(flushPages) {
p1.flush();
}
PdfPage p2 = document.addNewPage();
PdfStream str2 = p2.getFirstContentStream();
str2.getOutputStream().writeString("0 1 0 rg 100 600 100 100 re f\n");
if(flushPages) {
p2.flush();
}
PdfPage p3 = document.addNewPage();
PdfStream str3 = p3.getFirstContentStream();
str3.getOutputStream().writeString("0 0 1 rg 100 600 100 100 re f\n");
if(flushPages) {
p3.flush();
}
return document;
}
@Test
public void createPdfTest() throws Exception{
String fileName = "pdfHelloList.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc);
PdfFont font = PdfFontFactory.createFont(FontConstants.TIMES_ROMAN);
doc.add(new Paragraph("iText is:")).setFont(font);
List list = new List().setSymbolIndent(12).setListSymbol("\u2022").setFont(font);
list.add(new ListItem("Never gonna give you up"))
.add(new ListItem("Never gonna let you up"))
.add(new ListItem("Never gonna run around and desert you"))
.add(new ListItem("Never gonna make you cry"))
.add(new ListItem("Never gonna say goodbye"))
.add(new ListItem("Never gonna tell a lie and hurt you"));
doc.add(list);
doc.close();
}
@Test
public void createPdfImageTest() throws Exception{
String fileName = "pdfHelloImage.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(writer);
Document doc = new Document(pdfDoc);
Image fox = new Image(ImageDataFactory.create("src/main/resources/image/fox.jpg"));
Image dog = new Image(ImageDataFactory.create("src/main/resources/image/dog.jpg"));
Paragraph p = new Paragraph("The quick brown ").add(fox)
.add(" jumps over the lazy ").add(dog);
doc.add(p);
doc.close();
}
@Test
public void createPdfCanvasTest() throws Exception{
String fileName = "pdfHelloCanvas1.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(writer);
PageSize ps = PageSize.A4.rotate();
PdfPage page = pdfDoc.addNewPage(ps);
PdfCanvas canvas = new PdfCanvas(page);
canvas.concatMatrix(1, 0, 0, 1, ps.getWidth()/2, ps.getHeight()/2);
canvas.moveTo(-(ps.getWidth()/2-15), 0)
.lineTo(ps.getWidth()/2-15, 0)
.stroke();
canvas.setLineJoinStyle(PdfCanvasConstants.LineJoinStyle.ROUND)
.moveTo(ps.getWidth()/2-25, -10)
.lineTo(ps.getWidth()/2-15, 0)
.lineTo(ps.getWidth()/2-25, 10)
.stroke()
.setLineJoinStyle(PdfCanvasConstants.LineJoinStyle.MITER);
canvas.moveTo(0, -(ps.getHeight()/2-15))
.lineTo(0, ps.getHeight()/2-15)
.stroke();
canvas.saveState()
.setLineJoinStyle(PdfCanvasConstants.LineJoinStyle.ROUND)
.moveTo(-10, ps.getHeight()/2 -25)
.lineTo(0, ps.getHeight()/2-15)
.lineTo(10, ps.getHeight()/2-25)
.restoreState();
for(int i = -((int)ps.getWidth()/2-61); i < ((int)ps.getWidth()/2 -60); i += 40) {
canvas.moveTo(i, 5).lineTo(i, -5);
}
for(int j = -((int)ps.getHeight()/2-57); j < ((int)ps.getHeight()/2-56); j += 40) {
canvas.moveTo(-5, j).lineTo(5, j);
}
canvas.stroke();
Color grayColor = new DeviceCmyk(0.f,0.f,0.f,0.875f);
Color greenColor = new DeviceCmyk(1.f,0.f,1.f,0.176f);
Color blueColor = new DeviceCmyk(1.f,0.156f,0.f,0.118f);
canvas.setLineWidth(0.5f).setStrokeColor(blueColor);
for(int i = -((int)ps.getHeight()/2-57);i < ((int)ps.getHeight()/2-56) ; i +=40) {
canvas.moveTo(-(ps.getWidth()/2-15), i)
.lineTo(ps.getWidth()/2-15, i);
}
for(int j = -((int)ps.getWidth()/2-61); j < ((int)ps.getWidth()/2-60); j += 40) {
canvas.moveTo(j, -(ps.getHeight()/2-15))
.lineTo(j, ps.getHeight()/2-15);
}
canvas.stroke();
canvas.setLineWidth(3).setStrokeColor(grayColor);
canvas.setLineWidth(2).setStrokeColor(greenColor)
.setLineDash(10, 10, 8)
.moveTo(-((int)ps.getWidth()/2-15), -((int)ps.getHeight()/2-15))
.curveTo(0, -(ps.getHeight()/2-15),0,0)
.stroke();
pdfDoc.close();
}
@Test
public void cratePdfTextAnnotationTest() throws Exception{
String fileName = "pdfHelloAnnotaion1.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(writer);
pdfDoc.addNewPage();
PdfAnnotation ann = new PdfTextAnnotation(new Rectangle(20,800,0,0))
.setColor(Color.GREEN)
.setTitle(new PdfString("iText"))
.setContents("With iText, you can truly take your documentation needs to the next level.")
.setOpen(true);
pdfDoc.getFirstPage().addAnnotation(ann);
Document doc = new Document(pdfDoc);
doc.add(new Paragraph("The example of text annotation.")).setFont(PdfFontFactory.createFont(FontConstants.TIMES_ROMAN));
doc.close();
}
/**
* 中文文档
* @throws Exception
* @date 2019年8月14日 下午3:42:13
*/
@Test
public void createPdfDemo() throws Exception {
String fileName = "pdfDemo.pdf";
PdfWriter writer = new PdfWriter(destFolder+fileName);
PdfDocument pdfDoc = new PdfDocument(writer);
PageSize ps = PageSize.A4;
Document doc = new Document(pdfDoc,ps);
PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);
PdfFont fontEn = PdfFontFactory.createFont(FontConstants.HELVETICA);
doc.add(new Paragraph("版本号:").setFont(font).setFontSize(9).add(new Text("SHHS-OTC-201901").setFont(fontEn).setFontSize(9)).setTextAlignment(TextAlignment.RIGHT));
PdfPage page = pdfDoc.getFirstPage();
PdfCanvas canvas = new PdfCanvas(page);
canvas.moveTo(doc.getLeftMargin(), ps.getHeight()-60).lineTo(ps.getWidth()-doc.getRightMargin(), ps.getHeight()-60).setFillColor(Color.BLACK).stroke();
Table table0 = new Table(UnitValue.createPercentArray(new float[]{1})).useAllAvailableWidth();
table0.addCell(new Cell().add(new Paragraph("上海xxxx有限公司").setFont(font).setFontSize(11).setBold().setTextAlignment(TextAlignment.CENTER)).setBorder(new SolidBorder(Color.WHITE,0)));
table0.addCell(new Cell().add(new Paragraph("交易确认书").setFont(font).setFontSize(11).setBold().setTextAlignment(TextAlignment.CENTER)).setBorder(new SolidBorder(Color.WHITE,0)));
table0.addCell(new Cell().add(new Paragraph("合同编号:").setFont(font).setFontSize(11).add(new Text("OTCO181204-190416-002S").setFont(fontEn)).setTextAlignment(TextAlignment.RIGHT)).setBorder(new SolidBorder(Color.WHITE,0)));
table0.addCell(new Cell().add(new Paragraph("交易时间:2019 年 4 月 16 日").setFont(font).setFontSize(11).setTextAlignment(TextAlignment.RIGHT)).setBorder(new SolidBorder(Color.WHITE,0)));
table0.addCell(new Cell().add(new Paragraph("甲方(买方):上海xxxx有限公司").setFont(font).setFontSize(11).setBold().setTextAlignment(TextAlignment.LEFT)).setBorder(new SolidBorder(Color.WHITE,0)));
table0.addCell(new Cell().add(new Paragraph("乙方(卖方):深圳xxxx资产管理有限公司").setFont(font).setFontSize(11).setBold().setTextAlignment(TextAlignment.LEFT)).setBorder(new SolidBorder(Color.WHITE,0)));
table0.setBorder(new SolidBorder(Color.WHITE,0));
doc.add(table0);
doc.add(new Paragraph("甲方和乙方以下单独称“交易一方”,合称“交易双方”。交易双方已经签署了《中国证券期货市场场外衍生品交易主协议(2014 年版)》(以下称“主协议”)及补充协议,本确认书构成主协议下的一项“交易有效约定”,主协议和补充协议中的全部条款适用于本确认书,除非本确认书中另有约定。")
.setFont(font).setFontSize(11).setTextAlignment(TextAlignment.LEFT).setFirstLineIndent(20));
doc.add(new Paragraph("本确认书适用《中国证券期货市场场外衍生品交易商品类衍生品定义文件(2014 年版)》及其修改或补充(以下称“商品定义文件”),若本确认书与商品定义文件中的约定不一致,本确认书的相关约定具有优先法律效力。")
.setFont(font).setFontSize(11).setTextAlignment(TextAlignment.LEFT).setFirstLineIndent(20));
doc.add(new Paragraph("交易双方同意,交易双方通过电话/邮件交易方式确认交易达成时交易已生效,本确认书是对交易双方通过交易电话/邮件达成的场外衍生品交易(以下简称“交易”)所进行的书面记载,对交易双方具有法律约束力。")
.setFont(font).setFontSize(11).setTextAlignment(TextAlignment.LEFT).setFirstLineIndent(20));
Table table = new Table(UnitValue.createPercentArray(new float[]{1,1,1,1}));
table.setWidthPercent(100);
table.addHeaderCell(new Cell(1,4).add(new Paragraph("期权合约交易基本信息").setFont(font).setFontSize(11).setTextAlignment(TextAlignment.CENTER)));
table.addCell(new Cell().add(new Paragraph("期权合约类型").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("看涨").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("期权行权类型").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("欧式").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("期权生效日").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("2019年4月16日").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("期权到期日").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("2019年5月15日").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("期权标的").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("大连商品交易所Y1909").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("标的参考价").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("5546元/吨").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("期权行权价").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("5546元/吨").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("标的数量").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("1000吨").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("权利金单价").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("77.64元/吨").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("权利金总额").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("77640元").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("结算货币及方式").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("现金结算").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("结算机构").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("上海xxxx有限公司").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("结算价格确认方式").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("到期日收盘价/点价").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("初始保证金(乙方支付)").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("160502元").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("结算金额计算方式").setFont(font).setFontSize(11)));
table.addCell(new Cell(1,3).add(new Paragraph("若结算价格=<行权价,结算金额=0,若结算价格>行权价,结算金额=(结算价格-行权价)*标的数量").setFont(font).setFontSize(11)));
table.addCell(new Cell().add(new Paragraph("其他约定").setFont(font).setFontSize(11)));
table.addCell(new Cell(1,3).add(new Paragraph("经交易双方协商一致,可提前终止本交易,提前终止的期权费由双方协商一致决定。").setFont(font).setFontSize(11)));
doc.add(table);
doc.add(new Paragraph("本交易确认书在未约定的事项,交易双方可以以本确认书之外补充协议的形式予以约定。本交易确认书传真件或扫描件与正本具有同等法律效力。")
.setFont(font).setFontSize(11).setTextAlignment(TextAlignment.LEFT).setFirstLineIndent(20));
Table table2 = new Table(UnitValue.createPercentArray(new float[]{1,1})).useAllAvailableWidth();
table2.addCell(new Cell(1,1).add("甲方:").setFont(font).setFontSize(11).setBorder(new SolidBorder(Color.WHITE,0)).setHeight(40));
table2.addCell(new Cell(1,1).add("乙方:").setFont(font).setFontSize(11).setBorder(new SolidBorder(Color.WHITE,0)).setHeight(40));
table2.addCell(new Cell(1,1).add("签章:").setFont(font).setFontSize(11).setBorder(new SolidBorder(Color.WHITE,0)).setHeight(40));
table2.addCell(new Cell(1,1).add("签章:").setFont(font).setFontSize(11).setBorder(new SolidBorder(Color.WHITE,0)).setHeight(40));
table2.addCell(new Cell(1,1).add("被授权人/法人代表签字:").setFont(font).setFontSize(11).setBorder(new SolidBorder(Color.WHITE,0)));
table2.addCell(new Cell(1,1).add("被授权人/法人代表签字:").setFont(font).setFontSize(11).setBorder(new SolidBorder(Color.WHITE,0)));
table2.setBorder(new SolidBorder(Color.WHITE,0));
doc.add(table2);
doc.close();
}
}
生成文档效果
参考资料
https://github.com/iTextCN/itext7-in-mandarin/tree/master/guide/chapter1