1. 背景
ビジネス上の必要により、ダウンロードして閲覧できるようにプログラム データの一部から PDF レポートを生成する必要があります。
2. 実施方法
- PDF テンプレートをデザインし、PDF 編集ツールでテンプレートを編集したり、Adobe Acrobat DC、Wondershare PDF、QuickPDF などの市販のフォーム編集をサポートする PDF エディターを使用したりできます。
- フォーム編集を通じてフォームセルの対応する名前を設定し、その後のプログラムの割り当てに使用します。
- テキストを水平方向に中央揃えに設定できます (ただし、現在のプログラムは垂直方向の中央揃えをサポートしていません。後でこれを実現したい場合は、プログラムを開始する必要があります)。
- テキストを設定したら、プログラムの割り当て(コアコード)の作成を開始できます。
//创建A4大小的文档
Document document = new Document(PageSize.A4);
document.open();
//读取现有模板内容(templateFile为模板路径)
PdfReader reader = new PdfReader(FileUtil.path(templateFile));
//创建输出流
ByteArrayOutputStream bos = new ByteArrayOutputStream();
//实例化PdfStamper准备编辑pdf内容
PdfStamper ps = new PdfStamper(reader, bos);
//获取表单所有元素
AcroFields fields = ps.getAcroFields();
//设置具体字体格式编码,不设置的话中文可能会不显示
BaseFont baseFont = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
/添加替换元素
fields.addSubstitutionFont(baseFont);
//data是一个Map<String,String> 主要存储 key 表单模板中的单元格名 value为想要赋的值,遍历
for (String key : data.keySet()) {
String value = data.get(key);
//个人逻辑,参考即可,对于特定的表单元素设置不同的字体格式大小
if("r_game".equals(key)) {
//设置格式
fields.setFieldProperty(key, "textsize", 35f, null);
}else if("i_title".equals(key)) {
fields.setFieldProperty(key, "textsize", 20f, null);
}else if ("r_image".equals(key)){
if (!StringUtils.isEmpty(value)){
//设置添加图片
addImageToPdf(fields, ps,value);
continue;
}
}else if ("r_project_name".equals(key)||"r_header".equals(key)||"r_appraisal".equals(key)){
//将文本垂直居中添加
addTextToPdfCenter(fields,ps,value,key,baseFont);
continue;
}
else {
fields.setFieldProperty(key, "textsize", defaultSize, null);
}
fields.setField(key, value);
}
//生成的文档可编辑
ps.setFormFlattening(true);
//关闭操作
ps.close();
//将编辑后的文件输出到outputFile路径下
OutputStream fos = new FileOutputStream(FileUtil.path(outputFile));
fos.write(bos.toByteArray());
bos.close();
fos.close();
document.close();
- テーブル テンプレートへの画像の入力
private static void addImageToPdf(AcroFields form, PdfStamper stamper, String filePath) throws DocumentException, IOException {
// 通过域名获取所在页和坐标,左下角为起点
int pageNo = form.getFieldPositions("r_image").get(0).page;
Rectangle signRect = form.getFieldPositions("r_image").get(0).position;
float x = signRect.getLeft()+signRect.getRight();
float y = signRect.getTop();
// 读图片
Image image = Image.getInstance(filePath);
// 获取操作的页面
PdfContentByte under = stamper.getOverContent(pageNo);
// 根据域的大小缩放图片
image.scaleToFit(signRect.getWidth()/4, signRect.getHeight()/4);
// 添加图片并设置位置(个人通过此设置使得图片垂直水平居中,可参考,具体情况已实际为准)
image.setAbsolutePosition(x/2-image.getWidth()/2, y/2+image.getHeight());
under.addImage(image);
}
- 次のようにテキストが垂直方向に中央揃えになりません。
テキストを垂直方向に中央揃えにする
テンプレートの位置を取得し、フォームセルをリファクタリングすることで垂直方向の中央に配置します
private static void addTextToPdfCenter(AcroFields form, PdfStamper stamper, String text,String fieldName,BaseFont baseFont){
// 通过模板表单单元格名获取所在页和坐标,左下角为起点
int pageNo = form.getFieldPositions(fieldName).get(0).page;
Rectangle signRect = form.getFieldPositions(fieldName).get(0).position;
// 获取操作的页面
PdfContentByte contentByte = stamper.getOverContent(pageNo);
//创建表单
PdfPTable table = new PdfPTable(1);
//获取当前模板表单宽度
float totalWidth = signRect.getRight() - signRect.getLeft() - 1;
//设置新表单宽度
table.setTotalWidth(totalWidth);
//设置中文格式
Font font = new Font(baseFont);
//设置单元格格式
PdfPCell cell = new PdfPCell(new Phrase(text,font));
//设置单元格高度
cell.setFixedHeight(signRect.getTop()-signRect.getBottom()-1);
cell.setBorderWidth(0);
//设置垂直居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
//设置水平居中
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
//添加到表单中
table.addCell(cell);
//写入pdf
table.writeSelectedRows(0, -1, signRect.getLeft(), signRect.getTop(), contentByte);
}
効果は以下の通りです