java使用com.deepoove导出word文档

本文详细介绍了如何在Java项目中使用Maven引入poi-tl库,通过Controller处理GET请求并调用Service,服务端生成包含表格、图片和文本的Word文档,展示了数据绑定和模板渲染的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目代码

maven依赖

        <dependency>
			  <groupId>com.deepoove</groupId>
			  <artifactId>poi-tl</artifactId>
			  <version>1.10.5</version>
		 </dependency>

 controller

    @GetMapping("/word")
    public ResponseEntity<byte[]> getImageAsByteArray() throws IOException {
        byte[] bytes = reportService.exportWord();
        HttpHeaders headers = new HttpHeaders();
        String filename = "导出报告.docx";
        String encodedFilename = new String(filename.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
        headers.set("Content-Disposition", "attachment;filename=\""+encodedFilename +"\"");
        return new ResponseEntity<>(bytes, headers, HttpStatus.OK);
    }

​​​​service

@Override
    public byte[] exportWord() throws IOException {
        // 构造数据
        Map<String, Object> dataMap = Maps.newHashMap();
        // 描述
        dataMap.put("generalDescription", "这是报告生成的总体概述。请详情描述总体概述!");
        List<ReportTable> tableList = Lists.newArrayListWithCapacity(6);
        // 表格
        tableList.add(ReportTable.builder().no("1").category("一类").product("手机1").build());
        tableList.add(ReportTable.builder().no("2").category("二类").product("手机2").build());
        tableList.add(ReportTable.builder().no("3").category("三类").product("手机3").build());
        tableList.add(ReportTable.builder().no("4").category("四类").product("手机4").build());
        tableList.add(ReportTable.builder().no("5").category("五类").product("手机5").build());
        tableList.add(ReportTable.builder().no("6").category("六类").product("手机6").build());
        dataMap.put("table", tableList);
        // 图片
        try (InputStream inputStreamPicture = ReportServiceImpl.class.getClassLoader().getResourceAsStream("static/1.jpg");){
            dataMap.put("picture", Pictures.ofStream(inputStreamPicture).size(400, 400).create());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        // 绑定 render渲染表格等
        Configure config = Configure.builder().bind("table", new ReportTableRender()).build();
        // 文件写出
        byte[] bytes;
        FileOutputStream fos = null;
        FileInputStream fis = null;
        XWPFTemplate template = null;
        try (InputStream inputStream = ReportServiceImpl.class.getClassLoader().getResourceAsStream("templates/wordExportTemplate.docx")) {

            template = XWPFTemplate.compile(inputStream, config).render(dataMap);
            String tempDir = System.getProperty("java.io.tmpdir");
            File tempFile = File.createTempFile("temp", ".word", new File(tempDir));
            fos = new FileOutputStream(tempFile);
            template.writeAndClose(fos);
            fis = new FileInputStream(tempFile);
            bytes = new byte[Math.toIntExact(tempFile.length())];
            fis.read(bytes);
            fis.close();
            tempFile.delete();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            fos.close();
            fis.close();
            template.close();
        }
        return bytes;
    }

word模板

 导出效果

导出不同样式代码

  •  文本:在标题模板中 使用{{字段key}} 然后在生成的时候放到数据map中
     

            // 构造数据
            Map<String, Object> dataMap = Maps.newHashMap();
            // 描述
            dataMap.put("generalDescription", "这是报告生成的总体概述。请详情描述总体概述!");
  •  表格:首先是模板绑定也是{{字段key}} 然后放入数据map中,但是表格需要编写一个表格代理类去继承AbstractRenderPolicy。并且在渲染的时候绑定到template里面。如果有多个render可以bind多个
     

    // 表格
            tableList.add(ReportTable.builder().no("1").category("一类").product("手机1").build());
            tableList.add(ReportTable.builder().no("2").category("二类").product("手机2").build());
            tableList.add(ReportTable.builder().no("3").category("三类").product("手机3").build());
            tableList.add(ReportTable.builder().no("4").category("四类").product("手机4").build());
            tableList.add(ReportTable.builder().no("5").category("五类").product("手机5").build());
            tableList.add(ReportTable.builder().no("6").category("六类").product("手机6").build());
            dataMap.put("table", tableList);
            // 绑定 render渲染表格等
            Configure config = Configure.builder().bind("table", new ReportTableRender()).build();
    
    // 渲染时要绑定
     template = XWPFTemplate.compile(inputStream, config).render(dataMap);
    表格代理类
    package com.example.boot.report.render;
    
    import cn.hutool.core.collection.CollUtil;
    import com.deepoove.poi.data.style.BorderStyle;
    import com.deepoove.poi.policy.AbstractRenderPolicy;
    import com.deepoove.poi.render.RenderContext;
    import com.deepoove.poi.util.TableTools;
    import com.deepoove.poi.util.UnitUtils;
    import com.deepoove.poi.xwpf.BodyContainer;
    import com.deepoove.poi.xwpf.BodyContainerFactory;
    import com.example.boot.report.model.ReportTable;
    import org.apache.poi.xwpf.usermodel.*;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    @Component
    public class ReportTableRender extends AbstractRenderPolicy<List<ReportTable>> {
    
        private static final int COL_NUM = 3;
        private static final float TABLE_WIDTH = 14.49f;
        private static final String[] COL_TITLE = {"序号", "类别", "产品"};
    
        @Override
        protected void afterRender(RenderContext<List<ReportTable>> context) {
            // 清空标签
            clearPlaceholder(context, true);
        }
    
        @Override
        public void doRender(RenderContext<List<ReportTable>> context) throws Exception {
            XWPFRun run = context.getRun();
            List<ReportTable> thing = context.getThing();
            BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
            if (CollUtil.isEmpty(thing)) {
                return;
            }
            insertTable(run, bodyContainer, thing);
        }
    
        private static void insertTable(XWPFRun run, BodyContainer bodyContainer, List<ReportTable> dto) {
            int row = dto.size() + 1;
            // 插入表格
            XWPFTable table = bodyContainer.insertNewTable(run, row, COL_NUM);
            // 表格宽度
            TableTools.setWidth(table, UnitUtils.cm2Twips(TABLE_WIDTH) + "", null);
            // 边框和样式
            TableTools.borderTable(table, BorderStyle.DEFAULT);
            // 列标题编辑
            XWPFTableRow firstRow = table.getRow(0);
            firstRow.setHeight(0);
            List<XWPFTableCell> firstRowTableCells = firstRow.getTableCells();
            for (int i = 0; i < firstRowTableCells.size(); i++) {
                XWPFTableCell cell = firstRowTableCells.get(i);
                if (i == 0) {
                    cell.setWidth("20%");
                }
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                cell.setColor("D9D9D9");
                XWPFParagraph paragraph = cell.getParagraphs().get(0);
                paragraph.setAlignment(ParagraphAlignment.CENTER);
                XWPFRun paraRun = paragraph.createRun();
                paraRun.setText(COL_TITLE[i]);
                paraRun.setFontSize(10);
                paraRun.setBold(true);
            }
            // 数据区域赋值
            List<XWPFTableRow> rows = table.getRows();
            for (int i = 0; i < dto.size(); i++) {
                ReportTable tableDto = dto.get(i);
                XWPFTableRow tableRow = rows.get(i + 1);
                // 第一列
                XWPFTableCell cell = tableRow.getCell(0);
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                XWPFParagraph paragraph = cell.getParagraphs().get(0);
                paragraph.setAlignment(ParagraphAlignment.CENTER);
                paragraph.createRun().setText(tableDto.getNo());
                // 第二列
                cell = tableRow.getCell(1);
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                paragraph = cell.getParagraphs().get(0);
                paragraph.setAlignment(ParagraphAlignment.CENTER);
                paragraph.createRun().setText(tableDto.getCategory());
                // 第三列
                cell = tableRow.getCell(2);
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                paragraph = cell.getParagraphs().get(0);
                paragraph.setAlignment(ParagraphAlignment.CENTER);
                paragraph.createRun().setText(tableDto.getProduct());
            }
        }
    
    
    }
    
  • 图片:需要加@符号 {{@picture}} 可以用图片流,url等
     

            try (InputStream inputStreamPicture = ReportServiceImpl.class.getClassLoader().getResourceAsStream("static/1.2.jpg");){
                dataMap.put("picture", Pictures.ofStream(inputStreamPicture).size(400, 400).create());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }

 官方文档

  官方文档 有各种标签的解释 特殊场景可以参考官网

官方文档链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值