使用poi-tl模板引擎导出word文档

988 阅读3分钟

一 什么是poi-tl

poi-tl(poi template language)是Word模板引擎,使用Word模板和数据创建很棒的Word文档*。

poi-tl官网地址:deepoove.com/poi-tl/

上手入门这里我就不写了 兄弟们有兴趣可以自己对照官方文档去敲几行。直接进入正文

导入依赖

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.2</version>
</dependency>
<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>1.12.0</version>
</dependency>
  • 我这里导入的是5.2.2版本的poi,springboot版本是3.0这里是可以兼容的,但是springboot2.2.0或者其他低版本的springboot这里log4j依赖不兼容。可以像下面一样排除引入的log依赖*
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi</artifactId>
    <version>${poi.version}</version>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
        </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>${poi-ooxml.version}</version>
    <exclusions>
            <exclusion>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-api</artifactId>
            </exclusion>
            <exclusion>
                <groupId>org.apache.logging.log4j</groupId>
                <artifactId>log4j-core</artifactId>
            </exclusion>
    </exclusions>
</dependency>

<dependency>
    <groupId>com.deepoove</groupId>
    <artifactId>poi-tl</artifactId>
    <version>${poi-tl.version}</version>
</dependency>

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>${log4j-api.version}</version>
</dependency>

编写controller

package com.example.wordpoitldemo.controller;

import com.deepoove.poi.XWPFTemplate;
import com.example.wordpoitldemo.WordService;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;


/**
 * @author: xh
 * @date: 2023/11/15 9:48
 */
@Controller
@RequestMapping("/word")
public class WordController {

    @Resource
    private WordService wordService;

    @ApiOperation("Download Word")
    @GetMapping("download")
    public void wordDownload( HttpServletResponse response) {
        try {
            XWPFTemplate document =wordService.generateWordXWPFTemplate();
            String fileName="word文档导出.docx";
            response.reset();
            response.setContentType("text/html:charset=utf-8");
            String encodedFileName = URLEncoder.encode(fileName, "UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename="" + encodedFileName + """);
            OutputStream os = response.getOutputStream();
            document.write(os);
            os.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

编写service

package com.example.wordpoitldemo;

import cn.hutool.core.collection.CollectionUtil;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.*;
import com.example.wordpoitldemo.domain.WordModel;
import org.springframework.stereotype.Service;

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

/**
 * @author: xh
 * @date: 2023/11/15 10:14
 */
@Service
public class WordServiceImpl implements WordService{
    /**
     * 导出word模板
     * @return
     */
    @Override
    public XWPFTemplate generateWordXWPFTemplate() {
        //获取resources目录下的模板文件
        InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("word/template.docx");
        // 在这里使用file进行操作,例如读取文件内容
        XWPFTemplate template = XWPFTemplate.compile(inputStream);
        WordModel wordModel=new WordModel();
        wordModel.setName("张三");
        wordModel.setAge("18");
        wordModel.setSex("男");
        wordModel.setHobbies("唱歌和打篮球");

        //趋势图
        String[] abscissaData={"01", "02","03","04","05","06","07","08","09","10",
                "11","12","13","14","15","16","17","18","19","20",
                "21","22","23","24","25","26","27","28","29","30"};
        Double[] chargingCasesOrdinateData={
                159309.69, 164566.38,156819.87,148378.92,123710.59,176014.0,154682.63,154635.78,154635.78,154635.78,
                159309.69, 164566.38,156819.87,148378.92,123710.59,176014.0,154682.63,154635.78,154635.78,154635.78,
                159309.69, 164566.38,156819.87,148378.92,123710.59,176014.0,154682.63,154635.78,154635.78,154635.78,
        };
        wordModel.setTrendChart(creatLineChart("当月收入折线图","日收入(RMB)",abscissaData,chargingCasesOrdinateData));

        //表格
        //科室开单排名(前十科室)
        RowRenderData tenDepartmentsTableHead= Rows.of("排序", "科室名称","开单量").textColor("FFFFFF")
                .bgColor("4472C4").center().create();
        //创建表格list
        List<RowRenderData> tenDepartmentsRowList=new ArrayList<>();
        int order=1;
        List<Map<String, Object>> tenDepartmentsTableDate = getTenDepartmentsTableDate();
        if (CollectionUtil.isNotEmpty(tenDepartmentsTableDate)){
            for (Map<String, Object> tenDepartments : tenDepartmentsTableDate) {
                tenDepartmentsRowList.add(Rows.create(order+"",tenDepartments.get("departmentName")+"",tenDepartments.get("boldQuantity")+""));
                order++;
            }
        }
        wordModel.setTable(createTable(tenDepartmentsTableHead,tenDepartmentsRowList));
        return template.render(wordModel);
    }

    /**
     * 生成折线图
     *
     * @param title        图表标题
     * @param name         当前系列名称
     * @param abscissaData 横坐标数据
     * @param ordinateData 纵坐标数据
     * @return
     */
    private ChartMultiSeriesRenderData creatLineChart(String title, String name, String[] abscissaData, Double[] ordinateData) {
        ChartMultiSeriesRenderData chart = Charts
                .ofLine3D(title, abscissaData)
                .addSeries(name, ordinateData)
                .create();
        return chart;
    }

    /**
     * 获取科室开单排名前十的数据
     * @return
     */
    private List<Map<String,Object>> getTenDepartmentsTableDate() {
        List<Map<String,Object>> tenDepartmentsTableDate=new ArrayList<>();
        Map<String,Object> map=new HashMap<>();
        map.put("departmentName","测试1");
        map.put("boldQuantity","50");
        tenDepartmentsTableDate.add(map);

        Map<String,Object> map1=new HashMap<>();
        map1.put("departmentName","测试2");
        map1.put("boldQuantity","500");
        tenDepartmentsTableDate.add(map1);
        return tenDepartmentsTableDate;
    }

    /**
     *
     * @param headRow 表头
     * @param tableData  表格数据
     * @return
     */
    private TableRenderData createTable(RowRenderData headRow, List<RowRenderData> tableData) {
        // 构造表格渲染数据  科室开单排名(前十科室)
        TableRenderData table = Tables.of(headRow).center().create();
        // 准备表格数据
        if (CollectionUtil.isNotEmpty(tableData)){
            for (RowRenderData  renderData : tableData) {
                table.addRow(renderData);
            }
        }
        return table;
    }
}

model类

package com.example.wordpoitldemo.domain;

import com.deepoove.poi.data.ChartMultiSeriesRenderData;
import com.deepoove.poi.data.TableRenderData;
import lombok.Data;

/**
 * @author: xh
 * @date: 2023/11/15 10:20
 * word变量属性
 */
@Data
public class WordModel {
    /**
     * 单变量属性
     */
    private String name;
    private String age;
    private String sex;
    private String Hobbies;

    /**
     * 折线图
     */
    private ChartMultiSeriesRenderData TrendChart;

    /**
     * 表格
     */
    private TableRenderData table;

}

word模板设置

word模板.jpg 普通变量用{{}},表格变量用{{#}},折线图需要设置名称 我是用的wps 如下

1700016713124.jpg

到这里基本的一些讲解就结束了 最后看一下效果吧

导出1.jpg

导出2.jpg

这里只挑选了几种常见的word导出使用样例来展示,需要更多其他导出样例的 可以比照参考官方文档。

gitee:gitee.com/xianghaoddd…