• POI操作Word组件.haiwei-poi-word(模板+数据)


    目录

    Why haiwei-poi-word

    基本思想

    开发方法论

    术语

    版本要求

    快速入门

    模板编写

    组件能力

    文本替换

    最简单文本匹配

    标签前后格式不同

    文本中有标签

    标签中不可有空格

    文本框

    表格支持

    Loop单表

    Loop单表多行

    Loop并联

    Loop并联多行

    Loop嵌套

    图片打印

    代码架构

    Q&A

    Word版本支持03吗

    图片打印宽度单位和关系

    扩展能力

    代码


    Why haiwei-poi-word

    haiwei-poi-word 基于poi,自己编码实现比较负责,且需要兼容各种版本,可以做但很繁杂。word不同于excel行列分明,并且跟实际客户端的排版设置有关系,单纯代码实现工作量大,可扩展性差,并且效果不确定。

    同类比较:Poi-tl,也是个不错的组件,功能强大。有poi-tl为啥要封装Haiwei-poi呢?poi-tl就像是成品柜,Haiwei-poi-word更像是针对Saas化的定制。

    侧重点不同:

    poi-tl: 数据和模板没有完全分离,是用代码操作word的比较好的封装。

    haiwei-poi-word则完全分离,所有样式全部由模板word决定。

    基本思想

    文档 = 模板 + 模型(Model)

    模板: 提供所有布局和样式

    Model:只提供模板中需要填充的数据

    模板只在逻辑上预留位置,并设定展示的参数

    组件会根据数据类型 + 展示参数 来进行展示

    问题1: 如果位置是方框,参数是图片,数据是字符串 >> 字符串

    问题2: 位置是文本,参数是图片,数据是字符串 >>  字符串

    问题3:位置是文本,参数是图片,数据是图片 >>  根据参数展示图片

    问题4:位置是文本,参数没有,数据是图片 >>  展示原图

    如果模板和模型不匹配时展示原则:牺牲样式,尽可能展示数据

    - 好处:把问题展示出来,有助于问题的暴露和及早进行模板或者数据调整。

    模型决定数据类型

    - 字符串,图片

    开发方法论

    TDD 测试驱动设计

    这么复杂的系统,靠前期的设计很难设计完整,所以就按照case走。

    术语

    标签:占位符,place_holder  label sign 都指的是 ##{customer.name}

    版本要求

    POI 4.1.2+

    JDK 1.8+

    Office Word 2007(咱不支持03)

    快速入门

    Start

    <dependency>
       <groupId>com.haiweigroupId>
       <artifactId>haiwei-poi-wordartifactId>
       <version>1.0.1version>
    dependency>

    模板文件:

     示例代码:

    1. // 加载模板文件
    2. final XWPFDocument document = HaiweiDocumentGenerator.build(new File("template.docx"));
    3. // 数据构建
    4. List<Item1> items1 = new ArrayList<>();
    5. items1.add(new Item1("键盘11","电子类11","2020/8/11",new HaiweiImages()));
    6. items1.add(new Item1("键盘12","电子类12","2020/8/12",new HaiweiImages()));
    7. items1.get(0).getImages().addFiles("img1.jpg","img2.jpg");
    8. items1.get(1).getImages().addFiles("img2.jpg","img2.jpg");
    9. List<Item1> items2 = new ArrayList<>();
    10. items2.add(new Item1("键盘21","电子类21","2018/8/21",new HaiweiImages()));
    11. items2.add(new Item1("键盘22","电子类22","2018/8/22",new HaiweiImages()));
    12. items2.get(0).getImages().addFiles("img1.jpg","img2.jpg");
    13. items2.get(1).getImages().addFiles("img2.jpg","img2.jpg");
    14. Order1 order1 = new Order1("梅长苏1","N0001",items1);
    15. Order1 order2 = new Order1("梅长苏2","N0002",items2);
    16. List<Order1> orders = new ArrayList<>();
    17. orders.add(order1);
    18. orders.add(order2);
    19. // 添加bean
    20. HaiweiBeanCacheManager.setBean(orders,"orders");
    21. // 根据路径设置 单个变量
    22. HaiweiBeanCacheManager.setString("文档编号0011","文档编号00011");
    23. // 打印数据树
    24. HaiweiBeanCacheManager.print();
    25. // 设置回调函数,解决解析过程中的数据获取场景
    26. HaiweiBeanCacheManager.setCallBackCache(new HaiweiBeanCallback() {
    27. @Override
    28. public Object getBean(String path) {
    29. return null;
    30. }
    31. });
    32. //解析文档
    33. HaiweiXWPFDocumentUtil.parse(document);
    34. // 生成文件
    35. final File file = new File("结果文件.docx");
    36. HaiweiDocumentGenerator.toFile(document,file);

    模板编写

    组件能力

    数据类型

    文本(字符串,数字等可用字符串展示的),图片,图标

    标签位置:

    文本,文本框,表格

    文档位置:

    正文,页眉,页脚,备注

    表格:

    并联(不限制长度),嵌套(不限制深度),并联嵌套

    风格:

    背景,水印

    说明:已支持的为黑体展示。

    文本替换

    标签格式:##{ 标签名称.子对象.Name1:key=value&key1=value1 }

    注意:

    1. 中间不可有空格和换行(上面只是为了展示用,要不然就给替换了)
    2. 标签名称字符:中文,英文大小写,数字
    3. 风格符:点.  冒号: 等于= 与&
    4. 子对象可以多级,逻辑上没有层数限制

    最简单文本匹配

    ##{aa}

    标签前后格式不同

    按照最前面字符格式展示

    ##{aa}

    文本中有标签

    @$&*1我 AAA#######{aa}}}}}BBB@$&*1我

    标签中不可有空格

    有空格不会替换

    ##{a a}

    文本框

    文本框处理只是位置不同,处理方式一致。

    1###{aa}}}

    表格支持

    Loop单表

    订单编号:##{order.no}

    订单名称:##{order.name}

    行项1

    产品名称1

    产品金额1

    ##={begin:order.items_item}##={order:time_降序}

    ##{ item.name}

    ##{ item.type}

    ##{ item.time1}

    ##={end}

    Loop单表多行

    订单编号:##{order.no}

    订单名称:##{order.name}

    行项1

    产品名称1

    产品金额1

    ##={begin:order.items_item}##={order:time_降序}

    ##{ item.name}

    ##{ item.type}

    ##{ item.time1}

    ##{ item.time}

    ##={end}

    Loop并联

    订单编号:##={编号}

    订单名称:##={名称}

    订单类型:##={业务类型}

    订单时间:##={创建时间}

    行项1

    产品名称

    产品金额

    ##={begin:Items_item}##={order: item.时间_升序/降序}

    ##{item.名称}

    ##{item.业务类型}

    ##={item.创建时间}

    ##={end}

    行项1

    产品名称

    产品金额

    ##={begin:Items_item}##={order: item.时间_升序/降序}

    ##={ item.名称}

    ##={ item.业务类型}

    ##={ item.创建时间}

    ##={end}

    ##={begin:orders_order}

    订单编号:

    ##={ order.no}

    订单名称:

    ##={ order.name}

    产品名称

    产品类型

    时间

    ##={begin:order.items_item}

    ##={item.name }

    ##={item.type}

    ##={item.time}

    ##={end}

    ##={end}

    Loop并联多行

    订单编号:##={order.no}

    订单名称:##={order.name}

    行项1

    产品名称1

    产品金额1

    ##={begin:order.items_item}##={order:time_降序}

    ##={ item.name}

    ##={ item.type}

    ##={ item.time1}

    ##={ item.time}

    ##={end}

    行项2

    产品名称2

    产品金额2

    ##={begin:order.items_item}##={order:item.时间_降序}

    ##={ item.name}

    ##={ item.type}

    ##={ item.time}

    ##={ item.time1}

    ##={end}

    Loop嵌套

    ##={begin:orderList_order}##={order:order.account_升序}

    订单编号:

    ##={ order.no}

    订单名称:

    ##={ order.name}

    订单详细:

    行项1

    产品名称

    产品金额

    ##={begin:order.Items_item}##={order:item.time_升序}

    ##={item.名称}

    ##={item.业务类型}

    ##={item.创建时间}

    ##={end}

    ##={end}

    图片打印

    1. 表格:固定表格宽度,设置图片参数,缺省按照原图展示
    2. 文字中,插入表格,文字替换为图片
    3. 样例:
      1. ##{image_placeholder1:width=2.6&height=3.5}图片固定宽度,单位厘米
      2. ##{ image_placeholder1:size=auto} 前提条件:表格中,固定宽度,否则该参数失效。如根据图片数量,设置自动调整图片大小,布局为:2*2  3*3
      3. ##{image_placeholder1}原图输出
    4. 设置优先级:
      1. 明确指定宽和高 优先级最高
      2. 表格中,固定宽度,备注参数:size=auto,根据图片数量跳转图片宽度,高度按照宽度等比缩放
      3. 上述都没有就按照原图宽度输出
    5. 单位:point默认,px像素,cm厘米
    6. 打印图片数量limit
      1. 默认1
      2. 设置后才按照设置的数量打印,不足则按照实际输出,超过则按照limit设置数量
      3. Limit取值:all,即为全部打印
    7. 自动跳转尺寸适应内容别选了。选择后格式会通过内容多少来自动调整,可能不是用户想要的。所以需要判断字段内容的长度。

    8. 需要考虑单元格边距,默认2mm,固定宽度的时候考虑进去

    代码架构

    1. HaiweiBeanCacheManager 数据提供者
      1. 提前进行线程缓存
      2. 在解析word需要数据的时候通过回调获取
    2. HaiweiXWPFDocumentUtil 文档解析类
      1. 获取文档的页眉,页脚,正文分别对段落和表格进行处理
      2. 表格处理:解析模板生成Haiweitable模型,将模型和Bean结合,删除模板行
    3. HaiweiDocumentGenerator 文档对象生成和输出为docs文件工具类

    Q&A

    Word版本支持03吗

    暂不支持

    图片打印宽度单位和关系

    English Metric Units (EMUs)  英制公制单位(EMU),有时称为A单位

    转换类:org.apache.poi.util.Units.toEMU

    PIXEL像素 = 9525 * 1EMU

    CENTIMETER厘米 = 360000 EMUs = 28.34 * Point点

    Inch 英寸 = 2.54厘米

    1英尺 = 12英寸

    1POINT点 = 12700 * EMU = 13.3 * PIXEL像素

    Point 点数 打印和印刷单位

    DXA 1/20 *

    Dxa/20/28.34 = 厘米

    扩展能力

    1. 封装占位符和循环开始结束符,用户可自定义规则*****  提取出来
    2. SpringEL表达式***
    3. 异常处理 *
    4. 拦截器*
    5. 插件*
    6. 文档输出*****
    7. BeanCache缓存实现

    代码

    haiwei-poi: poi的常用操作的封装

  • 相关阅读:
    VSCode单机活动栏图标无法收起
    Spring Boot + EasyUI Datebox和Datetimebox样例
    武汉凯迪正大KDHG-220P互感器综合测试仪
    JavaScript实现代码雨
    【云原生之k8s】kubeadm搭建k8s集群
    高级深入--day38
    接口幂-全面详解(学习总结---从入门到深化)
    闲话Python编程-字典dict
    【TA-霜狼_may-《百人计划》】图形3.2 混合模式及剔除
    React - React v18 的 批处理
  • 原文地址:https://blog.csdn.net/weixin_42754896/article/details/126392939