截止2021年7月,itext的最新版本是itext7,本文是基于itext5编写(itext的大版本号是4-5-7,没有6)
itext5已于2020年9月停止维护
相关依赖:
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
用itext生成pdf大体分为5个步骤:
os = response.getOutputStream(); // 1.建立Document对象的实例 Document doc = new Document(); // 2.建立一个书写器(Writer)与document对象关联,通过书写器可以将文件写到输出流中 PdfWriter.getInstance(doc, os); // 3.打开文档 doc.open(); // 4.向文档中添加内容,这部分之后会详细说明 doc.add(new Paragraph("Hello World")); // 5.关闭文档 doc.close();
重点在第4步打开文档之后往里面加东西的操作。
第2步生成了一个PdfWriter
存在了doc
里面,在第5步调用doc.close()
的时候调用这个PdfWriter
的close()
方法才关闭流,所以最好写成try-with-resource的形式保证流可以关闭。
itext的文本由文本块(Chunk)、短语(Phrase)、段落(Paragraph)构成。
文本块(Chunk)是处理文本的最小单位,有一串带格式(包括字体、颜色、大小)的字符串组成。
如下代码就是创建一个字体为HELVETICA、大小为10、带下划线的字符串。
Font font = FontFactory.getFont(FontFactory.HELVETICA, 10, Font.UNDERLINE); Chunk chunk = new Chunk("chunk underline", font);
短语(Phrase)由一个或多个文本块(Chunk)组成,短语(Phrase)也可以设定字体,但对于其中已设定过字体的文本块(Chunk)无效。通过短语(Phrase)函数add()
可以将一个文本块(Chunk)加到短语(Phrase)中。
如下代码就是创建一个包括"phrase"
和chunk
的短语,但是"phrase"
的字号是20,chunk
的字号是10。
Font font = FontFactory.getFont(FontFactory.HELVETICA, 20, Font.UNDERLINE); Phrase phrase = new Phrase("phrase", font); phrase.add(chunk);
段落(Paragraph)由一个或多个文本块(Chunk)或短语(Phrase)组成,相当于WORD中的段落,同样可以设定段落的字体大小、颜色等属性。另外也可以设定段落的首行缩进、对齐方式(左对齐、右对齐、居中对齐)。通过函数setAlignment可以设定段落的对齐方式,默认为左对齐。
Paragraph paragraph = new Paragraph("Hello World"); // 左对齐 paragraph.setAlignment(Element.ALIGN_LEFT); // 居中 paragraph.setAlignment(Element.ALIGN_CENTER); // 右对齐 paragraph.setAlignment(Element.ALIGN_RIGHT); // 首行缩进10个单位,不清楚这个单位是什么,但肯定不是字符 paragraph.setFirstLineIndent(10);
itext本身并不支持中文字体,如果把上面代码里的文字替换成中文将会输出空白文档(连换行都没有)。
使用中日韩文字需要引入亚洲字体包itext-asian
。
BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED); Font font = new Font(baseFont, 12, Font.NORMAL);
上面这段代码表示生成宋体12号字,UniGB-UCS2-H
表示水平编码,UniGB-UCS2-V
则是垂直编码。
itext-asian
仅支持宋体一种简体字体,可通过扩展的方式添加其他字体。
目前itext支持gif、jpeg、png、wmf等图片格式。获取Image的方法有2种,网络图片可以通过字节数组的方式,本地图片可以直接使用路径获取。都是调用静态函数Image.getInstance()
,利用Java多态的特性。
// 根据byte[]获取 byte[] b = bos.toByteArray(); Image image = Image.getInstance(b); // 根据文件路径获取 String path = "/user/image.jpeg"; Image image = Image.getInstance(path);
表格主要由table和cell两部分组成
// 表格有4列 PdfPTable table = new PdfPTable(4); // 设置表格的宽度 table.setTotalWidth(600); // 也可以每列分别设置宽度 table.setTotalWidth(new float[] { 160, 70, 130, 100 }); // 锁住宽度 table.setLockedWidth(true); // 设置表格上面空白宽度 table.setSpacingBefore(30f); // 设置表格下面空白宽度 table.setSpacingAfter(0f); // 设置表格默认为无边框 table.getDefaultCell().setBorder(0); doc.add(table);
byte[] bs = bos.toByteArray(); Image image = Image.getInstance(bs); PdfPCell cell = new PdfPCell(image, true); // 设置cell边框(无边框),或setBorder cell.setBorderWidth(Rectangle.NO_BORDER); // 设置cell高度 cell.setFixedHeight(100); // 水平居中 cell.setHorizontalAlignment(Element.ALIGN_CENTER); // 垂直居中 cell.setVerticalAlignment(Element.ALIGN_MIDDLE); table.addCell(cell);
在图片比较多的时候,也可使用下面的方法添加图片,这样可以省略一些重新设置格式的消耗,实测会比new一个cell稍微快一些。
PdfPCell cell = new PdfPCell(); cell.setFixedHeight(100); cell.setImage(image1); table.addCell(cell); cell.setImage(image2); table.addCell(cell);
上例cell中存放的是图片,图片高度会自适应。注意如果是文本,需要cell高度大于文字字体。比如cell高度是30,字体是14,则cell内可以写2行字,第一行放不下的字会自动到第二行。但如果字体是16,则只能放1行字,如果文本过长,长的那部分就不会显示。
PdfPCell cell = new PdfPCell(new Paragraph("Text cell")); // 设置背景颜色 cell.setBackgroundColor(BaseColor.ORANGE); // 设置边框颜色 cell.setBorderColor(BaseColor.GREEN); // 设置左边距 cell.setPaddingLeft(10); // 设置跨2行 cell.setRowspan(2); // 设置跨两列 cell.setColspan(2); table.addCell(cell);
// 创建一个条形码对象 Barcode128 barcode128 = new Barcode128(); barcode128.setCode("123456789"); barcode128.setCodeType(Barcode128.CODE128); // 生成条形码图片 Image image = barcode128.createImageWithBarcode(cb, null, null); // 以图片的方式放到表格 PdfPCell cell = new PdfPCell(image, true); cell.setHorizontalAlignment(Element.ALIGN_CENTER); cell.setVerticalAlignment(Element.ALIGN_MIDDLE); cell.setFixedHeight(30); table.addCell(cell);
最好给条形码设置一个合适的高度,否则黑条会过密。
这篇文章需要补充的部分
等有空就写......
2021年7月28日
itextpdf生成表格的常见用法
https://blog.csdn.net/u010142437/article/details/84303581
[itext]Java生成PDF文件
https://www.cnblogs.com/qlqwjy/p/8213989.html
itextpdf JAVA 输出PDF文档
https://www.cnblogs.com/icerainsoft/p/4900359.html