OFD开发系列(二)-模板填充
原文链接:https://blog.csdn.net/oAXuHui/article/details/109726036
#、接上篇
我们前面对水印填充方法进行了简单介绍,本章描述的模板填充,可以是正文的填充,也可以是水印填充,水印填充可参考上一篇《OFD开发系列(一)-添加水印》。
一、什么是模板填充
模板填充是指基于固定的模板文档,在指定的位置(坐标/百分比)或文本替换填入所需的图片、文本、日期等内容,最后生成一个可用的文档以供用户存档、检索、签署等。我们知道,PDF可以使用表单填充,并且可以设置文字的字体、颜色、字号、对齐方式等。而在OFD版式文档里,没有表单的概念,我们需要采用其它方法进行填充。如下所示:
基于关键字填充:此处需要查找关键字,然后增加相对应的偏移值进行填充。
基于坐标填充:此处可以指定坐标x/y值(单位mm)或百分比进行填充,这种填充方法需要模板编辑系统的支持,例如:在页面上标注好填充坐标或填充百分比位置。
基于文本替换:此处可以基于模板引擎进行文本替换或自定义标识符,该方法可能会对版式文档的阅读版式产生影响,需要定义好字符长度、字体、字号等参数。
二、模板填充的场景
常见的填充场景有如下几类:电子保单、电子合同、取证报告、调查问卷、电子发票等。总之,关键内容需要变更的电子文档,都需要具备模板填充能力。
三、ofdrw实现填充
3.1、模板填充准备
我们将上文提到的模板填充方法(关键字填充、坐标填充)进行模板填充演示,文本替换各位可以基于模板引擎直接实现文本替换,此处不进行详细说明。
首先,我们需要在maven引入ofdrw的jar包(注意此处由于ofdrw功能优化升级和上一篇的版本不一致):
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
<scope>provided</scope>
</dependency>
<!-- ofdrw -->
<dependency>
<groupId>org.ofdrw</groupId>
<artifactId>ofdrw-full</artifactId>
<version>1.6.10</version>
</dependency>
其次,我们准备一个待填充的模板文档,第一列为A列,第二列为B列,其中事项标题为A1,A1旁边为B1,以此类推,如下所示:
3.2、关键字填充
我们需要对事项标题后面的文本框填入“基于ofdrw的关键字模板填充实现”,申请依据后面填入“新版本演示”。代码如下:
/**
* 模板处理
*/
@Test
public void testTemplateTextBaseKeyword() throws IOException, DocumentException {
Path inP = Paths.get("src/test/resources/z.ofd");
Path outP = Paths.get("target/Canvas-fillText.ofd");
try (OFDReader reader = new OFDReader(inP);
OFDDoc ofdDoc = new OFDDoc(reader, outP)) {
String t1 = "事项标题", t2 = "申请依据";
String f1 = "基于ofdrw的关键字模板填充实现", f2 = "新版本演示";
String[] keywords = {t1, t2};
List<KeywordPosition> positionList = KeywordExtractor.getKeyWordPositionList(reader, keywords);
//偏移量需要模板制作确认
float offset = 25;
for (KeywordPosition position : positionList) {
//创建可追加的虚拟页面
AdditionVPage page = ofdDoc.getAVPage(position.getPage());
//创建一个可以自动换行的段落
Paragraph paragraph = new Paragraph();
paragraph.setPosition(Position.Absolute)
.setWidth(f1.length() * 5.0).setHeight(10D) //设置外接矩形宽高
.setX(position.getBox().getTopLeftX() + position.getBox().getWidth() + offset) //设置x坐标
.setY(position.getBox().getTopLeftY()); //设置y坐标
//创建 Span 文本控件对象
Span span;
if (t1.equals(position.getKeyword())) {
span = new Span(f1);
} else {
span = new Span(f2);
}
//设置Span的属性
span.setFontSize(5.0);
span.setColor(0, 0, 0);
//段落添加Span文本控件
paragraph.add(span);
//页面添加段落
page.add(paragraph);
}
}
System.out.println("生成文档位置:" + outP.toAbsolutePath().toString());
}
此处通过KeywordExtractor检索到两个关键字的坐标,制作确认模板偏移量,通过循环创建,完成模板填充。特别指出:需要创建可追加的虚拟页面和需要计算好外接矩形的x/y坐标和宽高,文本控件对象Span支持的设置很多,如下所示,在此不在详述:
public class Span implements TextFontInfo {
private Font font;
private Double fontSize;
private Double letterSpacing;
private boolean bold;
private boolean italic;
private boolean underline;
private String text;
private int[] fillColor;
private boolean linebreak;
private Boolean integrity;
}
填充效果如下:
3.3、坐标填充
我们需要对事项依据下面的单元格A3 和 A3右边的单元格B3进行坐标填充,同样的,我们需要制作填充模板,确提前确定坐标位置,A3使用毫米单位,B3使用百分比单位。代码如下所示:
/**
* 模板处理
*/
@Test
public void testTemplateTextBaseKeyword() throws IOException, DocumentException {
Path inP = Paths.get("src/test/resources/z.ofd");
Path outP = Paths.get("target/Canvas-fillText.ofd");
try (OFDReader reader = new OFDReader(inP);
OFDDoc ofdDoc = new OFDDoc(reader, outP)) {
String key = "申请人", value = "ofdrw";
/*
* 此处参数值需要模板确定
*/
double A3_X = 30, A3_Y = 60.77;
//此处为36%和20.33%
double B3_X = 0.36 * ofdDoc.getPageLayout().getWidth(),
B3_Y = 0.2033 * ofdDoc.getPageLayout().getHeight();
//创建可追加的虚拟页面(指定第1页)
AdditionVPage page = ofdDoc.getAVPage(1);
//1、添加A3
{
//创建一个可以自动换行的段落
Paragraph paragraph = new Paragraph();
paragraph.setPosition(Position.Absolute)
.setWidth(key.length() * 5.0).setHeight(10D) //设置外接矩形宽高
.setX(A3_X) //设置x坐标
.setY(A3_Y); //设置y坐标
//创建 Span 文本控件对象
Span span = new Span(key);
//设置Span的属性
span.setFontSize(5.0);
span.setColor(0, 0, 0);
//段落添加Span文本控件
paragraph.add(span);
//页面添加段落
page.add(paragraph);
}
//2、添加B3
{
//创建一个可以自动换行的段落
Paragraph paragraph = new Paragraph();
paragraph.setPosition(Position.Absolute)
.setWidth(value.length() * 5.0).setHeight(10D) //设置外接矩形宽高
.setX(B3_X) //设置x坐标
.setY(B3_Y); //设置y坐标
//创建 Span 文本控件对象
Span span = new Span(value);
//设置Span的属性
span.setFontSize(5.0);
span.setColor(0, 0, 0);
//段落添加Span文本控件
paragraph.add(span);
//页面添加段落
page.add(paragraph);
}
}
System.out.println("生成文档位置:" + outP.toAbsolutePath().toString());
}
和3.2结果类似,此处生成了一个新的文档,如下所示:
到此,填充方法演示完成,这些在ofd里其实都是基本的功能。
四、遗留问题
上文提到的模板填充遗留两个问题:第一、填充模板制作;第二、是否支持表单填充;第三、没有日期、图片和图形的填充,各位可以基于此编写相关demo。目前没有开源的模板制作方案,各位有兴趣的同学可以自行研究并开源贡献。
————————————————
版权声明:本文为CSDN博主「阿徐汇」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/oAXuHui/article/details/109726036