这是一个word解析类,因为我做的系统用到了而且没有可用的帮助类,只能自己写。之前的实现方式是freemarker 模板解析。但是这次要求用poi不在使用freemarker。实现功能比较少,主要是满足开发需求即可,没有实现其它功能。实现功能如下:
1、word内文本内容解析
2、word内表格内容解析
3、word内图片内容解析
4、word脚注内容解析
功能实现的比较匆忙没有好好设计,如果可以将图标,图片,脚注等设置为实体类,便于配置管理。
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Base64;
import java.util.List;
import java.util.Properties;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFFootnote;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFPicture;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal;
import org.springframework.util.PropertyPlaceholderHelper;
import com.alibaba.cloud.commons.lang.StringUtils;
/**
* 通过word模板生成新的word工具类
**
*/
public class WordUtil {
public static final PropertyPlaceholderHelper helper = new PropertyPlaceholderHelper("${", "}");
/**
* 根据模板生成新word文档 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
*
* @param textMap 需要替换的信息集合
* @return 成功返回true,失败返回false
*/
public static void changWord(InputStream inputStream, Properties properties, int height, int width) {
// InputStream in = null;
try {
// 获取docx解析对象
XWPFDocument document = new XWPFDocument(inputStream);
// 解析替换文本段落对象
WordUtil.changeText(document, properties);
// 解析替换表格对象
WordUtil.changeTable(document, properties);
// 替换文本中的图片
WordUtil.changePicture(document, properties, height, width);
// 脚注/尾注解析 footnote
WordUtil.changeFootNote(document, properties);
File file = new File("I://实体文件.docx");
FileOutputStream stream = new FileOutputStream(file);
document.write(stream);
stream.close();
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 尾注解析
*
* @param document
* @param properties
*/
public static void changeFootNote(XWPFDocument document, Properties properties) {
List
for (XWPFFootnote footnote : footNoteList) {
List
for (XWPFParagraph paragraph : paragraphs) {
String text = paragraph.getText();
if (checkText(text)) {
List
String key = keyParam(runs);
for (XWPFRun run : runs) {
run.setText("", 0);
}
// 替换模板原来位置
String value = changeValue(key, properties);
// 字符串中有可能是图片转换的字符串
if (StringUtils.isNotEmpty(value)) {
runs.get(0).setText(value, 0);
}
}
}
}
}
/***
* 指定替换模板中的图片
*
* @param document
* @param filePath
* @param height
* @param width
*/
public static void changePicture(XWPFDocument document, Properties properties, Integer height, Integer width) {
// 获取段落集合
List
for (XWPFParagraph paragraph : paragraphs) {
// 判断此段落时候需要进行替换
String text = paragraph.getText();
if (checkText(text)) {
List
String key = keyParam(runs);
for (XWPFRun run : runs) {
// 字符串中有可能是图片转换的字符串
String value = changeValue(key, properties);
if (value.startsWith("data:image")) {
byte[] imageBytes = Base64.getDecoder().decode(value.split(",")[1]); // 获取Base64编码后的图像数据部分
try(ByteArrayInputStream in = new ByteArrayInputStream(imageBytes); ){// 创建ByteArrayInputStream对象
// 添加图片
XWPFPicture xwpfPicture = run.addPicture(in, XWPFDocument.PICTURE_TYPE_JPEG, "图片1.jpg",
Units.toEMU(width), Units.toEMU(height));
// 为图片添加边框
xwpfPicture.getCTPicture().getSpPr().addNewLn().addNewSolidFill().addNewSchemeClr()
.setVal(STSchemeColorVal.Enum.forString("tx1"));
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
}
public static String keyParam(List
if (runs.isEmpty()) {
return "";
}
StringBuffer st = new StringBuffer();
// 转换为一个字符串 [${E_002, 1, }${E_002, 2, }${E_002, 3, }]
for (XWPFRun run : runs) {
st.append(run.text());
}
return st.toString().replace(",", "");
}
/**
* 替换段落文本
*
* @param document docx解析对象
* @param textMap 需要替换的信息集合
*/
public static void changeText(XWPFDocument document, Properties properties) {
// 获取段落集合
List
for (XWPFParagraph paragraph : paragraphs) {
// 判断此段落时候需要进行替换
String text = paragraph.getText();
if (checkText(text)) {
List
for (XWPFRun run : runs) {
// 替换模板原来位置
String value = changeValue(run.toString(), properties);
// 字符串中有可能是图片转换的字符串
if (StringUtils.isNotEmpty(value) && !value.startsWith("data:image")) {
run.setText(value, 0);
}
}
}
}
}
/**
* 替换表格对象方法
*
* @param document docx解析对象
* @param textMap 需要替换的信息集合
*/
public static void changeTable(XWPFDocument document, Properties properties) {
// 获取表格对象集合
List
for (int i = 0; i < tables.size(); i++) {
// 只处理行数大于等于2的表格,且不循环表头
XWPFTable table = tables.get(i);
if (table.getRows().size() > 1) {
// 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
if (checkText(table.getText())) {
List
// 遍历表格,并替换模板
eachTable(rows, properties);
}
}
}
}
/**
* 遍历表格
*
* @param rows 表格行对象
* @param textMap 需要替换的信息集合
*/
public static void eachTable(List
for (XWPFTableRow row : rows) {
List
for (XWPFTableCell cell : cells) {
// 判断单元格是否需要替换
if (checkText(cell.getText())) {
// 基本一个单元格,都是size=1,如果预防意外,可以增加判断,或者添加循环
List
// System.out.println(String.format("text:%s,paragraphs:%d",cell.getText(),
// paragraphs.size()));
// for (XWPFParagraph paragraph : paragraphs) {
// List
// 替换模板原来位置
XWPRunValue(paragraphs.get(0).getRuns(), properties);
// }
}
}
}
}
/**
* 这个方法是一次处理一个单元格,一个单元格内,被解析成了 XWPFRun, 只给第一个 XWPFRun赋值即可,其它都赋值""
*
* @param runs
* @param textMap
*/
public static void XWPRunValue(List
if (runs.size() == 1) {
runs.get(0).setText(changeValue(runs.get(0).toString(), properties), 0);
return;
}
StringBuffer st = new StringBuffer();
// 转换为一个字符串 [${E_002, 1, }${E_002, 2, }${E_002, 3, }]
for (XWPFRun run : runs) {
//
st.append(run.text());
run.setText("", 0);
}
String value = st.toString().replace(",", "");
value = changeValue(value, properties);
// 一次性替换全部的值
runs.get(0).setText(value, 0);
}
/**
* 判断文本中时候包含$
*
* @param text 文本
* @return 包含返回true,不包含返回false
*/
public static boolean checkText(String text) {
return (text.indexOf("$") != -1);
}
/**
* 匹配传入信息集合与模板
*
* @param value 模板需要替换的区域
* @param textMap 传入信息集合
* @return 模板需要替换区域信息集合对应值
*/
public static String changeValue(String value, Properties properties) {
if (!checkText(value)) {
return value;
}
return helper.replacePlaceholders(value, properties);
}
public static void main(String[] args) throws Exception {
// 从FTP读取文件模板
InputStream is = new FileInputStream(new File("I://模板文件.docx"));
// 填充文本和表格需要替换的数据
Properties properties = new Properties();
properties.put("E_0001", "2000年01月01日");
properties.put("E_0002", "第一行");
properties.put("E_0003", "脚注解析异常");
// 图片字符串
properties.put("P01", "data:image/jpg;base64,"+"图片转换的字符串") ;
WordUtil.changWord(is, properties, 140, 400);
}
}