import java.io.*;importjava.util.Map;importcom.thinkgem.jeesite.common.utils.StringUtils;importorg.apache.poi.ooxml.POIXMLDocument;importorg.apache.poi.openxml4j.opc.OPCPackage;import org.apache.poi.xwpf.usermodel.*;importorg.apache.xmlbeans.XmlException;importorg.apache.xmlbeans.XmlToken;importorg.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;importorg.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;importorg.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;importorg.openxmlformats.schemas.wordprocessingml.x2006.main.CTFonts;importorg.openxmlformats.schemas.wordprocessingml.x2006.main.CTP;importorg.openxmlformats.schemas.wordprocessingml.x2006.main.CTRPr;importorg.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;import java.util.*;/***https://blog.csdn.net/qq_27828675/article/details/88708983
*/
public classWordTemplate {/*** 根据模板生成新word文档
* 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
*
*@paraminputUrl 模板存放地址
*@paramoutputUrl 新文档存放地址
*@paramtextMap 需要替换的信息集合
*@paramtableList 需要插入的表格信息集合
*@return成功返回true, 失败返回false*/
public staticCustomXWPFDocument changWord(String inputUrl, String outputUrl,
Map textMap, ListtableList) {
CustomXWPFDocument document= null;//模板转换默认成功
boolean changeFlag = true;try{//获取docx解析对象
document = newCustomXWPFDocument(POIXMLDocument.openPackage(inputUrl));//解析替换文本段落对象
WordTemplate.changeText(document, textMap);//解析替换表格对象
WordTemplate.changeTable(document, textMap, tableList);//生成新的word
/*File file = new File(outputUrl);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
FileInputStream stream = new FileInputStream(file);*/
//document.write(stream);//stream.close();
}catch(IOException e) {
e.printStackTrace();
changeFlag= false;
}returndocument;
}/*** 替换段落文本
*
*@paramdocument docx解析对象
*@paramtextMap 需要替换的信息集合*/
public static void changeText(XWPFDocument document, MaptextMap) {//获取段落集合
List paragraphs =document.getParagraphs();for(XWPFParagraph paragraph : paragraphs) {//判断此段落时候需要进行替换
String text =paragraph.getText();if(checkText(text)) {
List runs =paragraph.getRuns();for(XWPFRun run : runs) {//替换模板原来位置
run.setText((String) changeValue(run.toString(), textMap), 0);
}
}
}
}/*** 替换表格对象方法
*
*@paramdocument docx解析对象
*@paramtextMap 需要替换的信息集合
*@paramtableList 需要插入的表格信息集合*/
public static void changeTable(CustomXWPFDocument document, MaptextMap,
ListtableList) {//获取表格对象集合
List tables =document.getTables();for (int i = 0; i < tables.size(); i++) {//只处理行数大于等于2的表格,且不循环表头
XWPFTable table =tables.get(i);if (table.getRows().size() > 1) {//判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
if(checkText(table.getText())) {
List rows =table.getRows();//遍历表格,并替换模板
eachTable(document, rows, textMap);
}else{//System.out.println("插入"+table.getText());
insertTable(table, tableList);
}
}
}
}/*** 遍历表格,包含对图片内容的替换
*
*@paramrows 表格行对象
*@paramtextMap 需要替换的信息集合*/
public static void eachTable(CustomXWPFDocument document, List rows, MaptextMap) {for(XWPFTableRow row : rows) {
List cells =row.getTableCells();for(XWPFTableCell cell : cells) {//判断单元格是否需要替换
if(checkText(cell.getText())) {
List paragraphs =cell.getParagraphs();for(XWPFParagraph paragraph : paragraphs) {
List runs =paragraph.getRuns();for(XWPFRun run : runs) {//run.setText(changeValue(run.toString(), textMap),0);
Object ob=changeValue(run.toString(), textMap);if (ob instanceofString) {
run.setText((String) ob,0);
}else if (ob instanceofMap) {
run.setText("", 0);
Map pic=(Map) ob;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= newByteArrayInputStream(byteArray);try{
String ind=document.addPictureData(byteInputStream, picType);
document.createPicture(run, ind, document.getNextPicNameNumber(picType), width, height);
}catch(Exception e) {
e.printStackTrace();
}
}
}
}
}
}
}
}/*** 为表格插入数据,行数不够添加新行
*
*@paramtable 需要插入数据的表格
*@paramtableList 插入数据集合*/
public static void insertTable(XWPFTable table, ListtableList) {//创建行,根据需要插入的数据添加新行,不处理表头
for (int i = 1; i < tableList.size(); i++) {
XWPFTableRow row=table.createRow();
}//遍历表格插入数据
List rows =table.getRows();for (int i = 1; i < rows.size(); i++) {
XWPFTableRow newRow=table.getRow(i);
List cells =newRow.getTableCells();for (int j = 0; j < cells.size(); j++) {
XWPFTableCell cell=cells.get(j);
cell.setText(tableList.get(i- 1)[j]);
}
}
}/*** word跨列合并单元格*/
public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, inttoCell) {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);
}
}
}/*** word跨行并单元格*/
public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, inttoRow) {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);
}
}
}/*** 单元格设置字体
*@paramcell
*@paramcellText*/
private static voidgetParagraph(XWPFTableCell cell,String cellText){
CTP ctp=CTP.Factory.newInstance();
XWPFParagraph p= newXWPFParagraph(ctp, cell);
p.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run=p.createRun();
run.setText(cellText);
CTRPr rpr= run.getCTR().isSetRPr() ?run.getCTR().getRPr() : run.getCTR().addNewRPr();
CTFonts fonts= rpr.isSetRFonts() ?rpr.getRFonts() : rpr.addNewRFonts();
fonts.setAscii("仿宋");
fonts.setEastAsia("仿宋");
fonts.setHAnsi("仿宋");
cell.setParagraph(p);
}/*** 判断文本中时候包含$
*
*@paramtext 文本
*@return包含返回true, 不包含返回false*/
public static booleancheckText(String text) {boolean check = false;if (text.indexOf("$") != -1) {
check= true;
}returncheck;
}/*** 匹配传入信息集合与模板
*
*@paramvalue 模板需要替换的区域
*@paramtextMap 传入信息集合
*@return模板需要替换区域信息集合对应值*/
public static Object changeValue(String value, MaptextMap) {
Object obj= null;
Set> textSets =textMap.entrySet();for (Map.EntrytextSet : textSets) {if (textSet.getKey().contains("jobFullname") && value.contains("jobFullname")){
System.out.println(textSet.getKey());
}//匹配模板与替换值 格式${key}
String key = "${" + textSet.getKey() + "}";if (value.indexOf(key) != -1) {
obj=textSet.getValue();
}
}if (!(obj instanceofMap)) {//模板未匹配到区域替换为空
if (obj != null &&checkText(obj.toString())) {
obj= "";
}
}if (obj==null){
obj="";
}returnobj;
}/*** 根据图片类型,取得对应的图片类型代码
*
*@parampicType
*@returnint*/
private static intgetPictureType(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;
}
}returnres;
}/*** 将输入流中的数据写入字节数组
*
*@paramin
*@return
*/
public static byte[] inputStream2ByteArray(InputStream in, booleanisClose) {byte[] byteArray = null;try{int total =in.available();
byteArray= new byte[total];
in.read(byteArray);
}catch(IOException e) {
e.printStackTrace();
}finally{if(isClose) {try{
in.close();
}catch(Exception e2) {
System.out.println("关闭流失败");
}
}
}returnbyteArray;
}
}/*** @BelongsProject: exchange
* @BelongsPackage: com.elens.util
* @Author: xuweichao
* @CreateTime: 2019-03-20 12:34
* @Description: 重写XWPFDocument的方法,插入图片*/