先简单介绍一下IText
iText是一种生成PDF报表的Java组件。通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超链接显示或下载得到生成的报表,这样就很好的解决了B/S系统的报表处理问题。
IText生成PDF报表的方式
-
用Itext自己布局加元素生成pdf //itext-PdfStamper pdfStamper(俗称抠模板)
-
读取pdf模板进行填充 //itext-Document document(正常代码撰写)
两种方式各有优缺, pdfStamper代码简单,但是模板要先提供,且字段长度固定、不灵活. document模板可根据代码调整,缺点是要维护的后台代码较多,接下来分别演示一下
-
首先引入maven坐标
<!-- itextpdf --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.13.1</version> </dependency> <!-- itext-asian --> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> <dependency>
2.演示通过模板填充数据,首先新建一个word文档,编辑好文档内容,留出需要填充的留白
然后转换成pdf,在Adobe Acrobat中编辑表单域,填充留白,类似于操作word文档的占位符
接下来完成一个简单的小demo,上面已经将坐标导入
@GetMapping("/pdfTemplate")
public void pdfTemplate(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException {
//为了显示方便,直接在浏览器预览
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline;");
PdfReader pdfReader = new PdfReader("D:\\WordFile\\demo.pdf");
PdfStamper ps = new PdfStamper(pdfReader, response.getOutputStream());
AcroFields fields = ps.getAcroFields();
//使用中文字体
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
fields.setSubstitutionFonts(fontList);
HashMap<String, String> map = new HashMap<>();
map.put("id","1254");
map.put("username","张学良");
map.put("gender","男");
map.put("address","沈阳");
map.put("birthday",TimeTool.dateToStr(new Date(),null));
map.put("idnumber","123456789");
for (String key : map.keySet()) {
fields.setField(key,map.get(key));
}
//必须要调用这个,否则文档不会生成的
ps.setFormFlattening(true);
ps.close();
}
3.启动项目,浏览器进行测试,效果如图
4.接下来演示通过代码直接生成pdf报表,不借助模板
由于要通过代码布局,所以我事先定义了全局的字体静态变量
// 定义全局的字体静态变量
private static Font titlefont;
private static Font headfont;
private static Font keyfont;
private static Font textfont;
// 最大宽度
private static int maxWidth = 520;
// 静态代码块
static {
try {
// 不同字体(这里定义为同一种字体:包含不同字号、不同style)
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
titlefont = new Font(bfChinese, 16, Font.BOLD);
headfont = new Font(bfChinese, 14, Font.BOLD);
keyfont = new Font(bfChinese, 10, Font.BOLD);
textfont = new Font(bfChinese, 10, Font.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
来一个简单的需求吧,将数据库的一张表的所有信息打印到pdf报表
直接贴代码吧
// 定义全局的字体静态变量
private static Font titlefont;
private static Font headfont;
private static Font keyfont;
private static Font textfont;
// 最大宽度
private static int maxWidth = 520;
// 静态代码块
static {
try {
// 不同字体(这里定义为同一种字体:包含不同字号、不同style)
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
titlefont = new Font(bfChinese, 16, Font.BOLD);
headfont = new Font(bfChinese, 14, Font.BOLD);
keyfont = new Font(bfChinese, 10, Font.BOLD);
textfont = new Font(bfChinese, 10, Font.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
@Autowired(required = false)
SysUserMapper sysUserMapper;
@GetMapping("/createPdf")
public void createPdf(HttpServletRequest request, HttpServletResponse response) throws IOException, DocumentException, IllegalAccessException {
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline;");
// 新建一个文档,默认是A4纸的大小,4个边框为36
Document document = new Document(PageSize.A4);
// 将文档输出,我们写到输出流里面
PdfWriter instance = PdfWriter.getInstance(document, response.getOutputStream());
// 打开文档
document.open();
// 段落
Paragraph paragraph = new Paragraph("用户登记表", titlefont);
paragraph.setAlignment(1); //设置文字居中 0靠左 1,居中 2,靠右
paragraph.setIndentationLeft(12); //设置左缩进
paragraph.setIndentationRight(12); //设置右缩进
paragraph.setFirstLineIndent(24); //设置首行缩进
paragraph.setLeading(20f); //行间距
paragraph.setSpacingBefore(5f); //设置段落上空白
paragraph.setSpacingAfter(10f); //设置段落下空白
// 写入数据
document.add(paragraph);
Paragraph elements = new Paragraph("打印时间:" + TimeTool.dateToStr(new Date(), null),textfont);
elements.setSpacingAfter(10f);
elements.setAlignment(2);
document.add(elements);
List<UserEntity> userEntities = sysUserMapper.selectList(null);
PdfPTable pdfTable = new PdfPTable(6);
//设置表格占PDF文档100%宽度
pdfTable.setWidthPercentage(100);
//水平方向表格控件对齐
pdfTable.setHorizontalAlignment(PdfPTable.ALIGN_CENTER);
//创建一个表格的表头单元格
PdfPCell pdfTableHeaderCell = new PdfPCell();
pdfTableHeaderCell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
UserEntity userEntity1 = new UserEntity();
for (Field field : userEntity1.getClass().getDeclaredFields()) {
pdfTableHeaderCell.setPhrase(new Paragraph(field.getName(),textfont));
pdfTable.addCell(pdfTableHeaderCell);
pdfTableHeaderCell.setMinimumHeight(30);
}
//创建一个表格的正文内容单元格
PdfPCell pdfTableContentCell = new PdfPCell();
//设置水平对齐方式
pdfTableContentCell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
//设置垂直居中
pdfTableContentCell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
//表格内容行数的填充
for (UserEntity userEntity : userEntities) {
Class<? extends UserEntity> aClass = userEntity.getClass();
Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
pdfTableContentCell.setPhrase(new Paragraph((String) field.get(userEntity), textfont));
pdfTable.addCell(pdfTableContentCell);
}
}
document.add(pdfTable);
// 关闭文档
document.close();
}
生成效果如图
先到这吧...