项目需求:需要将数据按照一定的格式导出成word文档。文本替换,表格循环(表格内部行循环,整个表格循环),插入图片等。
参考连接:https://blog.csdn.net/u012775558/article/details/79678701
在该博客的基础上加入了插入图片,换行显示等功能。
<!-- 导出word需要用的包 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.1</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.1</version>
</dependency>
图片用XWPFDocument无法实现addPicture,POI自身有bug,会发生已经生成word文档,但office打不开文件,或者图片已经插入word文档,但显示不了,解决方法是自己写一个插入图片的方法,不用addPicture方法,代码如下:
/**
* insert Picture
* @param document
* @param filePath
* @param inline
* @param width
* @param height
* @throws InvalidFormatException
* @throws FileNotFoundException
*/
private static void insertPicture(XWPFDocument document, String filePath,
CTInline inline, int width,
int height,int format) throws InvalidFormatException, FileNotFoundException {
document.addPictureData(new FileInputStream(filePath),XWPFDocument.PICTURE_TYPE_PNG);
int id = document.getAllPictures().size() - 1;
final int EMU = 9525;
width *= EMU;
height *= EMU;
String blipId = document.addPictureData(new FileInputStream(filePath),format);
String picXml = getPicXml(blipId, width, height);
XmlToken xmlToken = null;
try {
xmlToken = XmlToken.Factory.parse(picXml);
} catch (XmlException xe) {
xe.printStackTrace();
}
inline.set(xmlToken);
inline.setDistT(0);
inline.setDistB(0);
inline.setDistL(0);
inline.setDistR(0);
CTPositiveSize2D extent = inline.addNewExtent();
extent.setCx(width);
extent.setCy(height);
CTNonVisualDrawingProps docPr = inline.addNewDocPr();
docPr.setId(id);
docPr.setName("IMG_" + id);
docPr.setDescr("IMG_" + id);
}
/**
* get the xml of the picture
* @param blipId
* @param width
* @param height
* @return
*/
private static String getPicXml(String blipId, int width, int height) {
String picXml =
"" + "" +
" " +
" " +
" " + " + 0 +
"\" name=\"Generated\"/>" + " " +
" " + " " +
" + blipId +
"\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
" " + " " +
" " + " " +
" " + " " +
" " +
" + width + "\" cy=\"" + height +
"\"/>" + " " +
" " +
" " + " " +
" " + " " +
" " + "";
return picXml;
}
下面是根据模板生成word文件的具体代码:
/**
* 根据dataMap对word文件中的标签进行替换;
* !!!!***需要注意dataMap的数据格式***!!!!
* 对于需要替换的普通标签数据标签(不需要循环)-----必须在dataMap中存储一个key为parametersMap的map,
* 来存储这些不需要循环生成的数据,比如:表头信息,日期,制表人等。
* 对于需要循环生成的表格数据------key自定义,value为 --ArrayList<Map<String, String>>
* @author Juveniless
* @date 2017年11月27日 下午3:29:27
* @param dataMap
*
*/
public void replaceDocument(Map<String, Object> dataMap) {
if (!dataMap.containsKey("parametersMap")) {
System.out.println("数据源错误--数据源(parametersMap)缺失");
return;
}
@SuppressWarnings("unchecked")
Map<String, Object> parametersMap = (Map<String, Object>) dataMap
.get("parametersMap");
List<IBodyElement> bodyElements = document.getBodyElements();// 所有对象(段落+表格)
int templateBodySize = bodyElements.size();// 标记模板文件(段落+表格)总个数
int curT = 0;// 当前操作表格对象的索引
int curP = 0;// 当前操作段落对象的索引
for (int a = 0; a < templateBodySize; a++) {
IBodyElement body = bodyElements.get(a);
if (BodyElementType.TABLE.equals(body.getElementType())) {// 处理表格
XWPFTable table = body.getBody().getTableArray(curT);
List<XWPFTable> tables = body.getBody().getTables();
table = tables.get(curT);
if (table != null) {
// 处理表格
List<XWPFTableCell> tableCells = table.getRows().get(0).getTableCells();// 获取到模板表格第一行,用来判断表格类型
String tableText = table.getText();// 表格中的所有文本
if (tableText.indexOf("##{foreach") > -1) {
// 查找到##{foreach标签,该表格需要处理循环
if (tableCells.size() != 2
|| tableCells.get(0).getText().indexOf("##{foreach") < 0
|| tableCells.get(0).getText().trim().length() == 0) {
System.out
.println("文档中第"
+ (curT + 1)
+ "个表格模板错误,模板表格第一行需要设置2个单元格,"
+ "第一个单元格存储表格类型(##{foreachTable}## 或者 ##{foreachTableRow}##),第二个单元格定义数据源。");
return;
}
String tableType = tableCells.get(0).getText();
String dataSource = tableCells.get(1).getText();
System.out.println("读取到数据源:"+dataSource);
if (!dataMap.containsKey(dataSource)) {
System.out.println("文档中第" + (curT + 1) + "个表格模板数据源缺失");
return;
}
@SuppressWarnings("unchecked")
List<Map<String, Object>> tableDataList = (List<Map<String, Object>>) dataMap
.get(dataSource);
//整个表格循环
if ("##{foreachTable}##".equals(tableType)) {
// System.out.println("循环生成表格");
addTableInDocFooter(table, tableDataList, parametersMap, 1);
//整个内行循环
} else if ("##{foreachTableRow}##".equals(tableType)) {
// System.out.println("循环生成表格内部的行");
addTableInDocFooter(table, tableDataList, parametersMap, 2);
}
} else if (tableText.indexOf("{") > -1) {
// 没有查找到##{foreach标签,查找到了普通替换数据的{}标签,该表格只需要简单替换
addTableInDocFooter(table, null, parametersMap, 3);
} else {
// 没有查找到任何标签,该表格是一个静态表格,仅需要复制一个即可。
addTableInDocFooter(table, null, null, 0);
}
curT++;
}
} else if (BodyElementType.PARAGRAPH.equals(body.getElementType())) {// 处理段落
// System.out.println("获取到段落");
XWPFParagraph ph = body.getBody().getParagraphArray(curP);
if (ph != null) {
// htmlText = htmlText+readParagraphX(ph);
addParagraphInDocFooter(ph, null, parametersMap, 0);
curP++;
}
}
}
// 处理完毕模板,删除文本中的模板内容
for (int a = 0; a < templateBodySize; a++) {
document.removeBodyElement(0);
}
}
/**
* 根据 模板表格 和 数据list 在word文档末尾生成表格
* @author Juveniless
* @date 2017年12月6日 上午10:12:05
* @param templateTable 模板表格
* @param list 循环数据集
* @param parametersMap 不循环数据集
* @param flag (0为静态表格,1为表格整体循环,2为表格内部行循环,3为表格不循环仅简单替换标签即可)
*
*/
public void addTableInDocFooter(XWPFTable templateTable, List<Map<String, Object>> list,
Map<String, Object> parametersMap, int flag) {
if (flag == 1) {// 表格整体循环
for (Map<String, Object> map : list) {
List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
for (int i = 1; i < templateTableRows.size(); i++) {
XWPFTableRow newCreateRow = newCreateTable.createRow();
CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
/*表格复制时,边框不显示*/
for (int j = 0; j < newCreateRow.getTableCells().size(); j++) {
CTTcBorders tblBorders = newCreateRow.getCell(j).getCTTc().getTcPr().addNewTcBorders();
tblBorders.addNewLeft().setVal(STBorder.NIL);
tblBorders.addNewRight().setVal(STBorder.NIL);
tblBorders.addNewBottom().setVal(STBorder.NIL);
tblBorders.addNewTop().setVal(STBorder.NIL);
newCreateRow.getCell(j).getCTTc().getTcPr().setTcBorders(tblBorders);
}
}
newCreateTable.removeRow(0);// 移除多出来的第一行
document.createParagraph();// 添加回车换行
replaceTable(newCreateTable, map);//替换标签
}
} else if (flag == 2) {// 表格表格内部行循环
XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
List<XWPFTableRow> TempTableRows = templateTable.getRows();// 获取模板表格所有行
int tagRowsIndex = 0;// 标签行indexs
for (int i = 0, size = TempTableRows.size(); i < size; i++) {
String rowText = TempTableRows.get(i).getCell(0).getText();// 获取到表格行的第一个单元格
if (rowText.indexOf("##{foreachRows}##") > -1) {
tagRowsIndex = i;
break;
}
}
/* 复制模板行和标签行之前的行 */
for (int i = 1; i < tagRowsIndex; i++) {
XWPFTableRow newCreateRow = newCreateTable.createRow();
CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行
replaceTableRow(newCreateRow, parametersMap);// 处理不循环标签的替换
}
/* 循环生成模板行 */
XWPFTableRow tempRow = TempTableRows.get(tagRowsIndex + 1);// 获取到模板行
for (int i = 0; i < list.size(); i++) {
XWPFTableRow newCreateRow = newCreateTable.createRow();
CopyTableRow(newCreateRow, tempRow);// 复制模板行
replaceTableRow(newCreateRow, list.get(i));// 处理标签替换
}
/* 复制模板行和标签行之后的行 */
for (int i = tagRowsIndex + 2; i < TempTableRows.size(); i++) {
XWPFTableRow newCreateRow = newCreateTable.createRow();
CopyTableRow(newCreateRow, TempTableRows.get(i));// 复制行
replaceTableRow(newCreateRow, parametersMap);// 处理不循环标签的替换
}
newCreateTable.removeRow(0);// 移除多出来的第一行
document.createParagraph();// 添加回车换行
} else if (flag == 3) {
//表格不循环仅简单替换标签
List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
for (int i = 0; i < templateTableRows.size(); i++) {
XWPFTableRow newCreateRow = newCreateTable.createRow();
CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
}
newCreateTable.removeRow(0);// 移除多出来的第一行
document.createParagraph();// 添加回车换行
replaceTable(newCreateTable, parametersMap);
} else if (flag == 0) {
List<XWPFTableRow> templateTableRows = templateTable.getRows();// 获取模板表格所有行
XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列
for (int i = 0; i < templateTableRows.size(); i++) {
XWPFTableRow newCreateRow = newCreateTable.createRow();
CopyTableRow(newCreateRow, templateTableRows.get(i));// 复制模板行文本和样式到新行
}
newCreateTable.removeRow(0);// 移除多出来的第一行
document.createParagraph();// 添加回车换行
}
}
/**
* 根据 模板段落 和 数据 在文档末尾生成段落
*
* @author Juveniless
* @date 2017年11月27日 上午11:49:42
* @param templateParagraph
* 模板段落
* @param list
* 循环数据集
* @param parametersMap
* 不循环数据集
* @param flag
* (0为不循环替换,1为循环替换)
*
*/
public void addParagraphInDocFooter(XWPFParagraph templateParagraph,
List<Map<String, String>> list, Map<String, Object> parametersMap, int flag) {
if (flag == 0) {
XWPFParagraph createParagraph = document.createParagraph();
// 设置段落样式
createParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
// 移除原始内容
for (int pos = 0; pos < createParagraph.getRuns().size(); pos++) {
createParagraph.removeRun(pos);
}
// 添加Run标签
for (XWPFRun s : templateParagraph.getRuns()) {
XWPFRun targetrun = createParagraph.createRun();
CopyRun(targetrun, s);
}
replaceParagraph(createParagraph, parametersMap);
} else if (flag == 1) {
// 暂无实现
}
}
/**
* 根据map替换段落元素内的{**}标签
* @author Juveniless
* @date 2017年12月4日 下午3:09:00
* @param xWPFParagraph
* @param parametersMap
*
*/
public void replaceParagraph(XWPFParagraph xWPFParagraph, Map<String, Object> parametersMap) {
List<XWPFRun> runs = xWPFParagraph.getRuns();
String xWPFParagraphText = xWPFParagraph.getText();
String regEx = "\\{.+?\\}";
Pattern pattern = Pattern.compile(regEx);
Matcher matcher = pattern.matcher(xWPFParagraphText);//正则匹配字符串{****}
if (matcher.find()) {
// 查找到有标签才执行替换
int beginRunIndex = xWPFParagraph.searchText("{", new PositionInParagraph()).getBeginRun();// 标签开始run位置
int endRunIndex = xWPFParagraph.searchText("}", new PositionInParagraph()).getEndRun();// 结束标签
StringBuffer key = new StringBuffer();
if (beginRunIndex == endRunIndex) {
// {**}在一个run标签内
XWPFRun beginRun = runs.get(beginRunIndex);
String beginRunText = beginRun.text();
int beginIndex = beginRunText.indexOf("{");
int endIndex = beginRunText.indexOf("}");
int length = beginRunText.length();
if (beginIndex == 0 && endIndex == length - 1) {
// 该run标签只有{**}
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 设置文本
key.append(beginRunText.substring(1, endIndex));
String value = getValueBykey(key.toString(),parametersMap);
if (value.endsWith("jpg") || value.endsWith(".png") || value.endsWith(".jpeg")){
int width = Units.toEMU(410);
int height = Units.toEMU(200);
String heightKey;
String imageWidth;
if (key.indexOf("**")>-1){
//截取**号
String key1 = key.toString().replaceAll("\\*","");
imageWidth = getValueBykey(key1+"Width",parametersMap);
heightKey = getValueBykey(key1+"Height",parametersMap);
}else {
String widthKey = key.toString()+"Width";
imageWidth = getValueBykey(widthKey,parametersMap);
heightKey = getValueBykey(key.toString()+"Height",parametersMap);
}
if (imageWidth!=null && imageWidth.length()>0){
width = Integer.parseInt(imageWidth);
}
if (heightKey!=null && heightKey.length()>0){
height = Integer.parseInt(heightKey);
}
try {
String fileExt = value.substring(value.lastIndexOf(".",value.length()));
int format = readImageExt(fileExt);
//insertNewRun.addPicture(new FileInputStream(value),format,"", Units.toEMU(width),Units.toEMU(height));
// String picId = document.addPictureData(new FileInputStream(value),format);
// int id2=document.getAllPackagePictures().size()+1;
//
// document.createPicture(picId,id2,width,height);
//判断图片是否存在
File file = new File(value);
if (file.exists()){
CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline();
try {
insertPicture(document,value,inline,width,height,XWPFDocument.PICTURE_TYPE_JPEG);
document.createParagraph();// 添加回车换行
}catch (Exception e){
e.printStackTrace();
}
}else {
insertNewRun.setText("");
}
//insertNewRun.addBreak();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else {
insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
}
xWPFParagraph.removeRun(beginRunIndex + 1);
} else {
// 该run标签为**{**}** 或者 **{**} 或者{**}**,替换key后,还需要加上原始key前后的文本
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 设置文本
key.append(beginRunText.substring(beginRunText.indexOf("{")+1, beginRunText.indexOf("}")));
String textString=beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(),parametersMap)
+ beginRunText.substring(endIndex + 1);
insertNewRun.setText(textString);
xWPFParagraph.removeRun(beginRunIndex + 1);
}
}else {
// {**}被分成多个run
//先处理起始run标签,取得第一个{key}值
XWPFRun beginRun = runs.get(beginRunIndex);
String beginRunText = beginRun.text();
int beginIndex = beginRunText.indexOf("{");
if (beginRunText.length()>1 ) {
key.append(beginRunText.substring(beginIndex+1));
}
ArrayList<Integer> removeRunList = new ArrayList<Integer>();//需要移除的run
//处理中间的run
for (int i = beginRunIndex + 1; i < endRunIndex; i++) {
XWPFRun run = runs.get(i);
String runText = run.text();
key.append(runText);
removeRunList.add(i);
}
// 获取endRun中的key值
XWPFRun endRun = runs.get(endRunIndex);
String endRunText = endRun.text();
int endIndex = endRunText.indexOf("}");
//run中**}或者**}**
if (endRunText.length()>1 && endIndex!=0) {
key.append(endRunText.substring(0,endIndex));
}
//*******************************************************************
//取得key值后替换标签
//先处理开始标签
if (beginRunText.length()==2 ) {
// run标签内文本{
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 设置文本
insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
}else {
// 该run标签为**{**或者 {** ,替换key后,还需要加上原始key前的文本
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 设置文本
String textString=beginRunText.substring(0,beginRunText.indexOf("{"))+getValueBykey(key.toString(),parametersMap);
if (key.indexOf("**foreachimage**")>-1){
List<Map<String,String>> list = (List<Map<String, String>>) parametersMap.get("**foreachimage**");
for (Map<String,String> map:list){
String name = map.get("imageName");
insertNewRun.setText(name);
insertNewRun.addBreak();
String image = map.get("image");
int width = Units.toEMU(410);
int height = Units.toEMU(200);
String heightKey;
String imageWidth;
if (key.indexOf("**")>-1){
//截取**号
String key1 = key.toString().replaceAll("\\*","");
imageWidth = getValueBykey(key1+"Width",parametersMap);
heightKey = getValueBykey(key1+"Height",parametersMap);
}else {
String widthKey = key.toString()+"Width";
imageWidth = getValueBykey(widthKey,parametersMap);
heightKey = getValueBykey(key.toString()+"Height",parametersMap);
}
if (imageWidth!=null && imageWidth.length()>0){
width = Integer.parseInt(imageWidth);
}
if (heightKey!=null && heightKey.length()>0){
height = Integer.parseInt(heightKey);
}
try {
//document.createParagraph();// 添加回车换行
String fileExt = textString.substring(textString.lastIndexOf(".",textString.length()));
//得到图片格式
int format = readImageExt(fileExt);
File file = new File(textString);
if (file.exists()) {
// String picId = document.addPictureData(new FileInputStream(textString),format);
// int id2=document.getAllPackagePictures().size()+1;
//
// document.createPicture(picId,id2,width,height);
CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline();
insertPicture(document,textString,inline,width,height,format);
}else {
insertNewRun.setText("");
}
/* insertNewRun.addPicture(new FileInputStream(textString),format,"", Units.toEMU(width),Units.toEMU(height));*/
insertNewRun.addBreak();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}else
// System.out.println(">>>>>"+textString);
//分行处理
if(textString.contains("@"))
{
String[] textStrings = textString.split("@");
for(int i = 0; i < textStrings.length;i++)
{
//System.out.println(">>>>>textStrings>>"+textStrings[i]);
insertNewRun.setText(textStrings[i]);
//insertNewRun.addCarriageReturn();
insertNewRun.addBreak();//换行
}
}
else if(textString.endsWith(".png") || textString.endsWith(".jpg") || textString.endsWith(".jpeg"))
{
int width = Units.toEMU(410);
int height = Units.toEMU(200);
String heightKey;
String imageWidth;
if (key.indexOf("**")>-1){
//截取**号
String key1 = key.toString().replaceAll("\\*","");
imageWidth = getValueBykey(key1+"Width",parametersMap);
heightKey = getValueBykey(key1+"Height",parametersMap);
}else {
String widthKey = key.toString()+"Width";
imageWidth = getValueBykey(widthKey,parametersMap);
heightKey = getValueBykey(key.toString()+"Height",parametersMap);
}
if (imageWidth!=null && imageWidth.length()>0){
width = Integer.parseInt(imageWidth);
}
if (heightKey!=null && heightKey.length()>0){
height = Integer.parseInt(heightKey);
}
try {
String fileExt = textString.substring(textString.lastIndexOf(".",textString.length()));
//判断图片格式
int format = readImageExt(fileExt);
File file = new File(textString);
if (file.exists()){
CTInline inline = insertNewRun.getCTR().addNewDrawing().addNewInline();
try { insertPicture(document,textString,inline,width,height,XWPFDocument.PICTURE_TYPE_JPEG);
document.createParagraph();// 添加回车换行
}catch (Exception e){
e.printStackTrace();
}
document.createParagraph();// 添加回车换行
}else {
insertNewRun.setText("");
}
//insertNewRun.addBreak();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
insertNewRun.setText(textString);
}
xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
}
//处理结束标签
if (endRunText.length()==1 ) {
// run标签内文本只有}
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
// 设置文本
insertNewRun.setText("");
xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
}else {
// 该run标签为**}**或者 }** 或者**},替换key后,还需要加上原始key后的文本
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(endRunIndex);
insertNewRun.getCTR().setRPr(endRun.getCTR().getRPr());
// 设置文本
String textString=endRunText.substring(endRunText.indexOf("}")+1);
insertNewRun.setText(textString);
xWPFParagraph.removeRun(endRunIndex + 1);//移除原始的run
}
//处理中间的run标签
for (int i = 0; i < removeRunList.size(); i++) {
XWPFRun xWPFRun = runs.get(removeRunList.get(i));//原始run
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));
insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
insertNewRun.setText("");
xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
}
}// 处理${**}被分成多个run
replaceParagraph( xWPFParagraph, parametersMap);
}//if 有标签
}
/**
* 复制表格行XWPFTableRow格式
*
* @param target
* 待修改格式的XWPFTableRow
* @param source
* 模板XWPFTableRow
*/
private void CopyTableRow(XWPFTableRow target, XWPFTableRow source) {
int tempRowCellsize = source.getTableCells().size();// 模板行的列数
for (int i = 0; i < tempRowCellsize - 1; i++) {
target.addNewTableCell();// 为新添加的行添加与模板表格对应行行相同个数的单元格
}
// 复制样式
target.getCtRow().setTrPr(source.getCtRow().getTrPr());
// 复制单元格
for (int i = 0; i < target.getTableCells().size(); i++) {
copyTableCell(target.getCell(i), source.getCell(i));
//判断表格是否是无边框的
CTTblBorders tcBorders = source.getTable().getCTTbl().getTblPr().getTblBorders();
if (tcBorders!=null){
CTTcBorders tblBorders = target.getCell(i).getCTTc().getTcPr().addNewTcBorders();
if (tcBorders.getBottom()!=null && tcBorders.getBottom().getVal().toString().equals("none")
&& tcBorders.getTop()!=null && tcBorders.getTop().getVal().toString().equals("none")
&& tcBorders.getLeft()!=null && tcBorders.getLeft().getVal().toString().equals("none")
&& tcBorders.getRight()!=null && tcBorders.getRight().getVal().toString().equals("none")){
//判断底部的border是否为空
CTTcBorders ctTblBorders = source.getCell(i).getCTTc().getTcPr().getTcBorders();
if (ctTblBorders!=null && ctTblBorders.getBottom()!=null && !ctTblBorders.getBottom().getVal().toString().equals("none")){
tblBorders.addNewBottom().setVal(STBorder.SINGLE);
}else {
tblBorders.addNewBottom().setVal(STBorder.NIL);
}
if (ctTblBorders!=null && ctTblBorders.getTop()!=null && !ctTblBorders.getTop().getVal().toString().equals("none")){
tblBorders.addNewTop().setVal(STBorder.SINGLE);
}else {
tblBorders.addNewTop().setVal(STBorder.NIL);
}
tblBorders.addNewRight().setVal(STBorder.NIL);
tblBorders.addNewLeft().setVal(STBorder.NIL);
target.getCell(i).getCTTc().getTcPr().setTcBorders(tblBorders);
}
}
}
}
/**
* 复制单元格XWPFTableCell格式
*
* @author Juveniless
* @date 2017年11月27日 下午3:41:02
* @param newTableCell
* 新创建的的单元格
* @param templateTableCell
* 模板单元格
*
*/
private void copyTableCell(XWPFTableCell newTableCell, XWPFTableCell templateTableCell) {
//得到表格边框属性
CTTcBorders tblBorders = templateTableCell.getCTTc().getTcPr().getTcBorders();
// 列属性
newTableCell.getCTTc().setTcPr(templateTableCell.getCTTc().getTcPr());
//复制表格边框属性
newTableCell.getCTTc().getTcPr().setTcBorders(tblBorders);
// 删除目标 targetCell 所有文本段落
for (int pos = 0; pos < newTableCell.getParagraphs().size(); pos++) {
newTableCell.removeParagraph(pos);
}
// 添加新文本段落
for (XWPFParagraph sp : templateTableCell.getParagraphs()) {
XWPFParagraph targetP = newTableCell.addParagraph();
copyParagraph(targetP, sp);
}
}
/**
* 复制文本段落XWPFParagraph格式
*
* @author Juveniless
* @date 2017年11月27日 下午3:43:08
* @param newParagraph
* 新创建的的段落
* @param templateParagraph
* 模板段落
*
*/
private void copyParagraph(XWPFParagraph newParagraph, XWPFParagraph templateParagraph) {
// 设置段落样式
newParagraph.getCTP().setPPr(templateParagraph.getCTP().getPPr());
// 添加Run标签
for (int pos = 0; pos < newParagraph.getRuns().size(); pos++) {
newParagraph.removeRun(pos);
}
for (XWPFRun s : templateParagraph.getRuns()) {
XWPFRun targetrun = newParagraph.createRun();
CopyRun(targetrun, s);
}
}
/**
* 复制文本节点run
* @author Juveniless
* @date 2017年11月27日 下午3:47:17
* @param newRun
* 新创建的的文本节点
* @param templateRun
* 模板文本节点
*
*/
private void CopyRun(XWPFRun newRun, XWPFRun templateRun) {
newRun.getCTR().setRPr(templateRun.getCTR().getRPr());
// 设置文本
newRun.setText(templateRun.text());
}
/**
* 根据参数parametersMap对表格的一行进行标签的替换
*
* @author Juveniless
* @date 2017年11月23日 下午2:09:24
* @param tableRow
* 表格行
* @param parametersMap
* 参数map
*
*/
public void replaceTableRow(XWPFTableRow tableRow, Map<String, Object> parametersMap) {
List<XWPFTableCell> tableCells = tableRow.getTableCells();
for (XWPFTableCell xWPFTableCell : tableCells) {
List<XWPFParagraph> paragraphs = xWPFTableCell.getParagraphs();
for (XWPFParagraph xwpfParagraph : paragraphs) {
replaceParagraph(xwpfParagraph, parametersMap);
}
}
}
/**
* 根据map替换表格中的{key}标签
* @author Juveniless
* @date 2017年12月4日 下午2:47:36
* @param xwpfTable
* @param parametersMap
*
*/
public void replaceTable(XWPFTable xwpfTable, Map<String, Object> parametersMap){
List<XWPFTableRow> rows = xwpfTable.getRows();
for (XWPFTableRow xWPFTableRow : rows ) {
List<XWPFTableCell> tableCells = xWPFTableRow.getTableCells();
for (XWPFTableCell xWPFTableCell : tableCells ) {
List<XWPFParagraph> paragraphs2 = xWPFTableCell.getParagraphs();
for (XWPFParagraph xWPFParagraph : paragraphs2) {
replaceParagraph(xWPFParagraph, parametersMap);
}
}
}
}
private String getValueBykey(String key, Map<String, Object> map) {
String returnValue="";
if (key != null) {
try {
returnValue=map.get(key)!=null ? map.get(key).toString() : "";
} catch (Exception e) {
// TODO: handle exception
System.out.println("key:"+key+"***"+e);
returnValue="";
}
}
return returnValue;
}
/**
* @description: 判断图片的后缀,得到图片该用哪种格式
* @params:
* @return:
* @author: fanwj
* @Date: 2020/1/14 9:33
*/
public int readImageExt(String fileExt) {
int format = XWPFDocument.PICTURE_TYPE_PNG;
if(fileExt.endsWith(".emf")){
format = XWPFDocument.PICTURE_TYPE_EMF;
} else if(fileExt.endsWith(".wmf")){
format = XWPFDocument.PICTURE_TYPE_WMF;
} else if(fileExt.endsWith(".pict")) {
format = XWPFDocument.PICTURE_TYPE_PICT;
} else if(fileExt.endsWith(".jpeg") || fileExt.endsWith(".jpg")) {
format = XWPFDocument.PICTURE_TYPE_JPEG;
} else if(fileExt.endsWith(".png")) {
format = XWPFDocument.PICTURE_TYPE_PNG;
} else if(fileExt.endsWith(".dib")) {
format = XWPFDocument.PICTURE_TYPE_DIB;
} else if(fileExt.endsWith(".gif")) {
format = XWPFDocument.PICTURE_TYPE_GIF;
} else if(fileExt.endsWith(".tiff")) {
format = XWPFDocument.PICTURE_TYPE_TIFF;
} else if(fileExt.endsWith(".eps")) {
format = XWPFDocument.PICTURE_TYPE_EPS;
} else if(fileExt.endsWith(".bmp")) {
format = XWPFDocument.PICTURE_TYPE_BMP;
} else if(fileExt.endsWith(".wpg")) {
format = XWPFDocument.PICTURE_TYPE_WPG;
}
return format;
}
parametersMap.put("**image**","/1.jpeg"); //图片
//图片的key值去掉**,加上Width,Height可以设置图片的大小
parametersMap.put("imageWidth",100);
//表格中图片大小
parametersMap.put("imageHeight",50);
4.普通的替换文本,在模板中直接加{}
表格整体循环
1.表格整体循环,第一行需要两个单元格,第一个单元格写**##{foreachTable}##**,第二个单元格写需要替换的List集合名称
2.其他需要替换的数据用标签代替即可
public static void main(String[] args) throws IOException{
Map<String, Object> wordDataMap = new HashMap<String, Object>();// 存储报表全部数据
Map<String, Object> parametersMap = new HashMap<String, Object>();// 存储报表中不循环的数据
parametersMap.put("name","XX项目");
parametersMap.put("testName","XX试验任务");
parametersMap.put("code","GH07822");
parametersMap.put("taskCode","JKL/19S7");
parametersMap.put("testHost","张三");
parametersMap.put("examiner","lisi");
parametersMap.put("description","sjjALjjskaaaaaaaa");
parametersMap.put("referUsers","无望,上课时");
parametersMap.put("equipment","设备1");
parametersMap.put("files","记录表");
parametersMap.put("time","2020-01-7");
List<Map<String, Object>> images = new ArrayList<Map<String, Object>>();
Map<String, Object> map1=new HashMap<>();
map1.put("imageName", "图1:曲线图");
map1.put("**imagePath**", "/1.jpeg");
map1.put("imageDesc", "[email protected]");
map1.put("imagePathWidth",100);
map1.put("imagePathHeight",50);
Map<String, Object> map2=new HashMap<>();
map2.put("imageName", "图2:");
map2.put("**imagePath**", "/1.jpeg");
map2.put("imageDesc", "[email protected]");
map2.put("imagePathWidth",100);
map2.put("imagePathHeight",50);
Map<String, Object> map3=new HashMap<>();
map3.put("imageName", "图3:设备运行温度变化图");
map3.put("**imagePath**", "/2.jpeg");
map3.put("imageDesc", "[email protected]");
map3.put("imagePathWidth",100);
map3.put("imagePathHeight",50);
parametersMap.put("imagePathWidth",100);
parametersMap.put("imagePathHeight",50);
images.add(map1);
images.add(map2);
images.add(map3);
wordDataMap.put("parametersMap",parametersMap);
wordDataMap.put("images",images);
File file = new File("/prorecord.docx");//改成你本地文件所在目录
// 读取word模板
FileInputStream fileInputStream = new FileInputStream(file);
WordTemplate template = new WordTemplate(fileInputStream);
// 替换数据
template.replaceDocument(wordDataMap);
//生成文件
File outputFile=new File("/输出.docx");//改成你本地文件所在目录
FileOutputStream fos = new FileOutputStream(outputFile);
template.getDocument().write(fos);
}