文章目录
一、itxet生成PDF五个步骤
第 1 步:创建一个 PdfWriter 对象
该PdfWriter类表示PDF文档的作家。此类属于包com.itextpdf.kernel.pdf。此类的构造函数接受一个字符串,表示要在其中创建 PDF 的文件的路径。
通过向其构造函数传递一个字符串值(表示您需要创建 PDF 的路径)来实例化 PdfWriter 类,如下所示。
第 2 步:创建一个 PdfDocument 对象
该PdfDocument类为表示在iText的PDF文档类。此类属于包com.itextpdf.kernel.pdf。要实例化此类(在写入模式下),您需要将PdfWriter类的对象传递给其构造函数。
通过将上面创建的 PdfWriter 对象传递给其构造函数来实例化 PdfDocument 类,如下所示。
第 3 步:添加一个空页面
PdfDocument类的addNewPage()方法用于在 PDF 文档中创建一个空白页面。
为上一步创建的 PDF 文档添加一个空白页面,如下所示。
第 4 步:创建一个 Document 对象
包com.itextpdf.layout的Document类是创建自给自足的 PDF 时的根元素。此类的构造函数之一接受类 PdfDocument 的对象。
通过传递在前面的步骤中创建的类PdfDocument的对象来实例化Document类,如下所示。
步骤 5:关闭文档
使用Document类的close()方法关闭文档,如下所示。
二、itext生成pdf
1.代码
1.1.依赖
<!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.13</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>
1.2基本使用
代码如下
/**
*
* @param value 文本
* @param font 字体
* @param horizontalAlignment 水平样式 0-left, 1-center, 2-right
* @param verticalAlignment 垂直样式 4-top, 5-middle, 6-bottom;
* @param colspan 列合并
* @param rowspan 行合并
* @param borderSide 外边框
* 0-默认
* 1-隐藏上边框
* 2-隐藏下边框
* 3-隐藏上、下边框
* 4-隐藏左边框
* 5-隐藏左、上边框
* 6-隐藏左、下边框
* 7-隐藏左、上、下边框
* 8-隐藏右边框
* 9-隐藏右、上边框
* 10-隐藏右、下边框
* 11-隐藏右、上、下边框
* 12-隐藏左、右边框
* 13-隐藏上、左、右边框
* 14-隐藏下、左、右边框
* 15-隐藏全部
* @return
*/
public static PdfPCell createCell(String value, Font font, int horizontalAlignment, int verticalAlignment, int colspan, int rowspan, int borderSide) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, font));//存值
cell.setHorizontalAlignment(horizontalAlignment);//水平居中
if(verticalAlignment>0){
cell.setUseAscender(true);//垂直居中
}
cell.setVerticalAlignment(verticalAlignment);//垂直居中
if(colspan>0 ){
cell.setColspan(colspan);
}
if(rowspan>0){
cell.setRowspan(rowspan);
}
if(borderSide>0){
cell.disableBorderSide(borderSide);
}
return cell;
}
public static void generatePDFDoc(){
Document doc = new Document(PageSize.A4);//定义doc
try {
File file = new File("C:\\Users\\cbh17\\Desktop\\test.pdf");//生成目标文件
file.createNewFile();
PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(file));
writer.setPageEvent(new Watermark("LeaSoft"));// 水印
doc.open();//open
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
//2. BaseFont.createFont("C:/WINDOWS/Fonts/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
//3. BaseFont.createFont("/simsun.ttc", BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
Font font = new Font(bf, 10, Font.NORMAL, BaseColor.BLACK);//字体
//使用中文字体有三种方式
//1.使用itext自带的字体集包
//2.使用本地的 字体资源
// 2.1 windows下,字体资源在目录 C:/WINDOWS/Fonts,注意 ttc后缀要 加 ',1'
// 2.2 linux 未尝试,不过同理,找到字体资源的绝对路径即可
//3.可以将 字体资源 放到项目 当中
Paragraph paragraph1 = new Paragraph("XXXXXXXXX", font);//段落
paragraph1.setAlignment(PdfPCell.ALIGN_CENTER);
paragraph1.setLeading(14f); //行间距
//paragraph1.setIndentationLeft(12); //设置左缩进
//paragraph1.setIndentationRight(12); //设置右缩进
//paragraph1.setFirstLineIndent(24); //设置首行缩进
//paragraph1.setSpacingBefore(5f); //设置段落上空白
//paragraph1.setSpacingAfter(10f); //设置段落下空白
//itext中没有行和列的概念,只有单元格,因此在声明table时就要指定列数
//然后按table.addCell(cell)顺序添加
PdfPTable table = new PdfPTable(new float[] { 1f, 1.5f, 1f, 1.5f});
//表头
table.addCell(createCell("XXX", font, PdfPCell.ALIGN_LEFT, PdfPCell.ALIGN_MIDDLE, 0,0,15));
table.addCell(createCell("XXX", font, PdfPCell.ALIGN_LEFT, PdfPCell.ALIGN_MIDDLE,3,0,15));
table.addCell(createCell("XXX", font, PdfPCell.ALIGN_LEFT, PdfPCell.ALIGN_MIDDLE,0,0,15));
table.addCell(createCell("XXX", font, PdfPCell.ALIGN_LEFT, PdfPCell.ALIGN_MIDDLE,0,0,15));
table.addCell(createCell("XXX", font, PdfPCell.ALIGN_LEFT, PdfPCell.ALIGN_MIDDLE,0,0,15));
table.addCell(createCell("XXX", font, PdfPCell.ALIGN_LEFT, PdfPCell.ALIGN_MIDDLE,0,0,15));
//动态表格
for(int i = 0; i<6; i++){
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("v", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
}
doc.add(paragraph1);
doc.add(table1);
}catch (Exception e){
e.printStackTrace();
}finally {
// 5.关闭文档
if(doc!=null){
doc.close();
}
}
}
二、pdf模板生成pdf
1.制作pdf模板
1.1下载Adobe Acrobat DC
官网比较慢 百度网盘永久链接https://pan.baidu.com/s/1JnkOtudacCKqdYpHqtR-Wg
提取码 :EDG6
2.制作
- 使用word制作,填充完文本样式之后,转pdf
- 使用Adobe编辑打开
点击准备表单,会自动帮你创建好表单,要是没有这个按钮,就去 更多工具 里添加
此按钮可以用户自定义添加表单
为每个表单添加唯一的别名
到此制作完成,但是使用pdf模板,无法实现添加动态表格,后续提供解决思路,不过还是不理想
3.代码
public static void generateTempPDF() throws Exception {
PdfReader reader = null;
PdfStamper ps = null;
OutputStream fos = null;
ByteArrayOutputStream bos = null;
try {
String fileName = "C:\\Users\\cbh17\\Desktop\\bb1.pdf";//模板绝对路径
reader = new PdfReader(fileName);
bos = new ByteArrayOutputStream();
ps = new PdfStamper(reader, bos);
// 使用中文字体
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
ArrayList<BaseFont> fontList = new ArrayList<BaseFont>();
fontList.add(bf);
AcroFields fields = ps.getAcroFields();
fields.setSubstitutionFonts(fontList);
fillData(fields, data());//渲染
//必须要调用这个,否则文档不会生成的
ps.setFormFlattening(true);
if(ps != null){
ps.close();
}
//生成pdf路径存放的路径
fos = new FileOutputStream("C:\\Users\\cbh17\\Desktop\\bb2.pdf");
fos.write(bos.toByteArray());
}catch (Exception e){
e.printStackTrace();
}finally {
if(fos!=null){
fos.flush();
fos.close();
}
if (bos != null){
bos.close();
}
if(reader != null){
reader.close();
}
}
}
/**
* 填充模板中的数据
*/
public static void fillData(AcroFields fields, Map<String, String> data) {
try {
for (String key : data.keySet()) {
String value = data.get(key);
// 为字段赋值,注意字段名称是区分大小写的
fields.setField(key, value);
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 填充数据源
* 其中data存放的key值与pdf模板中的文本域值相对应
*/
public static Map<String, String> data() {
Map<String, String> data = new HashMap<String, String>();
//key要与模板中的别名一一对应
data.put("customerName", "bb2");
data.put("houseName", "bb2");
data.put("buildArea", "2020/7");
data.put("code", "2020/7");
data.put("operateDate", "2020/7");
data.put("chargeEndDate", "2020/7");
return data;
}
至此模板填充完毕,但是使用 pdf模板 无法制作动态的 表格,因为并不能预知有多少数据,所以别名就不知道要用多少
3.通过pdf模板制作 除了表格以外的 临时文件,然后解析临时文件再进行填充
3.1代码
private void exportOrderDetailPdf()throws Exception {
List<String> pdfData = analysisPDF();
List<HashMap<String, String>> tableData = data();
generateNewPDF(pdfData,tableData);
}
/**
* 解析 临时文件
* 不清楚itext 有没有获取类似 line对象的办法,保证样式不丢失,否则只能获取文本
* 这里 我是在模板中 加入了一个 table 字符串 用作表格位置的标识
*/
private List<String> analysisPDF() throws Exception{
String tempFilePath = "C:\\Users\\cbh17\\Desktop\\bb2.pdf";//临时文件路径
File tempFile = new File(tempFilePath);
PdfReader reader = null;
List<String> list = new ArrayList<String>();
FileInputStream fileInputStream = null;
boolean deleteSign = true;
try {
fileInputStream = new FileInputStream(tempFile);
reader = new PdfReader(fileInputStream);
int pageNum = reader.getNumberOfPages();
String pageContent = "";
for (int i = 1; i <= pageNum; i++) {// 只能从第1页开始读
pageContent += PdfTextExtractor.getTextFromPage(reader, i);
}
String[] strArr = pageContent.split("\n");
list = Arrays.asList(strArr);
}catch (Exception e){
e.printStackTrace();
deleteSign = false;
}finally {
if (reader!=null){
reader.close();
}
if(fileInputStream!=null){
fileInputStream.close();
}
if(tempFile.exists() && deleteSign){
tempFile.delete();
}
}
return list;
}
/**
*制作假数据
*/
private List<HashMap<String,String>> data(){
List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
int x = 0;
while (x < 10) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("Key1", "Value1");
map.put("Key2", "Value2");
map.put("Key3", "Value3");
map.put("Key4", "Value4");
map.put("Key5", "Value5");
map.put("Key6", "Value6");
map.put("Key7", "Value7");
map.put("Key8", "Value8");
list.add(map);
x++;
}
return list;
}
/**
* 生成pdf
* 有两种情况
* 一种是获取 临时文件的流对象,然后对其做 增 的操作,因此后续添加的 内容只能在后边 不能插入
* 水印也会覆盖临时文件的内容,
* 另一种就是 我这种,获取临时文件的文本,然后 一起生成
*/
private void generateNewPDF(List<String> pdfData, List<HashMap<String, String>> tableData) throws Exception {
Document document = new Document();
FileOutputStream fileOutputStream = null;
PdfWriter writer = null;
try {
File file = new File("C:\\Users\\cbh17\\Desktop\\bb3.pdf");
file.createNewFile();
fileOutputStream = new FileOutputStream(file);
writer = PdfWriter.getInstance(document, fileOutputStream);
writer.setPageEvent(new Watermark("LeaSoft"));// 水印
document.open();
BaseFont bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font font = new Font(bf, 10, Font.NORMAL, BaseColor.BLACK);
for (String str : pdfData) {
if(str.equalsIgnoreCase(TABLE_SIGN)){
PdfPTable table = new PdfPTable(new float[] { 100, 100, 100, 100, 100, 100, 100, 100 });
table.setLockedWidth(true);
table.setTotalWidth(550);
table.addCell(createCell("XXXXXXXX", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("XXXXX", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,3,0,0));
table.addCell(createCell("XXXXXX", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("XXXXX", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("XXXXX", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("XXXXX", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
for (HashMap<String, String> tableDatum : tableData) {
table.addCell(createCell(tableDatum.get("Key1"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key2"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key3"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key4"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key5"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key6"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key7"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell(tableDatum.get("Key8"), font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
}
table.addCell(createCell("hhh", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,6,3,0));
table.addCell(createCell("a", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("a", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("a", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("a", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("a", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
table.addCell(createCell("a", font, Element.ALIGN_CENTER, PdfPCell.ALIGN_MIDDLE,0,0,0));
document.add(table);
}else{
Paragraph paragraph = new Paragraph(str, new Font(bf, 11, Font.BOLD, BaseColor.BLACK));
paragraph.setAlignment(PdfPCell.ALIGN_LEFT);
paragraph.setLeading(14f); //行间距
document.add(paragraph);
}
}
}catch (Exception e){
e.printStackTrace();
}finally {
if(document!=null && document.isOpen()){
document.close();
}
if (writer!=null && !writer.isCloseStream()){
writer.close();
}
if (fileOutputStream!=null){
fileOutputStream.close();
}
}
}
/**
*
* @param value 文本
* @param font 字体
* @param horizontalAlignment 水平样式 0-left, 1-center, 2-right
* @param verticalAlignment 垂直样式 4-top, 5-middle, 6-bottom;
* @param colspan 列合并
* @param rowspan 行合并
* @param borderSide 外边框
* 0-默认
* 1-隐藏上边框
* 2-隐藏下边框
* 3-隐藏上、下边框
* 4-隐藏左边框
* 5-隐藏左、上边框
* 6-隐藏左、下边框
* 7-隐藏左、上、下边框
* 8-隐藏右边框
* 9-隐藏右、上边框
* 10-隐藏右、下边框
* 11-隐藏右、上、下边框
* 12-隐藏左、右边框
* 13-隐藏上、左、右边框
* 14-隐藏下、左、右边框
* 15-隐藏全部
* @return
*/
public static PdfPCell createCell(String value, Font font, int horizontalAlignment, int verticalAlignment, int colspan, int rowspan, int borderSide) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, font));
cell.setHorizontalAlignment(horizontalAlignment);//水平居中
if(verticalAlignment>0){
cell.setUseAscender(true);//垂直居中
}
cell.setVerticalAlignment(verticalAlignment);//垂直居中
if(colspan>0 ){
cell.setColspan(colspan);
}
if(rowspan>0){
cell.setRowspan(rowspan);
}
if(borderSide>0){
cell.disableBorderSide(borderSide);
}
return cell;
}