java解析.docx格式文档,XWPFTable解析换行符,以及wps和office在读写.docx文档时段落结构不同的大坑

需求

从前端传来一个.docx文档,后端解析该文档里的表格,对其中的数据进行处理。

(我也不知道为什么非要解析word文档里面的表格,而不是直接传一个excel。)

实现

1.前端用的elementui-upload,把整个.docx文件传给后端。

2.后端controller接收这个文档,注意接收的格式是MultipartFile不是file,不然就报500了。

3.后端service解析这个文档:

public Map < String, Object > dealWord(MultipartFile file) throws IOException {
		// 3.1 解析整个文档
		XWPFDocument xwpf = new XWPFDocument(file.getInputStream());
		// 3.2 从文档中获取表格的迭代器
		Iterator < XWPFTable > it = xwpf.getTablesIterator();
		// 3.3 遍历所有的表格,挨个解析
		while (it.hasNext()) {
			// 3.3.1 获取到当前的表格
			XWPFTable table = it.next();
			// 3.3.2 获取到行数据
			List < XWPFTableRow > rows = table.getRows();
			// 3.3.3 遍历每行,获取每个单元格
			for (int i = 1; i < rows.size(); i++) {
				XWPFTableRow row = rows.get(i);
				List<XWPFTableCell> cells = row.getTableCells();
				// 3.3.4 获取每个单元格里面的文字
				for(int j = 0;j<cells.size();j++){
					String text = cells.get(j).getText()
				}
			}
		}

如果只需要获取每个单元格内的文字内容,不考虑换行,那么到这里就结束了。

如果需要解析单元格内的换行符,请继续往下看。

接下来介绍这里面的大坑。

一开始我以为XWPFTable是不能解析到换行符的,后来觉得怎么可能,就具体看了下XWPFTable里面的数据的结构。

但是用wps和office读写过的.docx文档,解析出来的段落结构是不一样的!

不过很好做兼容。

这里顺便介绍下解析出来的结构吧!

以如下表格为例(WPS读写版本):

这个表格解析出来的数据是类似于这样的:

字段解释:

这里的runs我也不知道怎么解释...看了看官方文档也不太明白,希望有所了解的朋友可以补充。

wps和word读写过的表格,就是在runs这里发生了差异。

图中可以看到,里面的一个段落paragrah里面有一个run对象,就是单元格1.
三个段落,各自有一个run对象。

但是在office读写过的表格里,这里可能有多个run对象,也就是单元格1可能被拆成多个run对象。

可以对比着看一下:

这里的单元格1被拆解成了单元格和1两个run对象。

探究office

闲着也是闲着,探究一下office里面run对象的数量的规则吧。

推测:以数据类型分割整个段落的文字,表格是字符串文字,1是数字。

现在我们要解析的offcie读写的表格:

解析出来的结果:

对比一下:

这就有点整不明白了吧....以我有限的知识水平,不知道为什么要把3和L拆开,但又把4L%合并成一个run对象了....

解决办法

这个问题挺好解决的:

要获取单元格内的第一排内容:
获取到tableCell,获取所有的paragrahs,获取第一个paragrah,遍历获取这个paragrah里面所有的runs.

这样就同时能适配wps和office啦。

上一段代码:

public Map < String, Object > dealWord(MultipartFile file) throws IOException {
		// 3.1 解析整个文档
		XWPFDocument xwpf = new XWPFDocument(file.getInputStream());
		// 3.2 从文档中获取表格的迭代器
		Iterator < XWPFTable > it = xwpf.getTablesIterator();
		// 3.3 遍历所有的表格,挨个解析
		while (it.hasNext()) {
			// 3.3.1 获取到当前的表格
			XWPFTable table = it.next();
			// 3.3.2 获取到行数据
			List < XWPFTableRow > rows = table.getRows();
			// 3.3.3 遍历每行,获取每个单元格
			for (int i = 1; i < rows.size(); i++) {
				XWPFTableRow row = rows.get(i);
				List<XWPFTableCell> cells = row.getTableCells();
				// 3.3.4 获取每个单元格里面的文字
				for(int j = 0;j<cells.size();j++){
					String text = cells.get(j).getText()
				}
				// 3.3.5 获取单元格里面的第一段内容
				// 如果想要获取所有段的内容 用ArrayList接收一下哈 这里不演示了
				for(int k = 0;k<cells.getParagraphs().size();k++){
					String text = "";
					// 遍历第一段里面所有的run 注意这里只get了0的段落
					for(int p = 0;p<cells.getParagraphs().get(0).getRuns().size();p++){
						text = text + cells.getParagraphs().get(0).getRuns().get(p);
					}
					System.out.prrintln("单元格第一排的内容是:"+text);
				}
			}
		}

是很简单的一个遍历啦,很容易适配,就写到这里了噢。

posted on 2021-12-31 18:29  northwest  阅读(1188)  评论(0编辑  收藏  举报

导航