Java 使用 poi 生成简单 word 文档并导出

目录

问题

如何解决

代码

pom

doc操作类

使用示例


问题

项目中需要将业务数据制成表格并插入word文档中,同时还需向word文档中插入图片,最后导出word文档。

如何解决

基于 poi 写了一个通用的doc操作类,支持插入表格和图片,最后导出。

代码

pom

        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi</artifactId>
            <version>5.2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>poi-ooxml</artifactId>
            <version>5.2.5</version>
        </dependency>

doc操作类

public class PoiDocDo {

    XWPFDocument xDoc;
    String name;

    public static PoiDocBuilder builder() { return new PoiDocBuilder();}

    public PoiDocDo(PoiDocBuilder builder) {
        xDoc = new XWPFDocument();
        name = builder.name;
    }

    public static class PoiDocBuilder {
        String name = "default";
        public PoiDocDo build() {
            return new PoiDocDo(this);
        }

        public PoiDocBuilder name(String name) {
            this.name = name;
            return this;
        }
    }

    public PoiDocDo insertParagraph(String text) {
        XWPFParagraph xPara = xDoc.createParagraph();
        xPara.setAlignment(ParagraphAlignment.LEFT);
        XWPFRun run = xPara.createRun();
        run.setFontSize(20);
        run.setText(text);
        run.addCarriageReturn();

        return this;
    }

    /**
     * 往文档中插入表格
     *
     * @param columns 列头
     * @param rows 内容行
     */
    public PoiDocDo insertTable(List<Map<String, String>> columns,
                                List<Map<String, Object>> rows) {
        XWPFTable xTable = xDoc.createTable(rows.size() + 1, columns.size());
        centerTableContent(xTable, columns.size());

        XWPFTableRow columnNameRow = xTable.getRow(0);
        List<String> columnFields = new ArrayList<>();
        Map<String, String> columnMap;
        for (int i = 0; i < columns.size(); i++) {
            columnMap = columns.get(i);
            columnNameRow.getCell(i).setText(columnMap.get("name"));
            columnFields.add(columnMap.get("field"));
        }
        XWPFTableRow contentRow;
        Map<String, Object> rowMap;
        for (int i = 1; i <= rows.size(); i++) {
            contentRow = xTable.getRow(i);
            rowMap = rows.get(i - 1);
            for (int j = 0; j < columnFields.size(); j++) {
                contentRow.getCell(j).setText(
                        rowMap.getOrDefault(columnFields.get(j), "").toString());
            }
        }
        return this;
    }

    /**
     * 表格内容居中,此方法为依次居中每个表格的内容
     *
     * @param xTable 表格
     */
    private void centerTableContent(XWPFTable xTable, int numberOfColumns) {
        for (int i = 0; i < xTable.getNumberOfRows(); i++) {
            for (int j = 0; j < numberOfColumns; j++) {
                XWPFTableCell cell = xTable.getRow(i).getCell(j);
                CTTc cttc = cell.getCTTc();
                CTTcPr ctPr = cttc.addNewTcPr();
                ctPr.addNewVAlign().setVal(STVerticalJc.CENTER);
                cttc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
            }
        }
    }

    public PoiDocDo insertImage(List<Map<String, String>> imageInfoList) {
        XWPFParagraph xPara;
        XWPFRun run;
        String imageName, imageData;
        byte[] bytes;

        for (Map<String, String> imageInfo : imageInfoList) {
            imageName = imageInfo.get("imageName");
            imageData = imageInfo.get("imageData");
            bytes = Base64.getDecoder().decode(imageData);

            xPara = xDoc.createParagraph();
            xPara.setAlignment(ParagraphAlignment.LEFT);
            run = xPara.createRun();
            run.setFontSize(20);
            run.setText(imageName);
            run.addCarriageReturn();
            try {
                run.addPicture(new ByteArrayInputStream(bytes), XWPFDocument.PICTURE_TYPE_JPEG,
                        imageName, Units.toEMU(414), Units.toEMU(284));
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return this;
    }

    public void export(OutputStream outputStream) {
        try (OutputStream os = outputStream) {
            xDoc.write(os);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void export(String desktopPath) {
        String docName = (desktopPath + "\\" + name).replaceAll("\\\\+", "/");
        try(OutputStream os = Files.newOutputStream(Paths.get(String.format("%s.docx", docName)))) {
            xDoc.write(os);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

使用示例

class PoiDocDoTest {

    @Test
    public void test() throws IOException {
        PoiDocDo domainObj = PoiDocDo.builder().name("myDoc").build();

        List<Map<String, String>> images = new ArrayList<>();
        Map<String, String> imageMap = new HashMap<>();
        images.add(imageMap);
        imageMap.put("imageName", "test");
        InputStream inputStream = Files.newInputStream(Paths.get("C:\\Users\\XXX\\Desktop\\XXX.png"));
        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
        int nRead;
        byte[] data = new byte[16384];
        while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
            buffer.write(data, 0, nRead);
        }
        imageMap.put("imageData", Base64.getEncoder().encodeToString(buffer.toByteArray()));

        List<Map<String, String>> columns = new ArrayList<>();
        Map<String, String> column = new HashMap<>();
        columns.add(column);
        column.put("name", "colum1");
        column.put("field", "field1");

        List<Map<String, Object>> rows = new ArrayList<>();
        Map<String, Object> row = new HashMap<>();
        rows.add(row);
        row.put("field1", "abc");

        domainObj.insertParagraph("This is a paragraph")
                .insertParagraph("picture under me")
                .insertImage(images)
                .insertTable(columns, rows)
                .export("C:\\Users\\XXX\\Desktop");
    }
}

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值