package cn.rao.WordUtils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.BodyElementType;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
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.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTInd;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTSpacing;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
public class WordUtils {
/**
* 循环填充表格内容
* @param xwpfDocument
* @param params
* @param tableIndex
* @throws Exception
*/
public static void insertValueToTable(XWPFTable table, Integer startRow, List<Map<String,String>> params, Boolean deleteTemplateCol) throws Exception {
try {
List<XWPFTableRow> rows = table.getRows();
if (rows.size() < 2) {
throw new Exception("tableIndex对应表格应该为2行");
}
// 模板的那一行
XWPFTableRow tmpRow = rows.get(startRow-1);
List<XWPFTableCell> tmpCells = null;
List<XWPFTableCell> cells = null;
XWPFTableCell tmpCell = null;
tmpCells = tmpRow.getTableCells();
String cellText = null;
for (int i = 0, len = params.size(); i < len; i++) {
Map<String, String> map = params.get(i);
// 创建新的一行
XWPFTableRow row = table.insertNewTableRow(i+startRow);
row.getCtRow().setTrPr(tmpRow.getCtRow().getTrPr());
// 获取模板的行高 设置为新一行的行高
row.setHeight(tmpRow.getHeight());
addTemplateRow(tmpRow, row);
cells = row.getTableCells();
for (int k = 0, klen = cells.size(); k < klen; k++) {
tmpCell = tmpCells.get(k);
XWPFTableCell cell = cells.get(k);
cellText = tmpCell.getText();
if (StringUtils.isNotBlank(cellText)) {
//转换为mapkey对应的字段
if (map.containsKey(cellText)) {
// copyCellAndSetValue(tmpCell, cell, map.get(cellText));
setCellText(tmpCell, cell, map.get(cellText));
}
}
}
}
// 删除模版行
if(deleteTemplateCol) {
table.removeRow(1);
}
}catch (Exception e){
e.printStackTrace();
throw e;
}
}
/**
*
* @Title: insertValueToTable
* @Description: 向表格中写入数据
* @param table
* @param rowNum
* @param params
* @throws Exception 参数描述
* @return void 返回类型
* @throws
*/
public static void insertValueToTable(XWPFTable table, Integer rowNum, Map<String,String> params) throws Exception{
try {
List<XWPFTableRow> rows = table.getRows();
XWPFTableRow row = rows.get(rowNum-1);
List<XWPFTableCell> cells = row.getTableCells();
for (int k = 0, klen = cells.size(); k < klen; k++) {
XWPFTableCell cell = cells.get(k);
String cellText = cell.getText();
if (StringUtils.isNotBlank(cellText)) {
//转换为mapkey对应的字段
if (params.containsKey(cellText)) {
XWPFParagraph cellP = cell.getParagraphs().get(0);
XWPFRun cellR = cellP.getRuns().get(0);
cellR.setText(params.get(cellText), 0);
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
/**
* 添加模板行
* @param sourceRow
* @param targetRow
*/
private static void addTemplateRow(XWPFTableRow sourceRow, XWPFTableRow targetRow) {
List<XWPFTableCell> cellList = sourceRow.getTableCells();
if (null == cellList) {
return;
}
XWPFTableCell targetCell = null;
for (XWPFTableCell sourceCell : cellList) {
targetCell = targetRow.addNewTableCell();
//列属性
targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
//段落属性
if(sourceCell.getParagraphs()!=null&&sourceCell.getParagraphs().size()>0){
targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr());
if(sourceCell.getParagraphs().get(0).getRuns()!=null&&sourceCell.getParagraphs().get(0).getRuns().size()>0){
XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
cellR.setText(sourceCell.getText());
cellR.setBold(sourceCell.getParagraphs().get(0).getRuns().get(0).isBold());
}else{
targetCell.setText(sourceCell.getText());
}
}else{
targetCell.setText(sourceCell.getText());
}
}
}
/**
* 复制模板行的属性并填充单元格
* @param tmpCell
* @param cell
* @param text
* @throws Exception
*/
private static void setCellText(XWPFTableCell tmpCell, XWPFTableCell cell,String text) {
cell.setColor(tmpCell.getColor());
CTTc cttc2 = tmpCell.getCTTc();
CTTcPr ctPr2 = cttc2.getTcPr();
CTTc cttc = cell.getCTTc();
CTTcPr ctPr = cttc.addNewTcPr();
if (ctPr2.getTcW() != null) {
ctPr.addNewTcW().setW(ctPr2.getTcW().getW());
}
if (ctPr2.getVAlign() != null) {
ctPr.addNewVAlign().setVal(ctPr2.getVAlign().getVal());
}
if (ctPr2.getTcBorders() != null) {
ctPr.setTcBorders(ctPr2.getTcBorders());
}
XWPFParagraph tmpParagraph = tmpCell.getParagraphs().get(0);
XWPFParagraph cellP = cell.getParagraphs().get(0);
// 模板行
XWPFRun tmpRun = null;
if (tmpParagraph.getRuns() != null && tmpParagraph.getRuns().size() > 0) {
// 第一行为模板行
tmpRun = tmpParagraph.getRuns().get(0);
}
// 写入数据
// XWPFRun cellR = cellP.createRun();
// cellR.setText(text);
XWPFRun cellR = null;
if(cellP.getRuns().size() == 0) {
cellR = cellP.createRun();
}else {
cellR = cellP.getRuns().get(0);
}
cellR.setText(text, 0);
// 复制字体信息
if (tmpRun != null) {
if(!cellR.isBold()){
cellR.setBold(tmpRun.isBold());
}
cellR.setItalic(tmpRun.isItalic());
cellR.setUnderline(tmpRun.getUnderline());
cellR.setColor(tmpRun.getColor());
cellR.setTextPosition(tmpRun.getTextPosition());
if (tmpRun.getFontSize() != -1) {
cellR.setFontSize(tmpRun.getFontSize());
}
if (tmpRun.getFontFamily() != null) {
cellR.setFontFamily(tmpRun.getFontFamily());
}
if (tmpRun.getCTR() != null) {
if (tmpRun.getCTR().isSetRPr()) {
CTRPr tmpRPr = tmpRun.getCTR().getRPr();
if (tmpRPr.isSetRFonts()) {
CTFonts tmpFonts = tmpRPr.getRFonts();
CTRPr cellRPr = cellR.getCTR().isSetRPr() ? cellR
.getCTR().getRPr() : cellR.getCTR().addNewRPr();
CTFonts cellFonts = cellRPr.isSetRFonts() ? cellRPr
.getRFonts() : cellRPr.addNewRFonts();
cellFonts.setAscii(tmpFonts.getAscii());
cellFonts.setAsciiTheme(tmpFonts.getAsciiTheme());
cellFonts.setCs(tmpFonts.getCs());
cellFonts.setCstheme(tmpFonts.getCstheme());
cellFonts.setEastAsia(tmpFonts.getEastAsia());
cellFonts.setEastAsiaTheme(tmpFonts.getEastAsiaTheme());
cellFonts.setHAnsi(tmpFonts.getHAnsi());
cellFonts.setHAnsiTheme(tmpFonts.getHAnsiTheme());
}
}
}
}
// 复制段落信息
cellP.setAlignment(tmpParagraph.getAlignment());
cellP.setVerticalAlignment(tmpParagraph.getVerticalAlignment());
cellP.setBorderBetween(tmpParagraph.getBorderBetween());
cellP.setBorderBottom(tmpParagraph.getBorderBottom());
cellP.setBorderLeft(tmpParagraph.getBorderLeft());
cellP.setBorderRight(tmpParagraph.getBorderRight());
cellP.setBorderTop(tmpParagraph.getBorderTop());
cellP.setPageBreak(tmpParagraph.isPageBreak());
if (tmpParagraph.getCTP() != null) {
if (tmpParagraph.getCTP().getPPr() != null) {
CTPPr tmpPPr = tmpParagraph.getCTP().getPPr();
CTPPr cellPPr = cellP.getCTP().getPPr() != null ? cellP
.getCTP().getPPr() : cellP.getCTP().addNewPPr();
// 复制段落间距信息
CTSpacing tmpSpacing = tmpPPr.getSpacing();
if (tmpSpacing != null) {
CTSpacing cellSpacing = cellPPr.getSpacing() != null ? cellPPr
.getSpacing() : cellPPr.addNewSpacing();
if (tmpSpacing.getAfter() != null) {
cellSpacing.setAfter(tmpSpacing.getAfter());
}
if (tmpSpacing.getAfterAutospacing() != null) {
cellSpacing.setAfterAutospacing(tmpSpacing
.getAfterAutospacing());
}
if (tmpSpacing.getAfterLines() != null) {
cellSpacing.setAfterLines(tmpSpacing.getAfterLines());
}
if (tmpSpacing.getBefore() != null) {
cellSpacing.setBefore(tmpSpacing.getBefore());
}
if (tmpSpacing.getBeforeAutospacing() != null) {
cellSpacing.setBeforeAutospacing(tmpSpacing
.getBeforeAutospacing());
}
if (tmpSpacing.getBeforeLines() != null) {
cellSpacing.setBeforeLines(tmpSpacing.getBeforeLines());
}
if (tmpSpacing.getLine() != null) {
cellSpacing.setLine(tmpSpacing.getLine());
}
if (tmpSpacing.getLineRule() != null) {
cellSpacing.setLineRule(tmpSpacing.getLineRule());
}
}
// 复制段落缩进信息
CTInd tmpInd = tmpPPr.getInd();
if (tmpInd != null) {
CTInd cellInd = cellPPr.getInd() != null ? cellPPr.getInd()
: cellPPr.addNewInd();
if (tmpInd.getFirstLine() != null) {
cellInd.setFirstLine(tmpInd.getFirstLine());
}
if (tmpInd.getFirstLineChars() != null) {
cellInd.setFirstLineChars(tmpInd.getFirstLineChars());
}
if (tmpInd.getHanging() != null) {
cellInd.setHanging(tmpInd.getHanging());
}
if (tmpInd.getHangingChars() != null) {
cellInd.setHangingChars(tmpInd.getHangingChars());
}
if (tmpInd.getLeft() != null) {
cellInd.setLeft(tmpInd.getLeft());
}
if (tmpInd.getLeftChars() != null) {
cellInd.setLeftChars(tmpInd.getLeftChars());
}
if (tmpInd.getRight() != null) {
cellInd.setRight(tmpInd.getRight());
}
if (tmpInd.getRightChars() != null) {
cellInd.setRightChars(tmpInd.getRightChars());
}
}
}
}
}
/**
* 合并行
* @param table
* @param col
* @param fromRow
* @param toRow
*/
public static void mergeCellVertically(XWPFTable table, int col, int fromRow, int toRow) {
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
CTVMerge vmerge = CTVMerge.Factory.newInstance();
if (rowIndex == fromRow) {
vmerge.setVal(STMerge.RESTART);
} else {
vmerge.setVal(STMerge.CONTINUE);
}
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
CTTcPr tcPr = cell.getCTTc().getTcPr();
if (tcPr != null) {
tcPr.setVMerge(vmerge);
} else {
tcPr = CTTcPr.Factory.newInstance();
tcPr.setVMerge(vmerge);
cell.getCTTc().setTcPr(tcPr);
}
}
}
/**
* 合并列
*
* @param table
* @param row
* @param fromCell
* @param toCell
*/
public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
if (cellIndex == fromCell) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
//cellCount为表格总列数
int cellCount = table.getRow(row).getTableCells().size();
Integer width = (toCell - fromCell + 1) / cellCount * table.getCTTbl().getTblPr().getTblW().getW().intValue();
cell.getCTTc().getTcPr().addNewTcW().setW(BigInteger.valueOf(width));
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
}
}
}
/**
*
* @Title: insertTemplateTableCol
* @Description: 添加表格列
* @param table 表格
* @param datas 待写入数据
* @return void 返回类型
* @throws
*/
public static void insertTemplateTableCol(XWPFTable table, List<List<String>> datas) {
List<XWPFTableRow> rows = table.getRows();
for(int k = 0; k < datas.size(); k++) {
List<String> data = datas.get(k);
for(int i = 0; i < rows.size(); i++) {
XWPFTableRow row = rows.get(i);
XWPFTableCell tmpCell = row.getCell(0);
XWPFTableCell cell = row.createCell();
setCellText(tmpCell, cell, data.get(i));
}
}
}
/**
* 替换文本中的占位符
* @param document
* @param textMap
*/
public static void changeText(XWPFDocument document, Map<String, Object> textMap) {
// 获取段落集合
// 返回包含页眉或页脚文本的段落
List<XWPFParagraph> paragraphs = document.getParagraphs();
// 增强型for循环语句,前面一个为声明语句,后一个为表达式
for (XWPFParagraph paragraph : paragraphs) {
// 判断此段落是否需要替换
String text = paragraph.getText();// 检索文档中的所有文本
if (checkText(text)) {
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
// 替换模板原来位置
Object ob = changeValue(run.toString(), textMap);
if (ob instanceof String) {
if (textMap.containsKey(run.toString())) {
run.setText((String) ob, 0);
}
}
}
}
}
}
/**
*
* @Title: insertTemplatePlaceholder
* @Description: 插入模板表占位符
* @param key 参数描述
* @return void 返回类型
* @throws
*/
public static void insertTemplatePlaceholder(XWPFDocument document,String key, List<List<String>> placeholderList) {
List<XWPFParagraph> paragraphList = document.getParagraphs();
if (paragraphList != null && paragraphList.size() > 0) {
XWPFParagraph paragraphUse = null;
for (XWPFParagraph paragraph : paragraphList) {
List<XWPFRun> runs = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++) {
String text = runs.toString();
if (text.indexOf(key) >= 0) {
paragraphUse = paragraph;
break;
}
}
}
// 在list中增加paragraph 会报异常
// 在cursor位置插入段落,按顺序添加
for(int i=0; i< placeholderList.size(); i++) {
List<String> placeholders = placeholderList.get(i);
for(String placeholder :placeholders) {
paragraphUse = insertPlaceholder(document, paragraphUse, placeholder);
}
}
}
}
/**
*
* @Title: insertPlaceholder
* @Description: 插入占位符
* @param document
* @param sourceParagraph
* @param key
* @return 参数描述
* @return XWPFParagraph 返回类型
* @throws
*/
private static XWPFParagraph insertPlaceholder(XWPFDocument document, XWPFParagraph sourceParagraph, String key) {
XmlCursor cursor = sourceParagraph.getCTP().newCursor();
cursor.toNextSibling();
XWPFParagraph paragraphNew = document.insertNewParagraph(cursor);
paragraphNew.getCTP().setPPr(sourceParagraph.getCTP().getPPr());
XWPFRun xwpfRun = paragraphNew.createRun();
xwpfRun.setText(key);
xwpfRun.setFontSize(sourceParagraph.getRuns().get(0).getFontSize());
xwpfRun.setFontFamily(sourceParagraph.getRuns().get(0).getFontFamily());
return paragraphNew;
}
/* 检查文本中是否包含指定的字符(此处为“$”),并返回值 */
private static boolean checkText(String text) {
boolean check = false;
if (text.contains("$")) {
check = true;
}
return check;
}
private static Object changeValue(String value, Map<String, Object> textMap) {
Set<Map.Entry<String, Object>> textSets = textMap.entrySet();
Object valu = "";
for (Map.Entry<String, Object> textSet : textSets) {
// 匹配模板与替换值 格式${key}
String key = textSet.getKey();
if (value.contains(key)) {
valu = textSet.getValue();
}
}
return valu;
}
/**
*
* @Title: reOpen
* @Description: 重新打开文档
* @param document
* @param destPath
* @return
* @throws Exception 参数描述
* @return XWPFDocument 返回类型
* @throws
*/
public static XWPFDocument reOpen(XWPFDocument document, String destPath)throws Exception {
try {
FileOutputStream out = new FileOutputStream(destPath);
document.write(out);
FileInputStream is = new FileInputStream(destPath);
XWPFDocument newDocument = new XWPFDocument(is);
return newDocument;
} catch (IOException e) {
throw new Exception(" 重新打开模板文档失败:", e);
}
}
/**
*
* @Title: formTime
* @Description: 获取格式化时间字符串
* @param type
* @return 参数描述
* @return String 返回类型
* @throws
*/
public static String formTime(String type) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(type);
Date date = new Date(System.currentTimeMillis());
String timeString = simpleDateFormat.format(date);
return timeString;
}
/**
* 删除占位符或占位符所在的段落
* @param document
* @param placeholders
* @param deleteParagraph 是否删除段落
*/
public static void deletePlaceholder(XWPFDocument document, List<String> placeholders, Boolean deleteParagraph) {
// 获取段落集合
// 返回包含页眉或页脚文本的段落
List<XWPFParagraph> paragraphs = document.getParagraphs();
List<IBodyElement> listBe = document.getBodyElements();
List<Integer> runList = new ArrayList<>();
int n = 0;
for(int i = 0; i < listBe.size(); i++){
XWPFParagraph paragraph = paragraphs.get(n);
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
// 替换模板原来位置
String runText = run.toString();
if(placeholders.contains(runText)) {
if(!deleteParagraph) {
run.setText("", 0);
}else {
runList.add(i);
}
}
}
n++;
//非文字段落n-1
if(listBe.get(i).getElementType() != BodyElementType.PARAGRAPH){
n--;
}
}
//遍历list删除
for(int i = runList.size() - 1; i >= 0; i--){
document.removeBodyElement(runList.get(i));
}
}
}
<project xmlns="http:///POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http:///POM/4.0.0 http:///xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.rao</groupId>
<artifactId>WordUtils</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>WordUtils</name>
<url>http://</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.16</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/org.apache.commons.lang -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>com.aspose</groupId>
<artifactId>aspose-words</artifactId>
<version>15.8.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/aspose-words-15.8.0-jdk16.jar</systemPath>
</dependency>
</dependencies>
</project>
需要注意的点:
1、向word中插入动态表格步骤
(1)在word模板中定义占位符,该占位符表示表格插入的行
(2)获取word 模板中需要的模板表,并定义占位符与模板表的对应关系
(3)遍历word模板,查找模板表的占位符,并替换为模板表
此步必须)
(5)填写数据
(6)删除占位符,删除占位符所在的段落
2、向word中插入占位符
插入占位符时不能直接在word中输入,应该预先在txt文档中输入完整的占位符,如:${addTable},然后将整个占位符字符串拷贝到word中