准备工作:

1.需要的jar(jar包在资源处已上传,可下载)

2.创建docx模板(doc不可以)

第一步:准备好jar(这里面的 ooxml-schemas-1.1.jar 大家可以尝试用poi-shemas-3.12-20150511.jar替换试试,但是偶尔会报java.lang.NoSuchMethodException: org.openxmlformats.schemas.wordprocessingml.x2006.....等错误,网络说poi-shemas-3.12-20150511.jar是简化版,需要用 ooxml-schemas-1.1.jar替换)

第二步:准备好docx模板(这里我写入了四个表格,根据您的需要制作,${date} 是段落部分, $符号不能没有,代码中需要判断替换的)

准备工作完成  下面是代码部分

BaseXWPFDocument.java

package word;import java.io.IOException;
import java.io.InputStream;import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;/*** 自定义 XWPFDocument,并重写 createPicture()方法*/
public class BaseXWPFDocument extends XWPFDocument{public BaseXWPFDocument(InputStream in) throws IOException {super(in);}public BaseXWPFDocument() {super();}public BaseXWPFDocument(OPCPackage pkg) throws IOException {super(pkg);}/*** @param id* @param width 宽* @param height 高* @param paragraph  段落*/public void createPicture(int id, int width, int height,XWPFParagraph paragraph) {final int EMU = 9525;width *= EMU;height *= EMU;String blipId = getAllPictures().get(id).getPackageRelationship().getId();CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();System.out.println(blipId+":"+inline);String picXml = ""+ "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"+ "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"+ "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"+ "         <pic:nvPicPr>" + "            <pic:cNvPr id=\""+ id+ "\" name=\"Generated\"/>"+ "            <pic:cNvPicPr/>"+ "         </pic:nvPicPr>"+ "         <pic:blipFill>"+ "            <a:blip r:embed=\""+ blipId+ "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"+ "            <a:stretch>"+ "               <a:fillRect/>"+ "            </a:stretch>"+ "         </pic:blipFill>"+ "         <pic:spPr>"+ "            <a:xfrm>"+ "               <a:off x=\"0\" y=\"0\"/>"+ "               <a:ext cx=\""+ width+ "\" cy=\""+ height+ "\"/>"+ "            </a:xfrm>"+ "            <a:prstGeom prst=\"rect\">"+ "               <a:avLst/>"+ "            </a:prstGeom>"+ "         </pic:spPr>"+ "      </pic:pic>"+ "   </a:graphicData>" + "</a:graphic>";inline.addNewGraphic().addNewGraphicData();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("图片名称" + id);docPr.setDescr("描述部分");}
}

CrtWordUtils.java

package word;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;import org.apache.poi.POIXMLDocument;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
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.openxmlformats.schemas.wordprocessingml.x2006.main.CTHMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcBorders;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STBorder;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;/*** 生成word工具类*/
public class CrtWordUtils{//private static Log logger = LogFactory.getLog(CrtWordUtils.class);/*** 根据模板生成word文档* @param inputUrl 模板路径* @param textMap 需要替换的文本内容* @param mapList 需要动态生成的内容* @return*/public static BaseXWPFDocument changWord(String inputUrl, Map<String, Object> textMap, List<Object> mapList) {BaseXWPFDocument document = null;try {//获取docx解析对象document = new BaseXWPFDocument(POIXMLDocument.openPackage(inputUrl));//解析替换文本段落对象//logger.info("CrtWordUtils--生成word中文本段落开始...");changeText(document, textMap);//logger.info("CrtWordUtils--生成word中文本段落结束...");//解析替换表格对象//logger.info("CrtWordUtils--生成word中表格开始...");changeTable(document,textMap, mapList);//logger.info("CrtWordUtils--生成word中表格结束...");} catch (IOException e) {//logger.error("CrtWordUtils--生成word失败,原因:"+e.getMessage());}return document;}/*** 替换表格对象方法* @param document docx解析对象* @param mapList 需要动态生成的内容*/public static void changeTable(BaseXWPFDocument document,Map<String, Object> textMap, List<Object> mapList){//获取表格对象集合List<XWPFTable> tables = document.getTables();//循环所有需要进行替换的文本,进行替换for (int i = 0; i < tables.size(); i++) {XWPFTable table = tables.get(i);XWPFParagraph p = document.getParagraphArray(0);p.setAlignment(ParagraphAlignment.LEFT);XWPFRun run = p.insertNewRun(0);List<XWPFTableRow> rows = table.getRows();//--------------------------------在第二个表格的第一行第一列的框中插入图片-----------------------------------if(i == 1){XWPFTableRow rowTest = table.getRow(0);XWPFTableCell imageCell = rowTest.getCell(0);List<XWPFParagraph> paragraphs = imageCell.getParagraphs();XWPFParagraph newPara = paragraphs.get(0);XWPFRun imageCellRunn = newPara.createRun();try {imageCellRunn.addPicture(new FileInputStream("D:/1.png"), BaseXWPFDocument.PICTURE_TYPE_PNG, "1.png", Units.toEMU(40), Units.toEMU(30));} catch (Exception e) {e.printStackTrace();}run.addBreak();}//--------------------------------在第二个表格的第一行第一列的框中插入图片-----------------------------------if(checkText(table.getText())){//遍历表格,并替换模板eachTable(document,rows, textMap);}}int index=0;//操作word中的表格for (int i = 0; i < tables.size(); i++) {//只处理行数大于等于2的表格,且不循环表头XWPFTable table = tables.get(i);List<String[]> list = (List<String[]>) mapList.get(index);if (!list.isEmpty()){//logger.info("CrtWordUtils--生成word中表格第"+(index+1)+"个表格开始");if(i == 3){changeTable_quality(document, mapList);}else{insertTable(table,list,i);//logger.info("CrtWordUtils--生成word中表格第"+(index+1)+"个表格结束");if(i == 1){//第二个表格需要列合并List<Integer[]> indexList = startEnd(list);for (int c=0;c<indexList.size();c++){ //合并行//logger.info("CrtWordUtils--生成word中表格需要合并的表格开始...");mergeCellVertically(table,0,indexList.get(c)[0]+2,indexList.get(c)[1]+2);//mergeCellVertically(table,1,indexList.get(c)[0]+1,indexList.get(c)[1]+1);// logger.info("CrtWordUtils--生成word中表格需要合并的表格结束...");}}}}index++;}}public static void changeTable_quality(BaseXWPFDocument document, List<Object> mapList){//获取表格对象集合List<XWPFTable> tables = document.getTables();//int index=0;//操作word中的表格for (int i = 0; i < tables.size(); i++) {//只处理行数大于等于2的表格,且不循环表头XWPFTable table = tables.get(i);List<String[]> list = (List<String[]>) mapList.get(i);if (null != list && 0 < list.size()){//logger.info("CrtWordUtils--生成word中表格第"+(i+1)+"个表格开始");//logger.info("CrtWordUtils--生成word中表格第"+(i+1)+"个表格结束");if(i == 3){//--i:第i个表格insertTable_quality(table,list,i);for (int c=0;c<list.size();c++){ //合并列mergeColumnsCellVertically(table,c+2,0,1);}}}//index++;}}/*** 此处做了特殊处理 如果文本段落中出现有需要换行, replaceTabStr对应下面的数据格式* * List<Object[]> resultBydeptList = baseMapList.get("resultBydeptList");StringBuilder sbResultStr = new StringBuilder();for (Iterator iter = resultBydeptList.iterator(); iter.hasNext();) {Object[] objArr = (Object[])iter.next();Object yearResultStr = objArr[2];if(yearResultStr != null){sbResultStr.append(objArr[0]).append(objArr[1]).append("replaceTabStr").append(objArr[2]).append("replaceTabStr");}}data.put("${paragraph1_yearresult}", sbResultStr.toString().isEmpty()?"无":sbResultStr.toString());* * 替换段落文本* @param document docx解析对象* @param textMap 需要替换的信息集合*/public static void changeText(BaseXWPFDocument document, Map<String, Object> textMap){//获取段落集合List<XWPFParagraph> paragraphs = document.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {//判断此段落是否需要进行替换String text = paragraph.getText();if(checkText(text)){List<XWPFRun> runs = paragraph.getRuns();for (int i = 0;i<runs.size();i++) {//替换模板原来位置Object obstr = changeValue(text, textMap);// logger.info("CrtWordUtils--段落信息..."+runs.get(i).toString());//分段显示的情况String[] values = obstr.toString().split("replaceTabStr");if(values.length > 1) {runs.get(i).setText(values[0],0);for (int j = 1; j < values.length; j++) {//存在分段则新建一个runXWPFRun newrun = paragraph.insertNewRun(j);newrun.getCTR().setRPr(runs.get(i).getCTR().getRPr());//copy样式newrun.addBreak();//换行newrun.getCTR().addNewTab();//缩进newrun.setText(values[j]);}break;}else{runs.get(i).setText(obstr.toString().replace("replaceTabStr", ""),0);}if(i > 0){runs.get(i).setText("",0);}}}}}/*** 为表格插入数据,行数不够添加新行* @param table 需要插入数据的表格* @param daList 表格的插入数据* @param type 表格类型:0-第一个表格 以此类推*/public static void insertTable(XWPFTable table, List<String[]> daList,Integer type){//创建行和创建需要的列(有行样式要求的)for(int i = 1; i < daList.size(); i++){//添加一个新行int startRow = type.equals(2)?3:2;//  第二个表格  插入新行从3开始 其他2开始int rowPos = startRow;  //rowPos 的作用是获取新行的下一行,便于复制新行的样式insertNewRow(table,table.getRow(rowPos),rowPos+1);//logger.info("CrtWordUtils--创建表格行成功");}//创建行,根据需要插入的数据添加新行,不处理表头for(int i = 0; i < daList.size(); i++){int startRow = type.equals(2)?3:2;//  第二个表格  插入新行从3开始 其他2开始int rowPos = startRow;  //rowPos 的作用是获取新行的下一行,便于复制新行的样式List<XWPFTableCell> cells = table.getRow(i+rowPos).getTableCells();//logger.info("CrtWordUtils--表格中每个单元格插入元素开始");for(int j = 0; j < cells.size(); j++){XWPFTableCell cell02 = cells.get(j);CTTc ctTc = cell02.getCTTc(); // here is need to change... 设置边框CTTcPr tcPr = ctTc.addNewTcPr();CTTcBorders border = tcPr.addNewTcBorders();border.addNewRight().setVal(STBorder.SINGLE);border.addNewLeft().setVal(STBorder.SINGLE);border.addNewBottom().setVal(STBorder.SINGLE);//设置字体居中tcPr.addNewVAlign().setVal(STVerticalJc.CENTER);ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);if(type.equals(2) && daList.get(i)[j].equals("否")){//内容显示红色//logger.info("CrtWordUtils--表格3中开始特殊处理");cell02.removeParagraph(0);XWPFParagraph newPara = new XWPFParagraph(cell02.getCTTc().addNewP(), cell02);                                                                                                                               XWPFRun run=newPara.createRun();                       newPara.setAlignment(ParagraphAlignment.CENTER);run.getCTR().addNewRPr().addNewColor().setVal("FF0000");/**FF0000红色*/                               run.setText(daList.get(i)[j]);    cell02.setColor("cc99ff");}else{cell02.setText(daList.get(i)[j]);}}}}/*** 为表格插入数据,行数不够添加新行* @param table 需要插入数据的表格* @param daList 表格的插入数据* @param type 表格类型:0-第一个表格 以此类推*/public static void insertTable_quality(XWPFTable table, List<String[]> daList,Integer type){//创建行和创建需要的列for(int i = 1; i < daList.size(); i++){//添加一个新行insertNewRow(table,table.getRow(2),3);//logger.info("CrtWordUtils--创建表格行成功");}//创建行,根据需要插入的数据添加新行,不处理表头for(int i = 0; i < daList.size(); i++){List<XWPFTableCell> cells = table.getRow(i+2).getTableCells();//String [] rowdatas  = daList.get(i);//logger.info("CrtWordUtils--表格中每个单元格插入元素开始");for(int j = 0; j < cells.size(); j++){XWPFTableCell cell02 = cells.get(j);CTTc ctTc = cell02.getCTTc(); // here is need to change... 设置边框CTTcPr tcPr = ctTc.addNewTcPr();CTTcBorders border = tcPr.addNewTcBorders();border.addNewRight().setVal(STBorder.SINGLE);border.addNewLeft().setVal(STBorder.SINGLE);border.addNewBottom().setVal(STBorder.SINGLE);//设置字体居中tcPr.addNewVAlign().setVal(STVerticalJc.CENTER);ctTc.getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);//if(type.equals(0)&&j==1){if(type.equals(0)&&j==1&&daList.get(i)[5].equals("0")){cell02.removeParagraph(0);XWPFParagraph newPara = new XWPFParagraph(cell02.getCTTc().addNewP(), cell02);                                                                                                                               XWPFRun run=newPara.createRun();                       newPara.setAlignment(ParagraphAlignment.CENTER);run.getCTR().addNewRPr().addNewColor().setVal("008000");/**#008000绿色*/                               run.setText(daList.get(i)[j]); }else{cell02.setText(daList.get(i)[j]);}}}}/*** 判断文本中是否包含$* @param text 文本* @return 包含返回true,不包含返回false*/public static boolean checkText(String text){boolean check  =  false;if(text.indexOf('$')!= -1){check = true;}return check;}/*** 匹配传入信息集合与模板* @param value 模板需要替换的区域* @param textMap 传入信息集合* @return 模板需要替换区域信息集合对应值*/public static Object changeValue(String value, Map<String, Object> textMap){Set<Map.Entry<String, Object>> textSets = textMap.entrySet();Object valu = value;for (Map.Entry<String, Object> textSet : textSets) {String key = textSet.getKey();if(value.indexOf(key)!= -1){valu = String.valueOf(valu).replace("$"+textSet.getKey().substring(1), textSet.getValue().toString());}}return valu;}/*** 合并行* @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 col 需要合并的列* @param fromRow 开始行* @param toRow 结束行*/public static void mergeColumnsCellVertically(XWPFTable table, int rownum, int fromCol, int toCol) {XWPFTableRow row = table.getRow(rownum);for(int rowIndex = fromCol; rowIndex <= toCol; rowIndex++){CTHMerge hMerge = CTHMerge.Factory.newInstance();if(rowIndex == fromCol){hMerge.setVal(STMerge.RESTART);} else {hMerge.setVal(STMerge.CONTINUE);}XWPFTableCell cell = row.getCell(rowIndex);CTTcPr tcPr = cell.getCTTc().getTcPr();if (tcPr != null) {tcPr.setHMerge(hMerge);} else {tcPr = CTTcPr.Factory.newInstance();tcPr.setHMerge(hMerge);cell.getCTTc().setTcPr(tcPr);}}}/*** 获取需要合并单元格的下标* @return*/public static List<Integer[]> startEnd(List<String[]> daList){List<Integer[]> indexList = new ArrayList();List<String> list = new ArrayList();for (int i=0;i<daList.size();i++){list.add(daList.get(i)[0]);}Map<Object, Integer> tm = new HashMap();for (int i=0;i<daList.size();i++){if (!tm.containsKey(daList.get(i)[0])) {tm.put(daList.get(i)[0], 1);} else {int count = tm.get(daList.get(i)[0]) + 1;tm.put(daList.get(i)[0], count);}}for (Map.Entry<Object, Integer> entry : tm.entrySet()) {String key = entry.getKey().toString();if (list.indexOf(key) != (-1)){Integer[] index = new Integer[2];index[0] = list.indexOf(key);index[1] = list.lastIndexOf(key);indexList.add(index);}}return indexList;}/*** 插入新行 同时复制首行的样式 * table 操作的表格* copyRow 表头下面的行* newRowIndex  copyRow该行下面的行的索引,复制copyRow该行的样式* * */public static XWPFTableRow insertNewRow(XWPFTable table,XWPFTableRow copyRow,Integer newRowIndex){XWPFTableRow targetRow = table.insertNewTableRow(newRowIndex);targetRow.getCtRow().setTrPr(copyRow.getCtRow().getTrPr());List<XWPFTableCell> copyCells = copyRow.getTableCells();XWPFTableCell targetCell = null;for (int i = 0; i < copyCells.size(); i++) {XWPFTableCell copyCell = copyCells.get(i);targetCell = targetRow.addNewTableCell();targetCell.getCTTc().setTcPr(copyCell.getCTTc().getTcPr());if(copyCell.getParagraphs() != null && copyCell.getParagraphs().size() > 0){targetCell.getParagraphs().get(0).getCTP().setPPr(copyCell.getParagraphs().get(0).getCTP().getPPr());if(copyCell.getParagraphs().get(0).getRuns() !=null && copyCell.getParagraphs().get(0).getRuns().size() > 0){XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();cellR.setBold(copyCell.getParagraphs().get(0).getRuns().get(0).isBold());}}}return targetRow;}/*** 根据图片类型,取得对应的图片类型代码* @param picType* @return int*/private static int getPictureType(String picType){int res = BaseXWPFDocument.PICTURE_TYPE_PICT;if(picType != null){if(picType.equalsIgnoreCase("png")){res = BaseXWPFDocument.PICTURE_TYPE_PNG;}else if(picType.equalsIgnoreCase("dib")){res = BaseXWPFDocument.PICTURE_TYPE_DIB;}else if(picType.equalsIgnoreCase("emf")){res = BaseXWPFDocument.PICTURE_TYPE_EMF;}else if(picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")){res = BaseXWPFDocument.PICTURE_TYPE_JPEG;}else if(picType.equalsIgnoreCase("wmf")){res = BaseXWPFDocument.PICTURE_TYPE_WMF;}}return res;}/*** 将输入流中的数据写入字节数组* @param in* @return*/public static byte[] inputStream2ByteArray(InputStream in, boolean isClose){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("关闭流失败");}}}return byteArray;}/*** 遍历表格* @param rows 表格行对象* @param textMap 需要替换的信息集合*/public static void eachTable(BaseXWPFDocument document, List<XWPFTableRow> rows , Map<String, Object> textMap){for (XWPFTableRow row : rows) {List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {//判断单元格是否需要替换if(checkText(cell.getText())){List<XWPFParagraph> paragraphs = cell.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {Object ob = changeValue(run.toString(), textMap);if (ob instanceof String){run.setText((String)ob,0);}else if (ob instanceof Map){/* 此处本想实现表格中插入图片 ,但是失效 所以在89行中自行处理 -^^-* 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 = new ByteArrayInputStream(byteArray);try {String ind = document.addPictureData(byteInputStream,picType);document.createPicture(Integer.valueOf(ind), width , height,paragraph);} catch (Exception e) {e.printStackTrace();}*/}}}}}}}/*** 关闭输入流** @param is*/private void close(InputStream is) {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}/*** 关闭输出流** @param os*/private void close(OutputStream os) {if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}}
}

Main.java

package word;import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;import javax.imageio.ImageIO;import org.apache.poi.util.IOUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;public class Main {public static void main(String[] args) throws Exception {//需要进行文本替换的信息Map<String, Object> data = new HashMap<String, Object>();data.put("${date}", "2020");//需要进行动态生成的信息List<Object> mapList = new ArrayList<Object>();//第一个动态生成的数据列表List<String[]> list01 = new ArrayList<String[]>();list01.add(new String[]{"张三","男","23"});list01.add(new String[]{"李四","女","24"});list01.add(new String[]{"王五","女","25"});//第二个动态生成的数据列表List<String[]> list02 = new ArrayList<String[]>();list02.add(new String[]{"张三","语文","134"});list02.add(new String[]{"张三","数学","141"});list02.add(new String[]{"张三","英语","132"});list02.add(new String[]{"李四","语文","131"});list02.add(new String[]{"李四","数学","131"});list02.add(new String[]{"李四","英语","134"});list02.add(new String[]{"王五","语文","136"});list02.add(new String[]{"王五","数学","145"});list02.add(new String[]{"王五","英语","134"});//第三个动态生成的数据列表List<String[]> list03 = new ArrayList<String[]>();list03.add(new String[]{"甲老师","是","否","否"});list03.add(new String[]{"乙老师","否","是","否"});list03.add(new String[]{"丙老师","否","是","否"});list03.add(new String[]{"丁老师","是","否","否"});//第四个动态生成的数据列表List<String[]> list04 = new ArrayList<String[]>();list04.add(new String[]{"语文","语文","英语","数学"});list04.add(new String[]{"英语","英语","语文","数学"});mapList.add(list01);mapList.add(list02);mapList.add(list03);mapList.add(list04);BaseXWPFDocument doc = CrtWordUtils.changWord("D:/test.docx",data,mapList);FileOutputStream fopts = new FileOutputStream("D:/stu.doc");/**--------此处实在文档的最后插入一张图片       可尝试在指定的段落中插入(此处未实现) ------*/FileInputStream fis = new FileInputStream("D:/1.png");byte[] byteArray = IOUtils.toByteArray(fis);ByteArrayInputStream bais = new ByteArrayInputStream(byteArray);ImageIO.read(bais);XWPFParagraph paragraph = doc.createParagraph();XWPFRun run2 = paragraph.createRun();/*//原始值int width = Units.toEMU(image.getWidth());int height = Units.toEMU(image.getHeight());*///自定义值int width = Units.toEMU(360);int height = Units.toEMU(360);run2.addPicture(new FileInputStream("D:/1.png"), BaseXWPFDocument.PICTURE_TYPE_PNG, "test",width, height);/**--------此处实在文档的最后插入一张图片------*/doc.write(fopts);fopts.close();}}

最终生成的文档(方便观看,多页展示了-^^-)

poi根据模板导出word(包含图片、动态生成表格、合并单元格)(亲测有效)相关推荐

  1. 【springboot+poi+poi-tl 模板导出wrod (包含图片集合、页眉、页脚)】

    springboot+poi+poi-tl 模板导出wrod 1. maven依赖 <dependency><groupId>org.apache.poi</groupI ...

  2. poi使用模板导出word带图片

    1.下面是我做的加载模板导出带图片的word的导出方式,使用之前请映入freemarker的jar包,可以从百度下载即可. 2.首先准备到你要导出的word模板,在要填充的模板中填入el表达式,如下图 ...

  3. POI根据模板导出word文件,以及word转PDF,PDF转图片再插入PDF中(防止PDF被修改)

    POI操作word和PDF POI根据模板导出word文件 word转PDF PDF转图片再插入PDF中(防止PDF被修改) POI根据模板导出word文件 一.制作word模版,${xxxx}是一会 ...

  4. 纯前端JS导出Word包含图片

    纯前端JS导出Word包含图片 纯前端JS导出Word文档包含图片 Word导出方式 依赖 实现代码 纯前端JS导出Word文档包含图片 在做项目中,遇到一个需求,是将后台返回的属性以及URL图片导出 ...

  5. EasyExcel根据自定义模板导出Excel(包含图片、表格)

    使用EasyExcel根据模板导出excel,包含图片.表格 提示:其实使用EasyExcel根据模板导出一个excel并不难,难点在于指定图片的位置 文章目录 使用EasyExcel根据模板导出ex ...

  6. freemarker模板导出word循环图片表格详细教程

    前言:表哥之前已经过一篇freemarker模板导出带表格word详细教程  freemarker模板导出带表格word详细教程_Java大表哥的博客-CSDN博客,为什么现在又要写一篇呢. 因为我这 ...

  7. 使用POI创建word表格合并单元格兼容wps

    poi创建word表格合并单元格代码如下: /** * @Description: 跨列合并 */ public void mergeCellsHorizontal(XWPFTable table, ...

  8. Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略)

    Web中的EasyExcel导出Excel(不创建对象且自定义合并单元格策略) 适用于多张表(只查单表数据就用创建对象那种方法) Controller @RequestMapping(value = ...

  9. x-data-spreadsheet 在线编辑excel文件,支持导入/导出/上传/读取网络 excel,合并单元格(vue版本)

    1. 环境 vue:2.6.10 x-data-spreadsheet:1.1.8 less:4.0.0 less-loader:7.1.0 xlsx:0.15.1 axios:0.18.1 2. 优 ...

最新文章

  1. 当前标识(NT AUTHORITY\NETWORK SERVICE)没有对“的写访问权限。
  2. Tiny4412裸机程序,按键检测(轮询方式)
  3. foreach形式的for语句
  4. WeChat报错navigateTo:fail can not navigateTo a tabbar page
  5. Python二级基础知识点
  6. 上午绿茶下午菊花茶晚上枸杞
  7. php转换ofd文件格式,一种OFD格式文档支持脚本的方法与流程
  8. 实例88:构建InfoGAN生成MNIST模拟数据
  9. OpenGLCG技术之Render To Texture
  10. java中的打印pdf_Java 打印PDF文档
  11. 计算机系统的层次结构(计算机组成原理5)
  12. 从屡遭拒稿到90后助理教授,罗格斯大学王灏:好奇心驱使我不断探索
  13. 工作流应用 电子表单签核
  14. 【STM32F429】第5章 RL-USB移植(MDK AC6)
  15. 生产者与消费者模式的概念、运用、3种实现
  16. 浅析简历——中华英才网
  17. 如何设置IIS中的HTTPS服务
  18. Linux的发音问题
  19. 搞了三年,再看数据中台的价值与解决方案
  20. 华为OD机试 九宫格按键输入法

热门文章

  1. 不让用计算机怎么回怼,当别人怼你时,如何优雅地怼回去
  2. 学会Redis缓存中间件,这一篇就够了
  3. 如何有效提高公众号文章阅读量
  4. ubuntu解决 Can‘t locate Time/HiRes.pm in @INC 安装Time::HiRes教程
  5. 当python遇上echarts (三)绘制3D图表
  6. Matlab img格式图片转为dicom格式
  7. 谷歌浏览器批量删除书签
  8. iOS 模拟器安装APP,在电脑上运行ios的app
  9. OI模板 卢卡斯定理
  10. PDF编辑器首选工具Acrobat Pro DC