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

 更新时间:2024年06月17日 09:29:52   作者:编程经验分享  
这篇文章主要介绍了Java如何使用poi生成简单word文档并导出问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

问题

项目中需要将业务数据制成表格并插入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");
    }
}

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Java中的对象流总结(必看篇)

    Java中的对象流总结(必看篇)

    下面小编就为大家带来一篇Java中的对象流总结(必看篇)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-04-04
  • SpringBoot的两种启动方式原理解析(配置方案)

    SpringBoot的两种启动方式原理解析(配置方案)

    本文介绍了Spring Boot中两种启动方式,使用内置Tomcat启动和使用外置Tomcat部署,在使用内置Tomcat启动时,可以通过IDEA的main函数启动,也可以使用nohup命令在后台运行,这篇文章主要介绍了SpringBoot的两种启动方式原理 ,需要的朋友可以参考下
    2025-01-01
  • 在springboot中使用AOP进行全局日志记录

    在springboot中使用AOP进行全局日志记录

    这篇文章主要介绍就在springboot中使用AOP进行全局日志记录,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Java递归实现菜单树的方法详解

    Java递归实现菜单树的方法详解

    这篇文章主要为大家详细介绍了Java递归实现菜单树的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • MybatisPlus自定义Sql实现多表查询的示例

    MybatisPlus自定义Sql实现多表查询的示例

    这篇文章主要介绍了MybatisPlus自定义Sql实现多表查询的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • java中ConcurrentHashMap的读操作为什么不需要加锁

    java中ConcurrentHashMap的读操作为什么不需要加锁

    ConcurrentHashMap完全允许多个读操作并发进行,读操作并不需要加锁。所以下面这篇文章主要给大家介绍了关于java中ConcurrentHashMap的读操作为什么不需要加锁的相关资料,需要的朋友可以参考下
    2018-10-10
  • Java 实战范例之员工管理系统的实现

    Java 实战范例之员工管理系统的实现

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+vue+Springboot+ssm+mysql+maven+redis实现一个前后端分离的员工管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • 详解Java反射各种应用

    详解Java反射各种应用

    Java除了给我们提供在编译期得到类的各种信息之外,还通过反射让我们可以在运行期间得到类的各种信息。通过反射获取类的信息,得到类的信息之后,就可以获取很多相关内容。下面跟着小编一起来看下吧
    2017-01-01
  • java 使用JDBC构建简单的数据访问层实例详解

    java 使用JDBC构建简单的数据访问层实例详解

    以下是如何使用JDBC构建一个数据访问层,包括数据转换(将从数据库中查询的数据封装到对应的对象中……),数据库的建立,以及如何连接到数据库,需要的朋友可以参考下
    2016-11-11
  • Java手写简易版HashMap的使用(存储+查找)

    Java手写简易版HashMap的使用(存储+查找)

    这篇文章主要介绍了Java手写简易版HashMap的使用(存储+查找),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01

最新评论