easypoi导出word修改样式

本文介绍使用Easypoi导出Word文档时如何动态修改样式,特别是针对遍历填充的数据如何统一设置字体样式,如仿宋小四等,并提供实现代码。

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

                                                easypoi导出word修改样式

 

          easyPoi是 POI 工具类,Excel的快速导入导出,Excel模板导出,Word模板导出,可以仅仅5行代码就可以完成Excel的导入导出,修改导出格式简单粗暴,快速有效(摘自码云https://gitee.com/lemur/easypoi

        对于简单的导出,只需要对象封装map里面,在模板上用{{}}表达式写出对象,就可以导出了,网上有很多教程,这里就不在赘述了。本文主要是讲如何通过Java代码来动态的修改样式。一般我们的word模板字段不是很多,只需要封装对象就可以了

  HashMap<String, Object> map = new HashMap<String, Object>(4);
        //单个对象
        map.put("id", "1231313");
        map.put("name", "A某某");
        map.put("age", "34");
        map.put("phone", "18787674333");
        return map;

//easypoi通用导出word
  XWPFDocument s = WordExportUtil.exportWord07("/" + templateFile, map);

 导出的模板如下,这样模板字段是什么样式的,比如加粗倾斜宋体等,导出的结果就是什么样式的,只需要调整模板的样式就可以了。

对于导出内容比较多的word,通常可以利用list进行遍历导出,这样如果修改其中某些字段的样式,那就变得比较复杂了,在网上找了很久,发现这方面的资料还是比较少的,而且都没有达到理想中的效果。

经过一天的摸索与努力,终于实现了修改所有遍历的字段的样式,这样后来者如果再遇到这类问题,就不需要花费过多的时间和精力了,也算是发扬下当代互联网人的精神吧。

       word导出要求遍历的字段全部采用仿宋,小四字体,网上很容易搜到了一种方法,经过整理下过程如下

获取对象

调用easypoi会返回一个XWPFDocument的对象,获取表table,行row,空格子cell,每一个段落paragraph,然后获取run对象就可以修改样式了。

                 //获取table
                XWPFTable sourceTable = s.getTables().get(0);

                 //获取row
                XWPFTableRow sourceRow = sourceTable.getRow(3);
            
                 //获取cell
                XWPFTableCell sourceCell = sourceRow.getCell(0);
              
                 //获取每一行
                XWPFParagraph sourcePara = sourceCell.getParagraphs().get(0);
                 //获取每一个run对象 
                XWPFRun sourceRun = sourcePara.getRuns().get(0);
                 // 设置列宽
                sourceCell .setWidth(String.valueOf(sourceRow.getCell(0).getWidth()));
                sourceCell .setWidthType(sourceRow.getCell(0).getWidthType());
                // 设置垂直对齐方式
                sourceCell .setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                 // 设置水平对齐方式
                sourcePara .setAlignment(ParagraphAlignment.CENTER);
                 //修改字体的样式大小,内容,颜色等等
                sourceRun.setFontSize(12);
                sourceRun.setBold(true);
                sourceRun.setText("舜发于畎亩之中");
                sourceRun.setCapitalized(true);
                sourceRun.setColor("BED4F1");
                sourceRun.setDoubleStrikethrough(true);
                sourceRun.setEmbossed(true);
                sourceRun.setFontFamily("仿宋", XWPFRun.FontCharRange.cs);
                sourceRun.setFontSize(12);
                sourceRun.setImprinted(true);
                sourceRun.setItalic(true);
                sourceRun.setShadow(true);
                sourceRun.setStrikeThrough(true);
             
              

代码只是修改某一个空格子的样式,如果可以,那我就循环判断修改任何一个空格子了。我以为这样就可以了,但也只是我以为,也不会花费一天之久了,其中多少次想放弃呢。

       上述代码的确可以去修改遍历list字体的大小,颜色,倾斜,加粗等。顺便说下,仿宋小四,是12号。但是不可以修改为仿宋的字体格式。接下来就是踩坑排错的过程了。首先 sourceRun.setFontFamily("仿宋");这个方法可以单个参数“宋体”,也可以两个参数 cellRun.setFontFamily("仿宋", XWPFRun.FontCharRange.eastAsia);试了下,也不行。第二个参数是个枚举类,每种类型都试了也不行。全都写上也不行。放弃之心+20。无奈,只能继续百度了。

       网上又看到一个动态修改word字体样式的内容,也是差不多再深挖四层,就不贴思维导图了,看下代码就知道了,大致代码如下

 //获取fonts对象
 CTFonts tmpFonts = sourceRun.getCTR().getRPr().getRFonts();
 //设置字体
 tmpFonts.setEastAsia("仿宋");

当然了,试了下还是不行,放弃之心+20,老规矩吧这几个有的全部设置为仿宋了

                tmpFonts.setAscii("仿宋");
                tmpFonts.setEastAsia("仿宋");
                tmpFonts.setHAnsi("仿宋");
                tmpFonts.setCs("仿宋");

还是不行,放弃之心+20,然后看到了 asciiTheme 等theme,这个是不是也要设置为仿宋呢?

<w:rFonts w:ascii="仿宋" w:hAnsi="仿宋" w:cs="仿宋" w:eastAsia="仿宋" w:asciiTheme="" w:cstheme="" w:eastAsiaTheme="" w:hAnsiTheme=""/>

试了下代码只有 tmpFonts0.isSetAsciiTheme();和 tmpFonts.unsetAsciiTheme();也没有参数,返回布尔类型,那就没办法设置了。放弃之心+10.就在偶然之间发现了一些不是遍历出来的字段的内容为

<w:rFonts w:hint="eastAsia" w:ascii="仿宋" w:hAnsi="仿宋" w:eastAsia="仿宋" w:cs="Arial"/>

竟然不一样。感觉胜利女神已经在朝我挥手了。突然想起了在名侦探柯南中,小兰推理那集,工藤提到过福尔摩斯的一句话

首先要把一切不可能的结论都排除,那其余的,不管多么离奇,难以置信,也必然是无可辩驳的事实。或许剩下的是几种解释,如果这样,那就要一一地加以证实,直到最后只剩下一种具有充分根据证明的解释。

一旦你排除了所有不可能的事实外,那么剩下的,不管多么不可思议,那就是事实的真相。

 当我们排除一系列错误以后,那么真相已经离我们很近了。既然真相已经出现,剩下的只有向真相去靠拢了。

                //真相永远只有一个(名侦探柯南)
                CTFonts tmpFonts = sourceRun.getCTR().getRPr().getRFonts();
                //真相的tmpFonts0 
                CTFonts tmpFonts0 = sourceRun0.getCTR().getRPr().getRFonts();
                String fontFamily0 = sourceRun0.getFontFamily();
                System.out.println(tmpFonts0);
                //未曾从网上看到过setHint,核心代码
                tmpFonts.setHint(tmpFonts0.getHint());
                tmpFonts.setAscii(fontFamily0);
                tmpFonts.setEastAsia(fontFamily0);
                tmpFonts.setHAnsi(fontFamily0);
                tmpFonts.setCs("Arial");
                System.out.println("~~~~~~~~~~~这是真相~~~~~~~~~~~~~~~~~");
                System.out.println(tmpFonts);
                System.out.println(tmpFonts0.isSetAsciiTheme());
                System.out.println(tmpFonts0.getAsciiTheme());
                System.out.println("~~~~~~~~~~~这是我们的结果~~~~~~~~~~~~~~~~~");
                System.out.println(tmpFonts.isSetAsciiTheme());
                System.out.println(tmpFonts.getAsciiTheme());
                //也未曾看到过类似的代码,全凭借推理
                tmpFonts.unsetAsciiTheme();
                tmpFonts.unsetEastAsiaTheme();
                tmpFonts.unsetHAnsiTheme();
                System.out.println("~~~~~~~~~~这是按照真相修改后的结果~~~~~~~~~~~~~~~~~~");
                System.out.println(tmpFonts.isSetAsciiTheme());
                System.out.println(tmpFonts.getAsciiTheme());
                sourceRun.setFontSize(sourceRun0.getFontSize()); 
   /**
     * ~~~~~~~~~~~这是真相~~~~~~~~~~~~~~~~~
     * false
     * null
     * ~~~~~~~~~~~这是我们的结果~~~~~~~~~~~~~~~~~
     * true
     * null
     * ~~~~~~~~~~这是按照真相修改后的结果~~~~~~~~~~~~~~~~~~
     * false
     * null
     */

此时要注意下,我们从其他渠道获得的easypoi的jar包可能不全,我原有的就是不全的,还是从码云上拷一份吧,这是easypoi导出word的全部

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

        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-base</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-web</artifactId>
            <version>4.2.0</version>
        </dependency>
        <dependency>
            <groupId>cn.afterturn</groupId>
            <artifactId>easypoi-annotation</artifactId>
            <version>4.2.0</version>
        </dependency>
        <!-- Word 需要使用 -->
        <dependency>
            <groupId>org.apache.poi</groupId>
            <artifactId>ooxml-schemas</artifactId>
            <version>1.3</version>
            <optional>true</optional>
        </dependency>

 验证遍历后的结果中的一个字段可以,那么就可以循环去修改样式了

 /**
     * 修改月报的样式
     * @param sourceTable
     * @param tmpFonts0
     * @param fontFamily0
     */
    public static void changeMonthStyle(XWPFTable sourceTable, CTFonts tmpFonts0, String fontFamily0) {
        // List  list =  (List)listMap.get("debtList");
        //获取table

        // final int size = list.size();

        //获取所有的行数
        int size = sourceTable.getRows().size();
        //从第三行开始遍历修改样式
        for (int i = 3; i < size; i++) {
            //获取每一行
            XWPFTableRow row = sourceTable.getRow(i);
            // 设置行高
            // row.setHeight(600);
            // 获取每一个空格子

            List<XWPFTableCell> cellList = row.getTableCells();
            //获取每一行空格的总个数
            final int cellSize = cellList.size();
            //进行循环遍历修改每一个空格的样式,标题行不修改样式
            for (int j = 0; j < cellSize && cellSize > 1; j++) {
                //获取每一个空格
                XWPFTableCell cell = row.getCell(j);
                // 设置列宽
                //   cell.setWidth(String.valueOf(sourceRow.getCell(j).getWidth()));
                //   cell.setWidthType(sourceRow.getCell(j).getWidthType());
                // 设置垂直对齐方式
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
                //获取空格子里面的每一个行
                XWPFParagraph cellPara = cell.getParagraphs().get(0);
                // 设置水平对齐方式
                //  cellPara.setAlignment(ParagraphAlignment.CENTER);
                XWPFRun cellRun = cellPara.getRuns().get(0);
                System.out.println(cellRun.getText(0));
                String text = cellRun.getText(0);
                cellRun.setFontSize(12);
                //全网独一份,根据模板的样式设置总的样式
                CTFonts tmpFonts = cellRun.getCTR().getRPr().getRFonts();
                tmpFonts.setHint(tmpFonts0.getHint());
                tmpFonts.setAscii(fontFamily0);
                tmpFonts.setEastAsia(fontFamily0);
                tmpFonts.setHAnsi(fontFamily0);
                tmpFonts.setCs("Arial");
                tmpFonts.unsetAsciiTheme();
                tmpFonts.unsetEastAsiaTheme();
                tmpFonts.unsetHAnsiTheme();
                if (text.equals("资产总计") || text.equals("负债合计") ||
                        text.equals("所有者权益合计") || text.equals("负债和所有者权益总计") ||
                        text.equals("净利润") || text.equals("经营活动产生的现金流量净额") ||
                        text.equals("经营活动产生的现金流量净额") || text.equals("筹资活动产生的现金流量净额") ||
                        text.equals("现金及现金等价物净增加额") || text.equals("年末现金及现金等价物余额")
                ) {
                    //字体加粗第0列1列2列3列
                    cellRun.setBold(true);
                    row.getCell(j + 1).getParagraphs().get(0).getRuns().get(0).setBold(true);
                    row.getCell(j + 2).getParagraphs().get(0).getRuns().get(0).setBold(true);
                    row.getCell(j + 3).getParagraphs().get(0).getRuns().get(0).setBold(true);

                }

            }
        }
    }

到此,样式修改就完成了 。

有时候有些事,总是想放弃,却又一步一步走了下来。就在突然间灵光一现,答案就在眼前不远处。知识的积累同样如此,可能在很长的一段时间没有感觉到进步,可能是因为还没有到达质变的点,或在下一瞬间,就会突飞猛进,走上人生巅峰!共勉!

 参考文章如下:

EasyPOI导出Word定制版

poi导出word ,中文 字体样式 问题

码云easypoi

福尔摩斯名言

 

### 使用 EasyPoi 实现 Word 文档导出 EasyPoi 是一款强大的 Java 工具库,能够帮助开发者轻松实现 Excel 和 Word 的导入与导出功能。以下是基于若依框架使用 EasyPoi 导出 Word 文档的具体方法。 #### 1. 引入 Maven 依赖 为了使用 EasyPoi 功能,首先需要在项目的 `pom.xml` 文件中引入相应的依赖项。 ```xml <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>4.4.0</version> </dependency> ``` 上述代码展示了如何配置 Maven 依赖来支持 EasyPoi 的基本功能[^3]。 #### 2. 创建导出工具类 创建一个名为 `WordUtil.java` 的工具类用于封装导出逻辑。此工具类主要负责加载模板文件并填充数据到模板中。 ```java import cn.afterturn.easypoi.word.WordExportUtil; import org.apache.poi.xwpf.usermodel.XWPFDocument; import java.io.File; import java.io.FileOutputStream; import java.util.Map; public class WordUtil { public static void exportWord(String templatePath, String outputPath, Map<String, Object> dataMap) throws Exception { XWPFDocument document = WordExportUtil.exportWord(templatePath, dataMap); try (FileOutputStream fos = new FileOutputStream(new File(outputPath))) { document.write(fos); } } } ``` 这段代码实现了通过指定的模板路径和数据映射表生成目标 Word 文件的功能。 #### 3. 定义控制器接口 在若依框架中,通常会在 Controller 层定义对外暴露的服务接口。下面是一个简单的示例: ```java @RestController @RequestMapping("/export") public class ExportController { @PostMapping("/word") public ResponseEntity<byte[]> exportWord(@RequestBody Map<String, Object> dataMap) throws Exception { String templatePath = "classpath:templates/example.docx"; // 模板文件路径 String tempFilePath = System.getProperty("java.io.tmpdir") + "/output_word.docx"; WordUtil.exportWord(templatePath, tempFilePath, dataMap); HttpHeaders headers = new HttpHeaders(); headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=output_word.docx"); return ResponseEntity.ok() .headers(headers) .contentLength(new File(tempFilePath).length()) .contentType(MediaType.APPLICATION_OCTET_STREAM) .body(FileUtils.readFileToByteArray(new File(tempFilePath))); } } ``` 以上代码片段展示了一个 RESTful 接口,接收 JSON 数据作为输入参数,并返回生成好的 Word 文件供客户端下载[^1]。 #### 4. 准备 Word 模板 准备一份 `.docx` 格式的模板文件,在其中预留占位符以便后续动态替换内容。例如: - 占位符格式为 `${variableName}` 或者 `{{variableName}}`。 - 如果涉及列表数据,则需将其放置于表格结构内[^4]。 #### 5. 测试导出效果 启动应用程序后访问对应的 API 地址,传入必要的请求体(JSON 格式),验证最终生成的 Word 是否符合预期。 --- ### 注意事项 - 确保模板中的变量名与实际传递的数据键一致,否则可能导致渲染失败。 - 对于复杂场景下的样式调整建议借助第三方编辑器完成后再集成至程序中。
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值