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