使用Java的Apache POI和POI-TL应用模板样式合并word文档

前置内容

下面内容可直接跳过,直接查看代码即可
项目链接

POI简介和POI-TL简介

POI简介

POI(Poor Obfuscation Implementation)是一个用于操作Microsoft Office格式文件的Java库。它提供了一组API,可以读取、写入和操作Word文档(.doc和.docx)、Excel电子表格(.xls和.xlsx)以及PowerPoint演示文稿(.ppt和.pptx)等文件格式。

POI库的目标是为开发人员提供一种简单且便捷的方式来处理Microsoft Office文件,无需依赖于Microsoft Office本身。它支持在Java应用程序中创建、修改和读取Office文件,可以用于生成报表、读取和处理文件内容、进行数据导入和导出等场景。

本文针对word2007版本的文档进行处理, 这里主要用到处理docx文件格式的XWPF(XML Word Processor Format)类。

POI-TL

POI-TL是一个基于POI库的Java模板引擎,它提供了一种简单而强大的方式来生成和处理Microsoft Office文件中的模板。POI-TL的全称是POI-Template,它致力于简化处理Word和Excel模板的操作。

POI-TL的设计目标是使模板处理变得简单易用,开发人员可以通过定义模板和填充数据的方式来生成Word和Excel文件。它支持在模板中定义占位符和数据区域,然后使用Java代码填充占位符和数据,最后生成最终的Office文件。

Docx文件简介

将任意文档扩展名docx修改为zip,使用压缩软件打开后即可看到如下内容:在这里插入图片描述
双击word文件夹,即可看到如下内容:
在这里插入图片描述
内容介绍如下:
styles.xml:
存储了Word文档中的样式定义。它包含了文本样式、段落样式、页眉页脚样式、表格样式等的定义。这些样式可以应用于文档的不同部分,使其在格式和外观上保持一致性。

document.xml:
是Word文档的主要内容文件,其中包含了文本、段落、图片、表格、图表等的内容和格式。该文件存储了文档的实际文本和结构,并定义了每个元素的属性和样式。

numbering.xml:
用于存储Word文档中的编号列表定义。它包含了文档中使用的所有编号样式以及相应的编号规则、格式等信息。
diagrams:该目录存储了Word文档中插入的图表(如流程图、组织结构图等)的相关数据和XML文件。

media:
如果Word文档中包含了嵌入的多媒体文件(如图片、音频、视频等),那么这些文件会被存储在media目录下。

theme:
存储了Word文档的主题相关的数据和XML文件。主题定义了文档中使用的颜色、字体、效果等,帮助确保文档的整体外观和风格的一致性。

settings.xml:
包含了Word文档的各种设置信息,如页面设置、打印设置、语言设置、拼写检查设置、自动更正设置等。这个文件中存储了文档的全局设置。

footnotes.xml:
存储了Word文档中的脚注内容。脚注是文档中的附加信息,通常出现在页面底部,用于解释、引用或注释正文中的内容。

fontTable.xml:
存储了Word文档中使用的字体信息。它包含了文档中使用的所有字体的名称、字体样式、大小等属性。

endnotes.xml:
类似于脚注,存储了Word文档中的尾注内容。尾注通常出现在文档的末尾,用于提供额外的注释、参考或解释。

header1.xml:
存储了Word文档中第一个节(section)的页眉内容。页眉是位于页面顶部的信息,如标题、日期等。

webSettings.xml:
存储了Word文档中的Web设置。这些设置包括是否将文档作为Web页面显示、网页布局、网页字体等。

Word样式简介

word样式分为段落样式、字符样式、链接段落和字符样式、表格样式、列表样式,简单介绍如下:

段落样式:
段落样式用于定义整个段落的格式和外观,包括文本对齐、缩进、行间距、段前段后间距、编号等。通过应用段落样式,可以快速一致地格式化整个段落的内容。

字符样式:
字符样式用于定义文本中特定字符或文字的格式,如字体、字号、颜色、加粗、斜体等。通过应用字符样式,可以使某些文字在文本中以不同的样式显示。

链接段落和字符样式:
这种样式用于定义链接文本的外观,可以分别应用于链接的段落和链接的字符。它可以帮助标识链接内容,如超链接、目录、参考文献等。

表格样式:
表格样式用于定义Word文档中的表格的样式和外观,包括表格边框、背景颜色、标题行样式等。通过应用表格样式,可以快速美化并统一整个表格的样式。

列表样式:
列表样式用于定义和管理Word文档中的有序列表和无序列表的格式,如项目标记、缩进、行距等。列表样式可以应用于整个列表或者特定的项目。

其他还包含标题样式、图片样式、页面样式、注释样式、目录样式等,不再逐一列举。

项目要求

将若干文件合并至同一个word文档中;
按要求改变每个word文档的第一段内容但不能改变标题级别,且要求第一段按多级编号的顺序进行编号;
保证后续内容按固定的模板样式设置;

网上查阅到的资料大部分都使用poi-tl的NiceXWPFDocument类的merge方法对文档进行合并,但如果合并文档数量较多,即使使用相同的模板,也会产生大量的重复样式[1]:
过多样式导致无法正常使用

设计思路

将待合并的文档模板中的标题样式全部使用系统内置样式,然后设置类型为段落样式,即可保证标题级别的正确性,下面是设计思路;
预备工作:制作template.docx和merge.docx,这两个文档都拥有所有样式,其中merge.docx作为被合并的基础文档,内容为空或者仅有一段。
1、读取待合并文档,获取其段落的样式名称,保存至列表;
2、合并每个文档前将第一段内容替换掉
3、将文档合并至空白基础文件merge.docx内。
4、将template.docx样式写入被合并的文档中。

具体代码如下:

  /**
    * MergeFileAndReplaceTitle(ArrayList<ArrayList<String>> fileList,String destFile)
    * @param fileList 文件名和标题列表:[D:\poitl中文\文档1.docx, 标题111111],[D:\poitl中文\文档1.docx, 标题22222]...]
    * @param destFile 输出文件名
    */
    public static void MergeFileAndReplaceTitle(ArrayList<ArrayList<String>> fileList,String destFile) {
    	String path = "D:\\poitl中文\\";
    	String template = path + "template.docx";
    	String blankFile = path + "merge.docx";//用于创建空白word文件
    	try {
    		NiceXWPFDocument tempDocument = new NiceXWPFDocument(new FileInputStream(template));//样式模板文档
    		NiceXWPFDocument newDoc = new NiceXWPFDocument(new FileInputStream(blankFile));
    		ArrayList<String> allFileStyles = new ArrayList<String>();
            for(ArrayList<String> obj :fileList) {
            	String filePath = obj.get(0);
            	NiceXWPFDocument srcDocument = new NiceXWPFDocument(new FileInputStream(filePath));
            	XWPFParagraph p1 = srcDocument.getParagraphArray(0);
            	p1.removeRun(0);//删除第一段原内容
           	 	p1.createRun().setText(obj.get(1));
            	List<XWPFParagraph> srcPList = srcDocument.getParagraphs();
            	for(int i = 0;i<srcPList.size();i++) {
            		allFileStyles.add(srcPList.get(i).getStyleID());
            	}
            	newDoc = newDoc.merge(srcDocument);
            }
            List<XWPFParagraph> newDocParagraphs = newDoc.getParagraphs();
            for(int i = 1;i<newDocParagraphs.size();i++) {//空白文档模板有1行
            	newDocParagraphs.get(i).setStyle(allFileStyles.get(i-1));
            }
            newDoc.createStyles().setStyles(tempDocument.getStyle());
    		FileOutputStream out = new FileOutputStream(destFile);
    		newDoc.write(out);
    		System.out.println(destFile + "文件输出成功");
    		newDoc.close();
    	}catch(Exception e) {
    		e.printStackTrace();
    	}
    }

文件合并后样式如下:
并未增加新样式

注意:
1、程序对普通字符样式要求并不严格,但对标题样式或段落样式要求严格,对每个待合并的文档,需要使用统一模板样式。
2、段落数字编号在编号级别相同情况下,会对第二个使用相同的编号列表继续编号,此时可编辑样式文件numbering.xml里的编号样式<w:abstractNum w:abstractNumId=“1” w15:restartNumberingAfterBreak=“0”>,设置w15:restartNumberingAfterBreak=“1”,使其在分节符后将编号值重新从1开始计数(连续型分节符即可)。

以上程序使用的资源版本为poi-4.1.2 和poi-tl-1.10.0 ,在eclipse2022.03环境下测试通过

引用

1.引用资料链接: 方案二:通过poi-tl实现word文字插入,并把多个word合并

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在Spring Boot中使用poi-tl库来导出带有合并列的Word表格并下载,您可以按照以下步骤操作: 1. 首先,确保您的Spring Boot项目中已经添加了poi-tl的依赖。您可以在pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.6.0</version> </dependency> ``` 2. 创建一个Controller来处理导出请求。例如,创建一个名为WordExportController的类,并添加一个处理导出请求的方法。 ```java import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.data.*; import com.deepoove.poi.util.BytePictureUtils; import org.apache.poi.xwpf.usermodel.XWPFTable; import org.apache.poi.xwpf.usermodel.XWPFTableRow; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; @Controller public class WordExportController { @GetMapping("/export") public ResponseEntity<InputStreamResource> exportWord() throws IOException { // 创建一个数据模型 List<List<String>> tableData = new ArrayList<>(); tableData.add(createRow("Merged Cells", "Cell 3")); tableData.add(createRow("Cell 4", "Cell 6")); // 使用poi-tl的XWPFTemplate来生成Word文档 XWPFTemplate template = XWPFTemplate.compile("templates/template.docx").render( new DataTable(tableData) .setHeader(createRow("Header 1", "Header 2")) .setCellWidth(2000) // 设置单元格宽度 .setHeaderCellStyle(new CellStyle().setBold(true).setColor("FFFFFF").setBgColor("336699")) .setOddRowCellStyle(new CellStyle().setColor("FFFFFF").setBgColor("99CCFF")) .setEvenRowCellStyle(new CellStyle().setColor("FFFFFF").setBgColor("CCEEFF")) ); // 将生成的Word文档转换为字节数组 ByteArrayOutputStream out = new ByteArrayOutputStream(); template.write(out); byte[] documentBytes = out.toByteArray(); // 设置下载响应的头信息 HttpHeaders headers = new HttpHeaders(); headers.setContentDispositionFormData("attachment", "merged_table.docx"); headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); // 创建一个包含Word文档字节数组的InputStreamResource InputStreamResource resource = new InputStreamResource(new ByteArrayInputStream(documentBytes)); // 返回响应实体 return ResponseEntity.ok() .headers(headers) .body(resource); } private List<String> createRow(String cell1, String cell2) { List<String> row = new ArrayList<>(); row.add(cell1); row.add(cell2); return row; } } ``` 3. 在resources目录下创建一个名为template.docx的Word模板文件。在模板文件中,您可以根据自己的需求设置表格样式和内容。 4. 启动您的Spring Boot应用程序,并访问导出请求的URL(例如:http://localhost:8080/export)。将会自动下载名为merged_table.docx的Word文档,其中包含合并列的表格。 请确保按照您的需求修改代码,并根据模板文件的位置进行相应的调整。 希望对您有所帮助!如果您有任何其他问题,请随时提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值