springboot集成easypoi导出word换行处理过程

 更新时间:2025年08月16日 08:39:06   作者:涛哥是个大帅比  
Spring Boot集成Easypoi导出Word时,换行符\n失效显示为空格,解决方法包括生成段落或替换模板中\n为回车,同时需确保变量{{temp}}在Map中设为"  "(带空格空字符串),避免空指针或残留变量

项目场景

springboot集成easypoi导出word

<dependency>
	<groupId>cn.afterturn</groupId>
	<artifactId>easypoi-spring-boot-starter</artifactId>
	<version>4.4.0</version>
</dependency>

问题描述

spring boot集成easypoi导出word时,内容包含换行符\n,导出word时换行符失效,会将换行符\n识别为空格。

解决方案

第一种:生成段落的方式

示例代码:

import com.xinghuo.common.base.ActionResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Cleanup;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileOutputStream;

@RestController
@Api(tags = "测试")
@RequestMapping("/test")
public class TestController {

    @ApiOperation("导出Word")
    @GetMapping("/export")
    public ActionResult export() {
        exportWord();
        return ActionResult.success();
    }

    /**
     * 导出Word,支持换行
     */
    public void exportWord(){
        try{
            String content = "第一行\n第二行中文\n"+"第三行";

            @Cleanup XWPFDocument doc = new XWPFDocument();

            if(content != null && content.contains("\n")) {
                //设置换行
                String[] text = content.split("\n");
                for (int i = 0; i < text.length; i++) {
                    XWPFParagraph p = doc.createParagraph();
                    p.createRun().setText(text[i]);
                }
            }else{
                XWPFParagraph p = doc.createParagraph();
                p.createRun().setText(content);
            }

            String name = "测试换行内容.docx";
            String filePath = "F:"+ File.separator + name;
            @Cleanup FileOutputStream output = new FileOutputStream(filePath);
            doc.write(output);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

导出的word内容

第二种:替换模板的情况,换行符替换成回车

示例代码:

import cn.afterturn.easypoi.word.WordExportUtil;
import com.xinghuo.common.base.ActionResult;
import com.xinghuo.common.util.XSSEscape;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.Cleanup;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.File;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Api(tags = "测试")
@RequestMapping("/test")
public class Test1Controller {

    @ApiOperation("导出Word")
    @GetMapping("/export")
    public ActionResult export() {
        exportWordTemplate();
        return ActionResult.success();
    }

    /**
     * 导出Word替换模板,支持换行
     */
    public void exportWordTemplate(){
        try{
            String content = "第一行\n第二行中文\n"+"第三行";
            Map<String, Object> map = new HashMap<>();
            map.put("content",content);

            @Cleanup XWPFDocument doc = WordExportUtil.exportWord07("F:/export_template.docx", map);
            //文本换行
            addBreakInCell(doc.getParagraphs());

            String name = "测试换行内容-替换模板.docx";
            String filePath = "F:"+ File.separator + name;
            @Cleanup FileOutputStream output = new FileOutputStream(XSSEscape.escapePath(filePath));
            doc.write(output);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 文本换行
     */
    public static void addBreakInCell(List<XWPFParagraph> paragraphs) {
        for (XWPFParagraph p : paragraphs) {
            for (XWPFRun run : p.getRuns()) {//XWPFRun对象定义具有一组公共属性的文本区域
                if(run.getText(0)!= null && run.getText(0).contains("\n")) {
                    String[] lines = run.getText(0).split("\n");
                    if(lines.length > 0) {
                        run.setText(lines[0], 0); // set first line into XWPFRun
                        for(int i=1;i<lines.length;i++){
                            // add break and insert new text
                            run.addBreak();//中断
//                              run.addCarriageReturn();//回车符,但是不起作用
                            run.setText(lines[i]);
                        }
                    }
                }
            }
        }
    }
}

 其中export_template.docx文件是word模板,内容为:

导出的内容

导出的本地文件截图

总结

 注意:模板中有变量值{{temp}},参数Map里面对应的temp值是null或者"",导出的word就会变成抛空指针异常或者{{temp}}、其他带{{ 的形式,直接在Map中设置temp的值为" ",就可以导出空白到模板,注意是加了空格的字符串" "

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

相关文章

  • Feign使用@PathVariable方式

    Feign使用@PathVariable方式

    Feign使用@PathVariable注解在URL中插入变量,类似于SpringMVC的用法,通过示例展示了如何使用该注解,并在实际调用中替换占位符
    2024-11-11
  • Java使用JSONPath解析JSON完整内容详解

    Java使用JSONPath解析JSON完整内容详解

    这篇文章主要介绍了Java使用JSONPath解析JSON完整内容详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • JavaWeb开发之使用jQuery与Ajax实现动态联级菜单效果

    JavaWeb开发之使用jQuery与Ajax实现动态联级菜单效果

    这篇文章主要介绍了JavaWeb开发之使用jQuery与Ajax实现动态联级菜单效果的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-10-10
  • Java基础之自动装箱,注解操作示例

    Java基础之自动装箱,注解操作示例

    这篇文章主要介绍了Java基础之自动装箱,注解操作,结合实例形式分析了java拆箱、装箱、静态导入、注释等相关使用技巧,需要的朋友可以参考下
    2019-08-08
  • Java实现读写文件功能的代码分享

    Java实现读写文件功能的代码分享

    这篇文章主要为大家详细介绍了如何利用Java语言实现读写文件功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-08-08
  • Spring Boot读取resources目录文件方法详解

    Spring Boot读取resources目录文件方法详解

    这篇文章主要介绍了Spring Boot读取resources目录文件方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Java中valueOf和parseInt的区别详解

    Java中valueOf和parseInt的区别详解

    这篇文章主要介绍了Java中valueOf和parseInt的区别详解,在编程中,遇到类型转换,好像会经常用到 parseInt 和 valueOf,当然这里只拿 Integer 类型进行陈述,其他类型也是雷同的,需要的朋友可以参考下
    2024-01-01
  • MapTask阶段shuffle源码分析

    MapTask阶段shuffle源码分析

    今天小编就为大家分享一篇关于MapTask阶段shuffle源码分析,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Java搭建RabbitMq消息中间件过程详解

    Java搭建RabbitMq消息中间件过程详解

    这篇文章主要介绍了Java搭建RabbitMq消息中间件过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • 详解Java字节码编程之非常好用的javassist

    详解Java字节码编程之非常好用的javassist

    这篇文章主要介绍了详解Java字节码编程之非常好用的javassist,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04

最新评论