一、背景
由于业务需求,我需要将程序的部分数据生成PDF报告以供下载浏览,且部分表单框样式希望根据内容的长短变化大小
二、实现方式
public class PdfUtil {
private static List<String> nameList = new ArrayList<>();
private static Font titlefont;
private static Font titlefont1;
private static Font headfont;
private static Font keyfont;
private static Font textfont;
private static int maxWidth = 520;
static {
nameList.add("r_project_name");
nameList.add("r_header");
nameList.add("r_appraisal");
nameList.add("i_name");
nameList.add("i_person");
nameList.add("i_result");
nameList.add("i_status");
try {
// 不同字体(这里定义为同一种字体:包含不同字号、不同style)
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
titlefont = new Font(bfChinese, 17, Font.BOLD, BaseColor.GRAY);
titlefont1 = new Font(bfChinese, 15, Font.BOLD);
headfont = new Font(bfChinese, 12, Font.BOLD);
keyfont = new Font(bfChinese, 10, Font.BOLD);
textfont = new Font(bfChinese, 10, Font.NORMAL);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws DocumentException, IOException {
Map<String, String> reviewData = new HashMap<>();
reviewData.put("r_project_name", "测试项目");
reviewData.put("r_header", "张三");
reviewData.put("r_appraisal", "李四");
reviewData.put("r_image", "C:\\Pictures\\fail.png");
reviewData.put("r_type", "通过");
List<Map<String,String>> itemData = new ArrayList<>();
for(int i = 0;i<3;i++){
Map<String,String> map = new HashMap<>();
map.put("i_type","类型"+i);
map.put("i_name","名称"+i);
map.put("i_status","状态"+i);
map.put("i_standard","标准"+i);
map.put("r_image","C:\\Pictures\\fail.png");
map.put("i_person","张三"+i);
map.put("i_result","结果"+i);
itemData.add(map);
}
createReportPdf("C:\\Pictures\\fail.png","D:\\test.pdf",reviewData,itemData);
}
/**
* @description: 自定义pdf样式创建pdf
* @params: [templateFile pdf右上角插入的图片地址
* outputFile 生成pdf文件的地址
* reviewData 评审数据
* itemData 科目数据
*/
public static String createReportPdf(String templateFile, String outputFile, Map<String, String> reviewData, List<Map<String, String>> itemData) throws IOException, DocumentException {
//创建文档
Document document = new Document(PageSize.A4);
//文件生成输出路径
File file = new File(outputFile);
//初始化
PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(file));
//设置页眉页脚
writer.setPageEvent(new MyHeaderFooter());
//开启文档编辑
document.open();
//通过图片路径初始化Image
Image image = Image.getInstance(templateFile);
//设置向右对齐
image.setAlignment(Element.ALIGN_RIGHT);
//依照比例缩放图片
image.scalePercent(50);
//创建总评表单
PdfPTable table = createTable1(new float[]{
5, 3, 15, 5});
table.addCell(createCell("项目名称", headfont));
table.addCell(createCell("专家", headfont));
table.addCell(createCell("风险", headfont));
table.addCell(createCell(reviewData.get("r_type"), headfont));
table.addCell(createCell(reviewData.get("r_project_name"), textfont));
table.addCell(createCell(reviewData.get("r_header"), textfont));
table.addCell(createCell(reviewData.get("r_appraisal"), textfont));
table.addCell(createImageCell(reviewData.get("r_image"), 1));
//创建段落
Paragraph paragraph = new Paragraph("评审情况", titlefont);
//设置文字居中 0靠左 1,居中 2,靠右
paragraph.setAlignment(0);
//段落开头前距
paragraph.setSpacingBefore(10f);
//写入文档
document.add(image);
document.add(table);
document.add(paragraph);
createReportPdf(document, itemData);
document.close();
return outputFile;
}
/**
* @description: 创建pdf中科目的样式
* @params: [document, itemData]
*/
public static void createReportPdf(Document document, List<Map<String, String>> itemData) throws IOException, DocumentException {
for (Map<String, String> itemMap : itemData) {
Paragraph paragraph = new Paragraph(itemMap.get("i_header"), titlefont1);
document.add(paragraph);
PdfPTable table = createTable(new float[]{
10, 10, 10, 10, 10, 5});
table.addCell(createCell("科目类型", keyfont));
table.addCell(createCell(itemMap.get("i_type"), textfont));
table.addCell(createCell("科目名称", keyfont));
table.addCell(createCell(itemMap.get("i_name"), textfont));
table.addCell(createCell("是否为必过", keyfont));
table.addCell(createCell(itemMap.get("i_status"), textfont));
table.addCell(createCell("标准值", keyfont, 6));
table.addCell(createCell(itemMap.get("i_standard"), textfont, Element.ALIGN_LEFT, 6, 170f));
table.addCell(createCell("评估结果", keyfont, 2));
table.addCell(createImageCell(itemMap.get("r_image"), 4));
table.addCell(createCell("评估人", keyfont, 2));
table.addCell(createCell(itemMap.get("i_person"), textfont, 4));
table.addCell(createCell("测试结果及风险评估", keyfont, 6));
table.addCell(createCell(itemMap.get("i_result"), textfont, Element.ALIGN_LEFT, 6, 100f));
document.add(table);
}
document.close();
}
/**
* @description: 创建图片单元格
* @params: [imagePath, colspan]
*/
public static PdfPCell createImageCell(String imagePath, int colspan) throws BadElementException, IOException {
if (imagePath == null || "".equals(imagePath)) {
return new PdfPCell();
}
//通过图片路径初始化图片
Image image = Image.getInstance(imagePath);
//居中
image.setAlignment(Element.ALIGN_CENTER);
//按70的比例缩小
image.scalePercent(70);
//添加到单元格内
PdfPCell pCell = new PdfPCell(image, false);
//跨列
pCell.setColspan(colspan);
//设置居中
pCell.setHorizontalAlignment(Element.ALIGN_CENTER);
pCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
return pCell;
}
/**
* @description: 创建单元格指定内容和字体
* @params: [value, font]
*/
public static PdfPCell createCell(String value, Font font) {
PdfPCell cell = new PdfPCell();
//居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
//设置最小高度
cell.setMinimumHeight(30f);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* @description: 创建单元格指定内容,字体,跨列
* @params: [value, font, colspan]
*/
public static PdfPCell createCell(String value, Font font, int colspan) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
cell.setColspan(colspan);
cell.setMinimumHeight(30f);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* @description: 创建单元格指定 内容、字体、位置、跨列、最小高度
* @params: [value, font, align, colspan, height]
*/
public static PdfPCell createCell(String value, Font font, int align, int colspan, float height) {
PdfPCell cell = new PdfPCell();
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
cell.setHorizontalAlignment(align);
cell.setColspan(colspan);
cell.setMinimumHeight(height);
cell.setPhrase(new Phrase(value, font));
return cell;
}
/**
* @description: 创建表单指定列数
* @params: [widths]
*/
public static PdfPTable createTable1(float[] widths) {
PdfPTable table = new PdfPTable(widths);
try {
table.setTotalWidth(maxWidth);
table.setLockedWidth(true);
table.setSpacingBefore(5.0f);
table.setHorizontalAlignment(Element.ALIGN_CENTER);
table.getDefaultCell().setBorder(1);
} catch (Exception e) {
e.printStackTrace();
}
return table;
}
public static PdfPTable createTable(float[] widths) {
PdfPTable table = new PdfPTable(widths);
try {
//设置宽度
table.setTotalWidth(maxWidth);
//固定宽度
table.setLockedWidth(true);
//前距
table.setSpacingBefore(15.0f);
//后距
table.setSpacingAfter(30.0f);
//内容居中
table.setHorizontalAlignment(Element.ALIGN_CENTER);
//设置边框
table.getDefaultCell().setBorder(1);
} catch (Exception e) {
e.printStackTrace();
}
return table;
}
}
class MyHeaderFooter extends PdfPageEventHelper {
static Font hfFont;
static {
try {
hfFont = new Font(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED), 12, Font.NORMAL);
} catch (DocumentException | IOException e) {
e.printStackTrace();
}
}
@Override
public void onOpenDocument(PdfWriter writer, Document document) {
}
/**
* @description: 一页加载完成触发,写入页眉和页脚
* @params: [writer, document]
* @return:
*/
@Override
public void onEndPage(PdfWriter writer, Document document) {
PdfPTable table = new PdfPTable(1);
try {
table.setTotalWidth(520);
table.setWidths(new int[]{
1});
table.setLockedWidth(true);
PdfPCell headerCell = new PdfPCell();
headerCell.setPhrase(new Phrase("第" + writer.getPageNumber() + "页", hfFont));
headerCell.setFixedHeight(30f);
headerCell.setBorderWidthLeft(0);
headerCell.setBorderWidthRight(0);
headerCell.setBorderWidthTop(0);
headerCell.setBorderWidthBottom(0);
headerCell.setHorizontalAlignment(Element.ALIGN_CENTER);
table.addCell(headerCell);
// 将页眉写到document中
table.writeSelectedRows(0, -1, 25, PageSize.A4.getBottom() + 30, writer.getDirectContent());
PdfPTable headerTable = new PdfPTable(1);
headerTable.setTotalWidth(520);
//设置页眉内容
PdfPCell footCell = new PdfPCell();
footCell.setPhrase(new Phrase("测试报告", hfFont));
footCell.setFixedHeight(25f);
//设置单元格无边框
footCell.setBorderWidthLeft(0);
footCell.setBorderWidthRight(0);
footCell.setBorderWidthTop(0);
footCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
headerTable.addCell(footCell);
//页码写入
headerTable.writeSelectedRows(0, -1, 37, PageSize.A4.getHeight() - 10, writer.getDirectContent());
} catch (Exception de) {
throw new ExceptionConverter(de);
}
}
// 全部完成后,将总页数的pdf模版写到指定位置
@Override
public void onCloseDocument(PdfWriter writer, Document document) {
}
三、效果图