当前位置: 首页 > news >正文

告别XML模板的繁琐!Word文档导出,easy!

word模板导出

最近项目中有个功能,导出月报,发现同事使用了docx格式模板,感觉比之前转成xml的简单多了,这边记录下使用方法。
xml方式导出word,模板太复杂了

资料

poi-tl

一个基于Apache POI的Word模板引擎,也是一个免费开源的Java类库,你可以非常方便的加入到你的项目中,并且拥有着让人喜悦的特性


官方文档地址 ,还是很详细的,有多个场景的示例

如何使用

  • 必要的标签知识
    • 文字

    {{var}}

    • 数据模型:
     String :文本
    
     TextRenderData :有样式的文本
    
     HyperlinkTextRenderData :超链接和锚点文本
    
      Object :调用 toString() 方法转化为文本
    
    • 图片

      图片标签以@开始:{{@var}}

      • 数据模型:
      String :图片url或者本地路径,默认使用图片自身尺寸
      
      ByteArrayPictureRenderData
      
      FilePictureRenderData
      
      UrlPictureRenderData
      
    • 表格行循环

      配合插件-LoopRowTableRenderPolicy

    • 图标

      • 多系列图表指的是条形图(3D条形图)、柱形图(3D柱形图)、面积图(3D面积图)、折线图(3D折线图)、雷达图、散点图等

      数据模型ChartMultiSeriesRenderData

      • 单系列图表指的是饼图(3D饼图)、圆环图等。
  • 引入依赖

        <dependency>
            <groupId>com.deepoove</groupId>
            <artifactId>poi-tl</artifactId>
            <version>1.12.2</version>
        </dependency>
  • 简单的demo

 
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.config.ConfigureBuilder;
import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.Charts;
import com.deepoove.poi.data.PictureRenderData;
import com.deepoove.poi.data.Pictures;
import com.deepoove.poi.plugin.table.LoopRowTableRenderPolicy;
import com.deepoove.poi.policy.RenderPolicy;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @program: learn_summary
 * @description:
 * @author: zzg@xnj
 * @create: 2025-03-10 15:58
 **/
@Service
public class WordService {


    public  void makeWord(){
        HashMap<String, Object> dates = new HashMap<>();
        //字符串
        String wenzi="这个是文字";
        dates.put("wenzi", wenzi);

        //单个图片
//        dates.put("pic", Pictures.ofUrl( "https://img.tukuppt.com/ad_preview/00/10/23/5c992ae114e20.jpg!/fw/980").size(200, 200).create());
        dates.put("pic", "https://img.tukuppt.com/ad_preview/00/10/23/5c992ae114e20.jpg!/fw/980");

        //多个图片
        ArrayList<String> urls = new ArrayList<>();
        urls.add("https://pic.52112.com/2020/04/13/JPG-200413_328/gCaPae4zjp_small.jpg");
        urls.add("https://img.tukuppt.com/ad_preview/00/10/23/5c992ae114e20.jpg!/fw/980");
        dates.put("pictures",  createPictureList("picture",urls,200,200));

        //插件使用
        HashMap<String, RenderPolicy> policyHashMap = new HashMap<>();
        //表格 使用LoopRowTableRenderPolicy
        LoopRowTableRenderPolicy loopRowTableRenderPolicy = new LoopRowTableRenderPolicy();
        ArrayList<HashMap<String, String>> tables = new ArrayList<>();
        HashMap<String, String> map = new HashMap<>();
        map.put("name", "大豆");
        map.put("count", "18");
        map.put("price", "100");
        tables.add(map);

        map = new HashMap<>();
        map.put("name", "黄豆");
        map.put("count", "38");
        map.put("price", "110");
        tables.add(map);

        dates.put("goods",tables);
        policyHashMap.put("goods", loopRowTableRenderPolicy);


        //图表
        ChartMultiSeriesRenderData chart = Charts
                .ofMultiSeries("商品售卖情况", new String[] { "大豆", "黄豆" })
                .addSeries("北京", new Double[] { 15.0, 6.0 })
                .addSeries("上海", new Double[] { 223.0, 119.0 })
                .create();

        dates.put("barChart", chart);
        try {
            WordService.createWordOfList("E:\\data\\text2.doc",new FileInputStream("E:\\data\\word_template.docx"),dates,policyHashMap);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
    private List<Map<String, PictureRenderData>> createPictureList(String mapKey,List<String> urls,int width, int height) {
        List<Map<String, PictureRenderData>> list = new ArrayList<>();
        for (String url : urls) {
            list.add(createPictureMap(mapKey,url, width, height));
        }

        return list;
    }

    private Map<String, PictureRenderData> createPictureMap(String mapKey,String imgUrl, int width, int height) {
        Map<String, PictureRenderData> map = new HashMap<>();
        map.put(mapKey, Pictures.ofUrl( imgUrl).size(width, height).create());
        return map;
    }


    /**
     * 创建word文档
     * @param outputPath 输出路径
     * @param templatePath 模板路径
     * @param data 数据
     * @param placeholderPolicy 占位标签使用插件
     * @return
     */
    public static boolean createWordOfList(String outputPath, InputStream templatePath, Map<String, Object> data, Map<String, RenderPolicy> placeholderPolicy)   {
        try {
            FileOutputStream out = new FileOutputStream(outputPath);
            BufferedOutputStream bos = new BufferedOutputStream(out);
            // 使用Configure.ConfigureBuilder而不是Builder
            ConfigureBuilder builder = Configure.builder();

            // 动态绑定插件
            if (placeholderPolicy!=null) {
                for (Map.Entry<String, RenderPolicy> entry : placeholderPolicy.entrySet()) {
                    builder.bind(entry.getKey(), entry.getValue());
                }
            }

            Configure configure = builder.build();
            // 读取模板并渲染数据
            XWPFTemplate template = XWPFTemplate.compile(templatePath, configure).render(data);
            try {
                template.write(bos);
                template.close();
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            out.flush();
            bos.flush();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

}

  • 模板
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

相关文章:

  • 穷举vs暴搜vs深搜vs回溯vs剪枝刷题 + 总结
  • 第5课 树莓派的Python IDE—Thonny
  • Gin(后端)和 Vue3(前端)中实现 Server-Sent Events(SSE)推送
  • DeepSeek + Excel:数据处理专家 具体步骤
  • 蓝桥杯备赛-二分-技能升级
  • C语言输入与输出:从零掌握数据的“对话”
  • STC89C52单片机学习——第20节: [8-2]串口向电脑发送数据电脑通过串口控制LED
  • MyBatis源码分析の配置文件解析
  • 创建postgis数据库
  • 【matlab例程】三维下的TDOA定位和EKF轨迹滤波例程,TDOA的锚点数量可自定义(订阅专栏后可获得完整代码)
  • 每日一题---腐烂的苹果(广度优先搜索)
  • Java常见的几种内存溢出及解决方法
  • MATLAB中events函数用法
  • 函数的引用/函数的默认参数/函数的占位参数/函数重载
  • 面试vue2开发时怎么加载编译速度(webpack)
  • 用C++新建快捷方式
  • 第5章 构造、析构、拷贝语义学3:对象复制语意学
  • 高频面试题(含笔试高频算法整理)基本总结回顾24
  • 【ElasticSearch】学习笔记
  • 零基础上手Python数据分析 (3):Python核心语法快速入门 (下) - 程序流程控制、函数与模块
  • 人民日报评论员:焕发风雨无阻、奋勇前行的精气神
  • 范宇任上海宝山区副区长
  • 中国海警位中国黄岩岛领海及周边区域执法巡查
  • 铁路上海站今日预计发送旅客65.8万人次,同比增长超16%
  • 临港迎来鸿蒙智行“尚界”整车及电池配套项目,首款车型今秋上市
  • 西夏文残碑等文物来沪,见证一段神秘灿烂的历史