在企业的信息系统中,报表处理一直占比较重要的作用,iText是一种生成PDF报表的Java组件。通过在服务器端使用Jsp或JavaBean生成PDF报表,客户端采用超链接显示或下载得到生成的报表,这样就很好的解决了B/S系统的报表处理问题。
iText简介
iText是著名的开放源码的站点sourceforge一个项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。 iText的安装非常方便,下载iText.jar文件后,只需要在系统的CLASSPATH中加入iText.jar的路径,在程序中就可以使用iText类库了。
一、关于Itext的安装
IText的安装非常方便,在http://itextpdf.com/ 网站上下载iText.jar文件后,只需要在系统的CLASSPATH中加入iText.jar的路径,在程序中就可以使用iText类库了。本次示例所使用的jar包有三个。
下载地址:https://pan.baidu.com/s/1VO4J74BK5m7eRLf73KN-4Q
二、项目搭建。
本示例使用SSM架构,具体项目搭建流程请访问博客查看:https://blog.csdn.net/Soulmate_Min
三、构建代码
首先,将下载好的jar包导入项目,将jar包Build Path。
1.写测试类:本示例创建class名为GetReportController
2.添加两张图片,一张为LOGO,一张为水印图片。作为备用。
3.测试类代码展示:
代码如下:
package com.gcx.test.controller;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.gcx.test.util.NewCreditReportUtil;
@Controller
@RequestMapping("/CreditReporterController")
public class GetReportController {
@RequestMapping("/getreport")
@ResponseBody
public String getreport(String corpname,HttpServletRequest request) throws Exception{
//报告准备工作
//生成的PDF报告编号
String reportNo = "GCX-2"+System.currentTimeMillis();
//PDF文件名称
String pdfFileName = reportNo + ".pdf";
//水印图片地址
String watermarkFilePath = request.getSession().getServletContext().getRealPath("/images/watermark.png");
//公司LOGO地址
String reportLogoFilePath = request.getSession().getServletContext().getRealPath("/images/credit_report_logo.png");
//定义一个Map,将生成的PDF需要的参数填入Map, Map将作为参数传到PDF模板中。
Map<String, Object> NewCorpReportMap=new HashMap<>();
NewCorpReportMap.put("reportLogoFilePath", reportLogoFilePath);
NewCorpReportMap.put("reportNo", reportNo);
NewCorpReportMap.put("watermarkFilePath", watermarkFilePath);
NewCorpReportMap.put("corpname", corpname);
//调取PDF工具类中的方法,将Map参数传入。
NewCreditReportUtil.generateDeepthCreditReport(NewCorpReportMap);
String s1 = "C://Users//sungm//Desktop//Test" + pdfFileName;
//给文件加水印
NewCreditReportUtil.addPdfMark("C:/Users/sungm/Desktop/Test/GCX-creditreport-template.pdf", s1, NewCorpReportMap.get("watermarkFilePath").toString());
return reportNo;
}
}
4.生成PDF所需工具类展示:
/**
* 用iText生成PDF文档需要5个步骤:
*
* ①建立com.lowagie.text.Document对象的实例。
* Document document = new Document();
*
* ②建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
* PDFWriter.getInstance(document, new FileOutputStream("Helloworld.PDF"));
*
* ③打开文档。
* document.open();
*
* ④向文档中添加内容。
* document.add(new Paragraph("Hello World"));
*
* ⑤关闭文档。
* document.close();
*
*/
添加水印方法:
paragraph格式:
居中无边框的cell:
不居中无边框的cell:
居中有边框的cell:
居中有边框的cell:
对doc文件添加页眉页脚方法:
设置字体:
插入图片:
首页--固定格式布局:本示例固定的格式,具体样式可以根据需求自己修改
非空判断:
完整工具类代码(包含以上所有示例):
package com.gcx.test.util;
import java.awt.Color;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.Font;
import com.lowagie.text.HeaderFooter;
import com.lowagie.text.Image;
import com.lowagie.text.Paragraph;
import com.lowagie.text.Phrase;
import com.lowagie.text.Rectangle;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfReader;
import com.lowagie.text.pdf.PdfStamper;
import com.lowagie.text.pdf.PdfWriter;
/**
* 用iText生成PDF文档需要5个步骤:
*
* ①建立com.lowagie.text.Document对象的实例。
* Document document = new Document();
*
* ②建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
* PDFWriter.getInstance(document, new FileOutputStream("Helloworld.PDF"));
*
* ③打开文档。
* document.open();
*
* ④向文档中添加内容。
* document.add(new Paragraph("Hello World"));
*
* ⑤关闭文档。
* document.close();
*
*/
public class NewCreditReportUtil {
//定义静态变量,用于生成水印文件名称
private final static String RESULT_FILE = "C:/Users/sungm/Desktop/Test/GCX-creditreport-template.pdf";
public static boolean generateDeepthCreditReport(Map<String, Object> NewCorpReportMap)
throws MalformedURLException, IOException, DocumentException {
//①建立com.lowagie.text.Document对象的实例。
Document doc = new Document();
doc.setMargins(20, 20, 30, 30);
String fontPath = "C:/Users/sungm/Desktop/Test";
//②建立一个书写器(Writer)与document对象关联,通过书写器(Writer)可以将文档写入到磁盘中。
PdfWriter.getInstance(doc, new FileOutputStream(RESULT_FILE));
// 设置中文字体
BaseFont fontChinese = BaseFont.createFont(fontPath + "/simfang.ttf", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
Font chinese = new Font(fontChinese, 10, Font.NORMAL);
// 添加页眉页脚
String headertitle = "*****报告" + " " + "*******";
addheaderandfooter(doc, chinese, headertitle);
//③打开文档。
doc.open();
// 18.0F是字体大小,0表示字体倾斜度, font.setStyle(1); 0:无变化1:加粗;2:斜体...
// font.setFamily("微软雅黑"); // 设置字体
Font myfont = setfont(fontPath + "/msyh.ttf", 13.0F, 0, Color.BLACK, 0);// 基本字体
//Font myfont1 = setfont(fontPath + "/msyh.ttf", 36.0F, 0, Color.BLACK, 1);// 标头字体(一级字体)
//Font myfont2 = setfont(fontPath + "/msyh.ttf", 27.0F, 0, Color.BLACK, 1);// 标头字体(二级字体)
Font myfont3 = setfont(fontPath + "/msyh.ttf", 18.0F, 0, Color.BLACK, 1);// 标头字体(三级字体)
//Font myfont4 = setfont(fontPath + "/msyh.ttf", 13.0F, 0, Color.BLACK, 1);// 标头字体(四级字体)
//Font myfont5 = setfont(fontPath + "/msyh.ttf", 12.0F, 0, Color.BLACK, 0);// 标头字体(五级字体)
// 初始化pdf基本功能性文本
Image image = null;
PdfPTable table;
PdfPCell cell = null;
Paragraph paragraph = null;
// 准备工作结束,进行文档内容填充:
// 添加公司logo图片
table = new PdfPTable(1);
String picpath = NewCorpReportMap.get("reportLogoFilePath").toString();
addpicture(table, image, picpath, cell, doc);
// 添加报告信息
firstpage(cell, table, paragraph, NewCorpReportMap.get("corpname").toString(), "企业信用报告",
NewCorpReportMap.get("reportNo").toString(), myfont, myfont3, doc);
// 第二页 (固定死页面)
doc.newPage();
doc.add(new Paragraph(" ", myfont));
paragraph = new Paragraph("报告说明", myfont3);
paragraph.setAlignment(1);
doc.add(paragraph);
doc.add(new Paragraph(" ", myfont));
geshi1(new Paragraph("1. 内容1",myfont), doc);
geshi1(new Paragraph("2. 内容2", myfont), doc);
geshi1(new Paragraph("3. 内容3", myfont), doc);
geshi1(new Paragraph("4. 内容4", myfont), doc);
// 第三页 报告摘要,每页空2行留给页眉
doc.newPage();
doc.add(new Paragraph(" ", myfont));
doc.add(new Paragraph(" ", myfont));
doc.close();
return false;
}
/**
* 给pdf文件添加水印
*
* @param InPdfFile
* 要加水印的原pdf文件路径
* @param outPdfFile
* 加了水印后要输出的路径
* @param object
* 水印图片路径
* @param pageSize
* 原pdf文件的总页数(该方法是我当初将数据导入excel中然后再转换成pdf所以我这里的值是用excel的行数计算出来的,
* 如果不是我这种可以 直接用reader.getNumberOfPages()获取pdf的总页数)
* @throws Exception
*/
public static void addPdfMark(String InPdfFile, String outPdfFile, String readpicturepath) throws Exception {
PdfReader reader = new PdfReader(InPdfFile);
int pageSize = reader.getNumberOfPages();
PdfStamper stamp = new PdfStamper(reader, new FileOutputStream(outPdfFile));
Image img = Image.getInstance(readpicturepath);// 插入水印
img.setAbsolutePosition(0, 0);
for (int i = 1; i <= pageSize; i++) {
PdfContentByte under = stamp.getUnderContent(i);
under.addImage(img);
}
stamp.close();// 关闭
File tempfile = new File(InPdfFile);
if (tempfile.exists()) {
tempfile.delete();
}
}
// paragraph的格式
public static void geshi1(Paragraph paragraph, Document doc) throws DocumentException {// 段落的格式
paragraph.setIndentationLeft(30);
paragraph.setIndentationRight(30);
paragraph.setFirstLineIndent(20f);
paragraph.setSpacingAfter(10f);
paragraph.setSpacingBefore(10f);
doc.add(paragraph);
}
// 居中无边框的cell
public static void geshi2(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
cell.setBorder(PdfPCell.NO_BORDER);
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
table.addCell(cell);
}
// 不居中无边框的cell
public static void geshi12(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
cell.setBorder(PdfPCell.NO_BORDER);
table.addCell(cell);
}
// 居中有边框的cell
public static void geshi22(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
cell.setHorizontalAlignment(PdfPCell.ALIGN_CENTER);
cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
cell.setVerticalAlignment(PdfPCell.ALIGN_CENTER);
table.addCell(cell);
}
// 居中有边框的cell
public static void geshi32(PdfPCell cell, PdfPTable table) throws DocumentException {// 表格的格式
cell.setColspan(3);
cell.setBorder(0);
table.addCell(cell);
}
// 对doc文件添加页眉页脚方法
public static void addheaderandfooter(Document doc, Font chinese, String headertitle) {
// 设置页眉页脚方法
/**
* HeaderFooter的第2个参数为非false时代表打印页码 页眉页脚中也可以加入图片,并非只能是文字
*/
HeaderFooter header = new HeaderFooter(new Phrase(headertitle, chinese), false);
header.setBorder(Rectangle.NO_BORDER);
header.setBorder(Rectangle.BOTTOM);
header.setAlignment(1);
header.setBorderColor(Color.red);
doc.setHeader(header);
HeaderFooter footer = new HeaderFooter(new Phrase("第-", chinese), new Phrase("-页", chinese));
/**
* 0是靠左 1是居中 2是居右
*/
footer.setAlignment(1);
footer.setBorderColor(Color.red);
footer.setBorder(Rectangle.NO_BORDER);
doc.setFooter(footer);
/**
* 页眉页脚的设置一定要在open前设置好
*/
}
// 设置字体
public static Font setfont(String fonttype, float fontsize, int fontflag, Color fontcolor, int fontstyle)
throws DocumentException, IOException {
BaseFont baseFont5 = BaseFont.createFont(fonttype, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Font font = new Font(baseFont5, fontsize, fontflag);
font.setColor(fontcolor);
if (fontstyle != 0) {// 如果传参为0不设置字体
font.setStyle(fontstyle);
}
return font;
}
// 插入图片
public static void addpicture(PdfPTable table, Image image, String picpath, PdfPCell cell, Document doc)
throws MalformedURLException, IOException, DocumentException {
image = Image.getInstance(picpath);
cell = new PdfPCell(image);
geshi2(cell, table);
doc.add(table);
}
// 首页--固定格式布局
public static void firstpage(PdfPCell cell, PdfPTable table, Paragraph paragraph, String corpname,
String reporttype, String reportNo, Font myfont, Font myfont3, Document doc) throws DocumentException {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");
String newyear = sdf.format(new Date());
paragraph = new Paragraph(corpname + newyear, myfont3);// 公司名
paragraph.setAlignment(1);
doc.add(paragraph);
paragraph = new Paragraph("企业信用报告", myfont3);// 信用报告类型
paragraph.setAlignment(1);
doc.add(paragraph);
doc.add(new Paragraph(" ", myfont));
doc.add(new Paragraph(" ", myfont));
doc.add(new Paragraph(" ", myfont));
doc.add(new Paragraph(" ", myfont));
doc.add(new Paragraph(" ", myfont));
doc.add(new Paragraph(" ", myfont));
table = new PdfPTable(2);
cell = new PdfPCell(new Phrase("报告编号:" + reportNo, myfont));
cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
table.addCell(cell);
cell = new PdfPCell(new Phrase("报告生成时间:" + sdf.format(new Date()), myfont));
cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
table.addCell(cell);
cell = new PdfPCell(new Phrase("报告生成机构:*****有限公司", myfont));
cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
table.addCell(cell);
cell = new PdfPCell(new Phrase("报告结论机构:******研究院", myfont));
cell.setBorder(PdfPCell.NO_BORDER);// Rectangle.NO_BORDER
table.addCell(cell);
doc.add(table);
}
//非空判断
public static String isnull(Object a) {
if (a != null && a != "" && a != "null" && a.toString() != "null") {
return a.toString();
} else {
return "";
}
}
}
完成后,启动项目测试功能是否存在问题:
打开浏览器,在地址栏中访问接口:
http://localhost:8080/test/CreditReporterController/getreport.do?corpname=*****有限公司
访问成功后,返回文件路径:
文件自动下载到桌面:
打开PDF文件,查看格式是否正确:
成功生成PDF文件。
接口测试成功。