Java-poi-XWPFDocument-MjWord

这篇文章介绍了使用Java编写的MjWord工具类,它提供了操作Word文档的功能,如获取段落、表格,向段落和表格写入数据,插入图片以及合并单元格,支持数据替换和格式保持。
摘要由CSDN通过智能技术生成

Java操作Word文档工具类:

  • 获取Word文档中的段落
  • 获取Word文档中的表格
  • 获取表格中的单元格
  • 向Word文档中的段落里写入数据,占位符${name}
  • 向Word文档中的表格里写入数据,占位符${name}
  • 向表格中的单元格里写入数据
  • 向Word文档里插入图片
  • 合并单元格
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.springframework.util.ReflectionUtils;
import org.um.util.common.UmUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description: word工具类
 * @Author: Michael Jie
 * @Date: 2024/1/30 8:23
 * @Version: V1.0
 **/
public class MjWord {
	private final String path;
	private FileInputStream fi;
	private final XWPFDocument docx;

	/**
	 * 构造函数
	 *
	 * @param path: Word文件路径
	 * @author Michael
	 * @date 2024/1/25 8:45
	 * @return: null
	 **/
	public MjWord(String path) throws Exception {
		File file = new File(path);
		if (!file.exists()) {
			throw new Exception("非文件路径!");
		}
		if (!path.toLowerCase().contains(".docx")) {
			throw new Exception("非docx文件路径!");
		}
		this.path = path.replace("/", File.separator);
		this.fi = new FileInputStream(file);
		this.docx = new XWPFDocument(this.fi);
	}

	/**
	 * 获取所有段落
	 *
	 * @param empty: 是否剔除空白段落
	 * @author Michael
	 * @date 2024/1/25 10:00
	 * @return: java.util.List<org.apache.poi.xwpf.usermodel.XWPFParagraph>
	 **/
	public List<XWPFParagraph> getParagraphs(boolean empty) throws Exception {
		List<XWPFParagraph> paragraphs = this.docx.getParagraphs();
		if (!empty) {
			return paragraphs;
		}
		//剔除空白段落
		List<XWPFParagraph> list = new ArrayList<>();
		for (XWPFParagraph paragraph : paragraphs) {
			String text = paragraph.getParagraphText();
			if (MjUtil.isNull(text)) {
				continue;
			}
			list.add(paragraph);
		}
		return list;
	}

	/**
	 * 获取特定段落
	 *
	 * @param inx: 子字符串
	 * @author Michael
	 * @date 2024/1/25 10:02
	 * @return: org.apache.poi.xwpf.usermodel.XWPFParagraph
	 **/
	public XWPFParagraph getParagraph(String inx) throws Exception {
		List<XWPFParagraph> paragraphs = getParagraphs(false);
		for (XWPFParagraph paragraph : paragraphs) {
			if (paragraph.getParagraphText().equals(inx)) {
				return paragraph;
			}
		}
		return paragraphs.get(0);
	}

	/**
	 * 获取所有表格
	 *
	 * @author Michael
	 * @date 2024/1/25 10:25
	 * @return: java.util.List<org.apache.poi.xwpf.usermodel.XWPFTable>
	 **/
	public List<XWPFTable> getTables() throws Exception {
		return this.docx.getTables();
	}

	/**
	 * 获取特定表格
	 *
	 * @param inx: 索引
	 * @author Michael
	 * @date 2024/1/25 10:10
	 * @return: org.apache.poi.xwpf.usermodel.XWPFTable
	 **/
	public XWPFTable getTable(int inx) throws Exception {
		List<XWPFTable> tables = getTables();
		return tables.get(inx);
	}

	/**
	 * 向段落里写入数据
	 *
	 * @param paragraph: 段落
	 * @param data:      数据
	 * @author Michael
	 * @date 2024/1/25 10:13
	 * @return: void
	 **/
	public void writeDataToParagraph(XWPFParagraph paragraph,
									 Map<String, String> data) throws Exception {
		String text = paragraph.getText();
		String resultText = MjUtil.replaceText(text, data);
		writeText(paragraph, resultText);
	}

	/**
	 * 向段落里写入数据
	 *
	 * @param paragraph: 段落
	 * @param data:      数据
	 * @param type:      类名路径
	 * @author Michael
	 * @date 2024/1/25 10:37
	 * @return: void
	 **/
	public void writeDataToParagraph(XWPFParagraph paragraph,
									 Object data,
									 String type) throws Exception {
		String text = paragraph.getText();
		String resultText = MjUtil.replaceText(text, data, type);
		writeText(paragraph, resultText);
	}

	/**
	 * 向表格里写入数据
	 *
	 * @param table: 表格
	 * @param data:  数据
	 * @author Michael
	 * @date 2024/1/25 17:46
	 * @return: void
	 **/
	public void writeDataToTable(XWPFTable table,
								 Map<String, String> data) throws Exception {
		List<XWPFTableRow> rows = table.getRows();
		for (XWPFTableRow row : rows) {
			List<XWPFTableCell> cells = row.getTableCells();
			for (XWPFTableCell cell : cells) {
				// 不能使用该方法直接加内容,这样会在原内容后面追加,并且不能保证跟原字体样式一致
				// cell.setText(resultText);
				List<XWPFParagraph> paragraphs = cell.getParagraphs();
				for (XWPFParagraph paragraph : paragraphs) {
					//向单元格的段落里写入数据
					writeDataToParagraph(paragraph, data);
				}
			}
		}
	}

	/**
	 * 向表格里写入数据
	 *
	 * @param table: 表格
	 * @param data:  数据
	 * @param type:  类名路径
	 * @author Michael
	 * @date 2024/1/25 10:50
	 * @return: void
	 **/
	public void writeDataToTable(XWPFTable table,
								 Object data,
								 String type) throws Exception {
		List<XWPFTableRow> rows = table.getRows();
		for (XWPFTableRow row : rows) {
			List<XWPFTableCell> cells = row.getTableCells();
			for (XWPFTableCell cell : cells) {
				List<XWPFParagraph> paragraphs = cell.getParagraphs();
				for (XWPFParagraph paragraph : paragraphs) {
					writeDataToParagraph(paragraph, data, type);
				}
			}
		}
	}

	/**
	 * 向表格里写入多条数据
	 *
	 * @param table:    表格
	 * @param dataList: 数据列表
	 * @param startRow: 起始行索引
	 * @author Michael
	 * @date 2024/1/25 10:24
	 * @return: void
	 **/
	public void writeDataListToTable(XWPFTable table,
									 List<Map<String, String>> dataList,
									 int startRow) throws Exception {
		for (Map<String, String> data : dataList) {
			//创建新的行
			CTRow ctrow = CTRow.Factory.parse(table.getRow(startRow).getCtRow().newInputStream());
			// 此方法可以使新增的行和模板样式一样,但是新行赋值是会将上面行的row也修改了
			// XWPFTableRow newRow = new XWPFTableRow(table.getRow(startRow).getCtRow(), table);
			XWPFTableRow newRow = new XWPFTableRow(ctrow, table);
			List<XWPFTableCell> cells = newRow.getTableCells();
			for (XWPFTableCell cell : cells) {
				List<XWPFParagraph> paragraphs = cell.getParagraphs();
				for (XWPFParagraph paragraph : paragraphs) {
					writeDataToParagraph(paragraph, data);
				}
			}
			table.addRow(newRow);
		}
		table.removeRow(startRow);
	}

	/**
	 * 向表格里写入多条数据
	 *
	 * @param table:    表格
	 * @param dataList: 数据列表
	 * @param startRow: 起始行索引,模板行
	 * @param type:     类名路径
	 * @author Michael
	 * @date 2024/1/25 10:24
	 * @return: void
	 **/
	public void writeDataListToTable(XWPFTable table,
									 List<Object> dataList,
									 int startRow,
									 String type) throws Exception {
		for (Object data : dataList) {
			CTRow ctrow = CTRow.Factory.parse(table.getRow(startRow).getCtRow().newInputStream());
			XWPFTableRow newRow = new XWPFTableRow(ctrow, table);
			List<XWPFTableCell> cells = newRow.getTableCells();
			for (XWPFTableCell cell : cells) {
				List<XWPFParagraph> paragraphs = cell.getParagraphs();
				for (XWPFParagraph paragraph : paragraphs) {
					writeDataToParagraph(paragraph, data, type);
				}
			}
			table.addRow(newRow);
		}
		table.removeRow(startRow);
	}

	/**
	 * 向单元格里写入数据
	 *
	 * @param tableInx: 表格索引
	 * @param row:      行索引
	 * @param col:      列索引
	 * @param text:     文本
	 * @author Michael
	 * @date 2024/1/25 15:30
	 * @return: void
	 **/
	public void writeDataToCell(int tableInx,
								int row,
								int col,
								String text) throws Exception {
		XWPFTable table = this.getTable(tableInx);
		writeDataToCell(table, row, col, text);
	}

	/**
	 * 向单元格里写入数据
	 *
	 * @param table: 表格
	 * @param row:   行索引
	 * @param col:   列索引
	 * @param text:  文本
	 * @author Michael
	 * @date 2024/1/25 15:30
	 * @return: void
	 **/
	public void writeDataToCell(XWPFTable table,
								int row,
								int col,
								String text) throws Exception {
		XWPFTableCell cell = getCell(table, row, col);
		cell.setText(text);
	}

	/**
	 * 向单元格里插入图片
	 *
	 * @param tableInx: 表格索引
	 * @param row:      行索引
	 * @param col:      列索引
	 * @param imgPath:  图片路径
	 * @param width:    宽
	 * @param height:   高
	 * @author Michael
	 * @date 2024/1/26 8:57
	 * @return: void
	 **/
	private void writePictureToCell(int tableInx,
									int row,
									int col,
									String imgPath,
									int width,
									int height) throws Exception {
		XWPFTable table = this.getTable(tableInx);
		writePictureToCell(table, row, col, imgPath, width, height);
	}

	/**
	 * 向单元格里插入图片
	 *
	 * @param table:   表格
	 * @param row:     行索引
	 * @param col:     列索引
	 * @param imgPath: 图片路径
	 * @param width:   宽
	 * @param height:  高
	 * @author Michael
	 * @date 2024/1/26 8:57
	 * @return: void
	 **/
	private void writePictureToCell(XWPFTable table,
									int row,
									int col,
									String imgPath,
									int width,
									int height) throws Exception {
		XWPFTableCell cell = getCell(table, row, col);
		//获取图片
		File image = new File(imgPath);
		if (!image.exists()) {
			throw new Exception("未发现图片!");
		}
		byte format;
		if (imgPath.endsWith(".emf")) {
			format = 2;
		} else if (imgPath.endsWith(".wmf")) {
			format = 3;
		} else if (imgPath.endsWith(".pict")) {
			format = 4;
		} else if (!imgPath.endsWith(".jpeg") && !imgPath.endsWith(".jpg")) {
			if (imgPath.endsWith(".png")) {
				format = 6;
			} else if (imgPath.endsWith(".dib")) {
				format = 7;
			} else if (imgPath.endsWith(".gif")) {
				format = 8;
			} else if (imgPath.endsWith(".tiff")) {
				format = 9;
			} else if (imgPath.endsWith(".eps")) {
				format = 10;
			} else if (imgPath.endsWith(".bmp")) {
				format = 11;
			} else {
				if (!imgPath.endsWith(".wpg")) {
					throw new Exception("图片格式不正确!");
				}

				format = 12;
			}
		} else {
			format = 5;
		}
		//插入图片
		List<XWPFParagraph> paragraphs = cell.getParagraphs();
		XWPFParagraph newPara = paragraphs.get(0);
		XWPFRun imageCellRun = newPara.createRun();
		FileInputStream is = new FileInputStream(imgPath);
		imageCellRun.addPicture(is, format, image.getName(), Units.toEMU(width), Units.toEMU(height));
	}

	/**
	 * 合并单元格
	 *
	 * @param tableInx: 表格索引
	 * @param startRow: 左上角单元格行索引
	 * @param startCol: 左上角单元格列索引,(0, 0)
	 * @param endRow:   右下角单元格行索引
	 * @param endCol:   右下角单元格列索引,(1, 1)
	 * @author Michael
	 * @date 2024/1/25 14:15
	 * @return: void
	 **/
	public XWPFTableCell mergeCells(int tableInx,
									int startRow,
									int startCol,
									int endRow,
									int endCol) throws Exception {
		XWPFTable table = this.getTable(tableInx);
		return mergeCells(table, startRow, startCol, endRow, endCol);
	}

	/**
	 * 合并单元格
	 *
	 * @param table:    表格
	 * @param startRow: 左上角单元格行索引
	 * @param startCol: 左上角单元格列索引,(0, 0)
	 * @param endRow:   右下角单元格行索引
	 * @param endCol:   右下角单元格列索引,(1, 1)
	 * @author Michael
	 * @date 2024/1/25 14:15
	 * @return: void
	 **/
	public XWPFTableCell mergeCells(XWPFTable table,
									int startRow,
									int startCol,
									int endRow,
									int endCol) throws Exception {
		//插入的表格行使用此方法合并无效果
		if (startRow == endRow) {
			//直接纵向合并
			table.getRow(startRow).getCell(startCol).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
			table.getRow(endRow).getCell(endCol).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
		} else {
			//先横向合并
			for (int i = startRow; i <= endRow; i++) {
				table.getRow(i).getCell(startCol).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
				table.getRow(i).getCell(endCol).getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
			}
			//再纵向合并
			table.getRow(startRow).getCell(startCol).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
			table.getRow(endRow).getCell(startCol).getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
		}
		return getCell(table, startRow, startCol);
	}

	/**
	 * 保存并关闭文件
	 *
	 * @param path:  保存路径
	 * @param close: 是否关闭文件
	 * @author Michael
	 * @date 2024/1/25 9:57
	 * @return: void
	 **/
	public void saveAndClose(String path,
							 boolean close) throws Exception {
		FileOutputStream fo = null;
		try {
			if (MjUtil.isNull(path)) {
				fo = new FileOutputStream(this.path);
			} else {
				//另存为
				fo = new FileOutputStream(path);
			}
			//保存
			this.docx.write(fo);
			//关闭
			if (close) {
				close();
			}
		} catch (Exception e) {
			close();
			throw new Exception("保存失败!", e);
		} finally {
			if (fo != null) {
				fo.close();
			}
		}
	}

	//将替换后的文本写入段落
	private void writeText(XWPFParagraph paragraph,
						   String str) throws Exception {
		boolean tag = false;
		for (XWPFRun run : paragraph.getRuns()) {
			if (tag) {
				//清除多余的run
				run.setText("", 0);
			} else {
				//要深入到run替换内容才能保证样式一致
				run.setText(str, 0);
				tag = true;
			}
		}
	}

	//获取单元格
	private XWPFTableCell getCell(XWPFTable table,
								  int row,
								  int col) throws Exception {
		XWPFTableRow tableRow = table.getRow(row);
		return tableRow.getCell(col);
	}

	//关闭文件
	private void close() throws Exception {
		if (this.fi != null) {
			this.fi.close();
			this.fi = null;
		}
	}
}

  • 15
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值