poi-tl详细教程将一整个页面word化

将一整个页面类似大屏的数据模块,全部输出成word,涉及到雷达图,折线图,表单,饼图等多种数据结构转word

poi-tl是一个特别好用的工具,你想要绘画什么图形,只要你按他的对应结构封装返回,poi会自动帮你绘画图表,填充数据,

前面都是很基础的,不想看的可直接往下拉,下面有图形

/**
 * ReportToWordUtil
 *生成报告Word工具
 * @author Zhang Zhi Hao
 * 2022/9/07
 */
@Slf4j
@Service
public class ReportToWordUtil {
    @Autowired
    private IxxxService xxxService;//你的service业务类
    private String profile;//你项目保存的路径 每个项目不一样,小伙伴自己悟
    /**
     * 获取路径 入参根据你们实际项目来,ruoyi框架的话可以套用SysConfig 
     * @param sysConfig
     */
    @Autowired
    public void setProfile(SysConfig sysConfig){
        
        profile = SysConfig.getProfile()+relatePath;
    }
    private String relatePath = "file/";//业务需求加入的前缀 可不加
    /**
     * 根据前端传的条件,生成不一样的页面数据 
     * @param req
     * @return
     */
    public AjaxResult report(xxxxReq req,HttpServletResponse response){
        //模板放在resouce/template目录下,这要不会就自己悟
        ClassPathResource classPathResource = new ClassPathResource("./template/reportTimeType.docx");//从项目中获取你的模板
        
        //获取数据 
        Map <String, Object> datas = getData(req);
        //3.创建XWPFTemplate对象,并设置读取模板路径和要渲染的数据
        XWPFTemplate template = XWPFTemplate.compile(classPathResource.getStream()).render(datas);
        //获取路径  
        HashMap <String, String> pathMap = makePath();
        //输出
        FileOutputStream absolutePathFileOutputStream = null;
        try {
            absolutePathFileOutputStream = new FileOutputStream(pathMap.get("absolutePath"));
            template.writeAndClose(absolutePathFileOutputStream);
            absolutePathFileOutputStream.close();
            FileUtils.writeBytes(pathMap.get("absolutePath"), response.getOutputStream());
        } catch (Exception e) {
            log.info("获取绝对路径错误");
            e.printStackTrace();
            return AjaxResult.error("生成失败");
        }

        return AjaxResult.success();
    }
    
    private HashMap <String, String> makePath() {
        // 存储的目录  拼接你想要的目录名字,
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("report/")
                .append("xxxx").append(".docx");
        // 文件相对路径
        String pathFile = stringBuilder.toString();
        // 组合成文件路径
        File file = new File(profile + pathFile);
        // 获取文件的所在目录路径
        File parent = new File(file.getParent());
        // 没有该目录就创建
        if (!parent.exists()) {
            parent.mkdirs();
        }
        HashMap<String, String> stringStringHashMap = new HashMap<>();
        // 绝对路径
        stringStringHashMap.put("absolutePath", file.toString());
        // 相对路径
        stringStringHashMap.put("relativePath", pathFile);

        return stringStringHashMap;
    }

}

上面是一些基础,都有对应的注释可看,根据实际需求去做即可,下面是对应图行的方法,先上我word模板,然后再贴每个图形的代码和注释。

 在word中注入数据,如{{xxxx}}这是直接注入数据,不转任何结构,{{#xxx}}即转换为表格形式

时间格式记得转换一下再填充 xxxx年xx月xx日,我这没做转换。接下来贴代码更清晰

/**
     * 构建word所需要的数据模型
     * @return
     */
    private Map<String, Object> getData(xxxxReq req){
        Map <String, Object> datas = new HashMap <>();
        String date = String.valueOf(new Date());
        datas.put("reportTimeType",date);
        //获取准备填充的数据
        List <xxxVo> records= xxxService.xxxListWithOutPage(req);
//全局异常处理
        if (records.size()<=0) {
            throw new GlobalException("当前页面没有可以生成的数据");
        }
//表格数据准备  表结构都是用RowRenderData结构
        RowRenderData[] rowRenderData = new RowRenderData[records.size() + 1];
//第0行使我们的表头,可以用字符串写死,也可以用你数据中的字段名称转中文,看需求
        rowRenderData[0] = Rows.of("xxx", "xxx", "xxx", "xxx","xxx","xxx","xxx","xxx").center().bgColor("8DB4E3").create();
        //赋值
        for (int i = 0; i <records.size(); i++) {
            rowRenderData[i+1] = Rows.create(records.get(i).getPlanNo(),records.get(i).getWorkLiablerName(),
                    String.valueOf(records.get(i).getPlanBeginTime()),String.valueOf(records.get(i).getPlanFinishTime()),
                    records.get(i).getConOperRiskValue(),records.get(i).getBenchmarkRiskValue(),
                    records.get(i).getConstructionUnitName(),records.get(i).getWorkTeamName()
            );
        }
//创建结构
        TableRenderData tableRenderData = Tables.create(rowRenderData);
//放入data中,"table",对应word中的{{#table}}一一对应,放入data后进行绘画
        datas.put("table",tableRenderData);

 接下来是复杂图形

1.雷达图

在你的模板中添加雷达图,点设置, 文本选项文本框,可选文字,填写你代码中对应的key{{xxx}}

不是表单,直接填入数据,poi会帮你转换,上代码结构

 xxxVo xxx =xxxService.getxxxByReq(req);
//对象判空方法
        if (Optional.ofNullable(xxx ).isPresent()) {
//ChartMultiSeriesRenderData  雷达图,折线图,多树状图都可以用这个结构,ofMultiSeries第一个参数对应你的标题,和你图中下面一排的数据
//addSeries,在对应你不同的系列数据,要一一对应上,在折现图中会有一个lineSeries方法,即划线数据
            ChartMultiSeriesRenderData  chartMultis = Charts.
                    ofMultiSeries("xxxxxx",
                            new String[]{"xxx", "xxx", "xxx", "xxx", "xxx"})
                    .addSeries("违章指数", new Integer[]{
                            xxx.getXxx(),
                            xxx.getXxxx(),
                            xxx.getXxxx(),
                            xxx.getXxx(),
                            xxx.getXxxxxx()})
                    .create();
            datas.put("violationIndex",chartMultis);
        }

 

效果图,折现图一样,模板画上折线图,贴参数,就不上了,直接上代码转结构把

 //转字符串数组 自己写方法调你需要填充的数据,这里直接给结构,折线图
//addLineSeries 第一个参数为你折线数据的key,可以理解为标签,系列
            ChartMultiSeriesRenderData comb = Charts.ofComboSeries("终端数量",stringList.toArray(new String[stringList.size()]))
                    .addBarSeries("xxx",integers.toArray(new Integer[integers.size()]))
                    .addLineSeries("xxx",doubles.toArray(new Double[doubles.size()]))
                    .create();
            datas.put("numberOfTerminals",comb);

 按poi的结构来,封装对应的数据进去,大同小异,各位大佬,新人刚刚入坑,有不好的地方手下留情,欢迎建议和留言,后续可能会考虑封装一下,针对每个图形单独抽取,还有个饼图的没发出来,大同小异,觉得有需要的同学可以留言

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值