<!-- 需要用的包-->
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.14</version>
</dependency>
package com.example.demo.jisuan;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
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 java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.util.List;
public class WordUtil2 {
/**
* 替换word中指定字符串
* 注意模板需要替换的字符串的格式
* 1、要连着打出来,或者在别的地方写好粘过来
* 2、先word转PDF,再将PDF转word
* <p>
* 替换word模板并生成新的word
*
* @param srcPath 模板地址
* @param destPath 新的word地址
* @param map 替换的内容
* @return 是否成功替换
*/
public static boolean newWord(String srcPath,
String destPath, Map<String, Object> map) {
//创建新的word文件
File errorExcelfile = new File(destPath);
if (!errorExcelfile.exists()) {
File file = errorExcelfile.getParentFile();
if (!file.exists())
file.mkdirs();
}
try {
OPCPackage opcPackage = POIXMLDocument.openPackage(srcPath);
CustomXWPFDocument doc = new CustomXWPFDocument(opcPackage);
// 替换段落中的指定文字
Iterator<XWPFParagraph> itPara = doc.getParagraphsIterator();
while (itPara.hasNext()) {
XWPFParagraph paragraph = (XWPFParagraph) itPara.next();
List<XWPFRun> runs = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++) {
//遍历读取模板的内容
String oneparaString = runs.get(i).getText(runs.get(i).getTextPosition());
if (oneparaString == null) {
continue;
}
//遍历要替换的内容 和模板相同字符串的key 被替换为value
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
if (oneparaString.indexOf(key) != -1) {
Object value = entry.getValue();
if (value instanceof String) {
oneparaString = oneparaString.replace(entry.getKey(), entry.getValue().toString());
} else if (value instanceof Map) {
//判断如果值是map类型 就说明是图片
oneparaString = oneparaString.replace(key, "");
Map pic = (Map) value;
int width = Integer.parseInt(pic.get("width").toString());
int height = Integer.parseInt(pic.get("height").toString());
int picType = getPictureType(pic.get("type").toString());
byte[] byteArray = (byte[]) pic.get("content");
ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
//以字节流的形式 向 XWPFParagraph 添加图片
doc.addPictureData(byteInputStream, picType);
//创建图片模板
doc.createPicture(doc.getAllPictures().size() - 1, width, height, paragraph);
}
}
}
runs.get(i).setText(oneparaString, 0);
}
}
FileOutputStream outStream = null;
outStream = new FileOutputStream(destPath);
doc.write(outStream);
outStream.close();
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 根据图片类型,取得对应的图片类型代码
*
* @param picType
* @return int
*/
private static int getPictureType(String picType) {
int res = CustomXWPFDocument.PICTURE_TYPE_PICT;
if (picType != null) {
if (picType.equalsIgnoreCase("png")) {
res = CustomXWPFDocument.PICTURE_TYPE_PNG;
} else if (picType.equalsIgnoreCase("dib")) {
res = CustomXWPFDocument.PICTURE_TYPE_DIB;
} else if (picType.equalsIgnoreCase("emf")) {
res = CustomXWPFDocument.PICTURE_TYPE_EMF;
} else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
res = CustomXWPFDocument.PICTURE_TYPE_JPEG;
} else if (picType.equalsIgnoreCase("wmf")) {
res = CustomXWPFDocument.PICTURE_TYPE_WMF;
}
}
return res;
}
public static void main(String[] args) {
System.out.println("hello world");
List<Person> dtos = new ArrayList<>();
for (int i = 0; i < 20; i++) {
Person dto = new Person();
if(i%3==0){
dto.setName("张三" + i);
dto.setSex("nan" + i);
dto.setAge("11" + i);
dtos.add(dto);
}else{
dto.setName("");
dto.setSex("nan" + i);
dto.setAge("");
dtos.add(dto);
}
}
List<String> head = new ArrayList<>();
head.add("姓名");
head.add("年龄");
head.add("性别");
String srcPath = "F:\\jinxin.docx";
String targetPath = "F:\\jinxin1.docx";
String key = "liebiaotable";// 在文档中需要替换插入表格的位置
exportBg(head, dtos, srcPath, targetPath, key);
}
// public static void main(String[] args) {
// Map<String,Object> map = new HashMap<>();
// map.put("需求说明","测试替换");
// newWord("F:\\jin.docx","F:\\jinxin.docx",map);
// }
/**
* 替换word中指定字符串(这里用来将字符串替换为表格,上边的newWord用来替换文字等)
* @param head 表头
* @param data 数据
* @param srcPath 需要操作的文档模板
* @param targetPath 操作完后输出的位置
* @param key 需要替换的文字,如果需要替换多个位置就用个map啥的
* @param <T>
*/
//创建一个表格插入到key标记的位置
public static <T> void exportBg(List<String> head, List<T> data, String srcPath, String targetPath, String key) {
XWPFDocument doc = null;
try {
doc = new XWPFDocument(POIXMLDocument.openPackage(srcPath));
List<XWPFParagraph> paragraphList = doc.getParagraphs();
if (paragraphList != null && paragraphList.size() > 0) {
for (XWPFParagraph paragraph : paragraphList) {
List<XWPFRun> runs = paragraph.getRuns();
for (int i = 0; i < runs.size(); i++) {
String text = runs.get(i).getText(0);
if (text != null) {
text = text.trim();
if (text.indexOf(key) >= 0) {
runs.get(i).setText(text.replace(key, ""), 0);
XmlCursor cursor = paragraph.getCTP().newCursor();
// 在指定游标位置插入表格
XWPFTable table = doc.insertNewTbl(cursor);
CTTblPr tablePr = table.getCTTbl().getTblPr();
CTTblWidth width = tablePr.addNewTblW();
//获取这个东西用来改表格宽度
width.setW(BigInteger.valueOf(7000));
insertInfo(table, head, data);
break;
}
}
}
}
}
FileOutputStream os = new FileOutputStream(targetPath);
doc.write(os);
os.flush();
os.close();
} catch (IOException | IllegalAccessException | IntrospectionException | InvocationTargetException e) {
e.printStackTrace();
}
}
/**
* 把信息插入表格
*/
private static <T> void insertInfo(XWPFTable table, List<String> head, List<T> data) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
//获取第一行
XWPFTableRow row = table.getRow(0);
// //获取这个东西用来改表格宽度
// CTTblPr tblPr = table.getCTTbl().getTblPr();
// //改变长度策略为自己调整 默认为auto
// tblPr.getTblW().setType(STTblWidth.DXA);
// //设置表格宽度为7000
// tblPr.getTblW().setW(BigInteger.valueOf(10));
//根据头创建表格head
for (int col = 1; col < head.size(); col++) {//默认会创建一列,即从第2列开始
// 第一行创建了多少列,后续增加的行自动增加列
CTTcPr cPr = row.createCell().getCTTc().addNewTcPr();
//设置单元格高度为500
row.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(500));
//可以用来设置单元格长度
//CTTblWidth width = cPr.addNewTcW();
//width.setW(BigInteger.valueOf(2000));
}
//循环给表格添加头信息
for (int i = 0; i < head.size(); i++) {
//往表格里面写入头信息
row.getCell(i).setText(head.get(i));
}
//计数器
int i = 0;
//循环填充body列表(列表为vo数组)
for (T item : data) {
//获取类
Class<?> clazz = item.getClass();
//获取item字段
Field[] fields = item.getClass().getDeclaredFields();
//创建行
row = table.createRow();
//修改行高为500
row.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(1000));
//循环获取vo类的属性
for (Field field : fields) {
//获取当前field的属性描述器
PropertyDescriptor descriptor = new PropertyDescriptor(field.getName(), clazz);
//获取field字段的get方法
Method readMethod = descriptor.getReadMethod();
//执行get方法并填充到表格中
row.getCell(i).setText(String.valueOf(readMethod.invoke(item)));
//计数器+1
i++;
}
//执行完一行计数器归零
i = 0;
}
mergeCellsVertically(table,0,1,4);
}
/**
*
* @param table 自己猜
* @param col 第几列
* @param fromRow 开始行
* @param toRow 结束行
*/
// word跨行并单元格
public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
if ( rowIndex == fromRow ) {
// The first merged cell is set with RESTART merge value
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
} else {
// Cells which join (merge) the first one, are set with CONTINUE
cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
}
}
}
/**
* 列的我这里没用,留着备用
* @param table
* @param row
* @param fromCell
* @param toCell
*/
// // word跨列合并单元格
// public 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);
// } else {
// // Cells which join (merge) the first one, are set with CONTINUE
// cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
// }
// }
// }
}
、、
<!-- 之前打算用这个包的方法开发来着,没研究明白所以放弃了 -->
<dependencies>
<!-- <dependency>-->
<!-- <groupId>e-iceblue</groupId>-->
<!-- <artifactId>spire.doc.free</artifactId>-->
<!-- <version>3.9.0</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>e-iceblue</groupId>-->
<!-- <artifactId>spire.xls.free</artifactId>-->
<!-- <version>3.9.1</version>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId> e-iceblue </groupId>-->
<!-- <artifactId>spire.office</artifactId>-->
<!-- <version>4.8.0</version>-->
<!-- </dependency>-->
</dependencies>
<repositories>
<repository>
<id>com.e-iceblue</id>
<url>https://repo.e-iceblue.cn/repository/maven-public/</url>
</repository>
</repositories>
|