原文链接:https://blog.csdn.net/u012775558/article/details/79678701

根据原代码新增了插入符号和控制分页功能。改了类名,一些方法,新增一个符号类。

模板


导出结果

代码:

工具类:

package com.demo.util;import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.poi.xwpf.usermodel.*;/*** @ClassName:POIWordUtil* @Description: poi导出word嵌套循环* @Date:2022/10/20 14:02**/
public class POIWordUtil {private XWPFDocument document;public XWPFDocument getDocument() {return document;}public void setDocument(XWPFDocument document) {this.document = document;}/*** 初始化模板内容* @param inputStream 模板的读取流(docx文件)* @throws IOException**/public POIWordUtil(InputStream inputStream) throws IOException {document = new XWPFDocument(inputStream);}/*** 将处理后的内容写入到输出流中* @param outputStream* @throws IOException*/public void write(OutputStream outputStream) throws IOException {document.write(outputStream);}/*** 根据dataMap对word文件中的标签进行替换;* !!!!***需要注意dataMap的数据格式***!!!!* 对于需要替换的普通标签数据标签(不需要循环)-----必须在dataMap中存储一个key为parametersMap的map,* 来存储这些不需要循环生成的数据,比如:表头信息,日期,制表人等。* 对于需要循环生成的表格数据------key自定义,value为 --ArrayList<Map<String, String>>*   关于模板:*     循环表格:需在表格上新增一行分为两列,第一列固定为  ##{foreachTable}## ;第二列为循环表名称,即map的 key值*         表格内的数据替换内容为 {key}*     表格内循环:需在表格上新增一行分为两列,第一列固定为  ##{foreachTableRow}## ;第二列为表名称,即map的 key值*         在需循环的列的上方新增一行固定为 ##{foreachRows}##*         循环列数据替换内容为 {key}* @param dataMap*/public void replaceDocument(Map<String, Object> dataMap) throws Exception {if (!dataMap.containsKey("parametersMap")) {throw new Exception("数据源错误--数据源(parametersMap)缺失");}@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) {throw new Exception("文档中第"+ (curT + 1)+ "个表格模板错误,模板表格第一行需要设置2个单元格,"+ "第一个单元格存储表格类型(##{foreachTable}## 或者 ##{foreachTableRow}##),第二个单元格定义数据源。");}String tableType = tableCells.get(0).getText();String dataSource = tableCells.get(1).getText();if (!dataMap.containsKey(dataSource)) {throw new Exception("文档中第" + (curT + 1) + "个表格模板数据源缺失");}@SuppressWarnings("unchecked")List<Map<String, Object>> tableDataList = (List<Map<String, Object>>) dataMap.get(dataSource);if ("##{foreachTable}##".equals(tableType)) {addTableInDocFooter(table, tableDataList, parametersMap, 1,dataMap.get("interval") != null ? (int) dataMap.get("interval") : null,dataMap.get("paging") != null ? (int) dataMap.get("paging") : null);} else if ("##{foreachTableRow}##".equals(tableType)) {addTableInDocFooter(table, tableDataList, parametersMap, 2,null,null);}} else if (tableText.indexOf("{") > -1) {// 没有查找到##{foreach标签,查找到了普通替换数据的{}标签,该表格只需要简单替换addTableInDocFooter(table, null, parametersMap, 3,null,null);} else {// 没有查找到任何标签,该表格是一个静态表格,仅需要复制一个即可。addTableInDocFooter(table, null, null, 0,null,null);}curT++;}} else if (BodyElementType.PARAGRAPH.equals(body.getElementType())) {// 处理段落XWPFParagraph ph = body.getBody().getParagraphArray(curP);if (ph != null) {addParagraphInDocFooter(ph, null, parametersMap, 0);curP++;}}}// 处理完毕模板,删除文本中的模板内容for (int a = 0; a < templateBodySize; a++) {document.removeBodyElement(0);}}/*** 根据 模板表格 和 数据list 在word文档末尾生成表格* @param templateTable 模板表格* @param list   循环数据集* @param parametersMap  不循环数据集* @param flag   (0为静态表格,1为表格整体循环,2为表格内部行循环,3为表格不循环仅简单替换标签即可)* @param interval (只用于flag == 1)循环表格之间的回车数,默认间隔1个回车,用于手动调整布局* @param paging (只用于flag == 1)循环表格每循环几次分页,用于手动调整布局*/public void addTableInDocFooter(XWPFTable templateTable, List<Map<String, Object>> list,Map<String, Object> parametersMap, int flag,Integer interval,Integer paging) {if (flag == 1) {// 表格整体循环int index = 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));// 复制模板行文本和样式到新行}newCreateTable.removeRow(0);// 移除多出来的第一行document.createParagraph();// 添加回车换行if(interval != null && interval > 1){for(int i = 1;i < interval;i++){document.createParagraph();}}replaceTable(newCreateTable, map);//替换标签//分页(几次循环分页一次)if(paging != null && paging > 0 && index%paging == 0){document.createParagraph().createRun().addBreak(BreakType.PAGE);}index ++;}} else if (flag == 2) {// 表格表格内部行循环XWPFTable newCreateTable = document.createTable();// 创建新表格,默认一行一列List<XWPFTableRow> TempTableRows = templateTable.getRows();// 获取模板表格所有行int tagRowsIndex = 0;// 标签行indexsfor (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();// 添加回车换行}}/*** 根据 模板段落 和 数据 在文档末尾生成段落* @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替换段落元素内的{**}标签* @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));setValue(insertNewRun,parametersMap.get(key.toString()),null,null);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 start = beginRunText.substring(0, beginIndex);String end = beginRunText.substring(endIndex + 1);setValue(insertNewRun,parametersMap.get(key.toString()),start,end);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<>();//需要移除的run//处理中间的runfor (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());// 设置文本setValue(insertNewRun,parametersMap.get(key.toString()),null,null);xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run}else {// 该run标签为**{**或者 {** ,替换key后,还需要加上原始key前的文本XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());// 设置文本String start = beginRunText.substring(0,beginRunText.indexOf("{"));setValue(insertNewRun,parametersMap.get(key.toString()),start,null);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));//原始runXWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());insertNewRun.setText("");xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run}}// 处理${**}被分成多个runreplaceParagraph( 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));}}/*** 复制单元格XWPFTableCell格式* @param newTableCell 新创建的的单元格* @param templateTableCell 模板单元格*/private void copyTableCell(XWPFTableCell newTableCell, XWPFTableCell templateTableCell) {// 列属性newTableCell.getCTTc().setTcPr(templateTableCell.getCTTc().getTcPr());// 删除目标 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格式* @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* @param newRun 新创建的的文本节点* @param templateRun 模板文本节点**/private void CopyRun(XWPFRun newRun, XWPFRun templateRun) {newRun.getCTR().setRPr(templateRun.getCTR().getRPr());// 设置文本newRun.setText(templateRun.text());}/*** 根据参数parametersMap对表格的一行进行标签的替换* @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}标签* @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);}}}}/*** @Title: setValue* @Description: 设置内容* @Param: [run, value, start, end]* @return: void**/private void setValue(XWPFRun run,Object value,String start,String end){String val = null;if(value != null && value instanceof WordSymbol){//符号WordSymbol wordSymbol = (WordSymbol) value;run.setFontFamily(wordSymbol.getTypeface(), wordSymbol.getFcr());val = wordSymbol.getCode();}else{val = value != null ? value.toString() : "";}if(start != null){val = start + val;}if(end != null){val += end;}run.setText(val);}
}

符号类:

package com.demo.util;import org.apache.poi.xwpf.usermodel.XWPFRun;/*** @ClassName:WordSymbol* @Description: 符号类* @Date:2022/10/21 10:33**/
public class WordSymbol {private String typeface;//字体private String code;//编码private XWPFRun.FontCharRange fcr;WordSymbol(String typeface, String code, XWPFRun.FontCharRange fcr){this.typeface = typeface;this.code = code;this.fcr = fcr;}public String getTypeface() {return typeface;}public void setTypeface(String typeface) {this.typeface = typeface;}public String getCode() {return code;}public void setCode(String code) {this.code = code;}public XWPFRun.FontCharRange getFcr() {return fcr;}public void setFcr(XWPFRun.FontCharRange fcr) {this.fcr = fcr;}/*** @Title: getSymbol1* @Description: 常用符号1:框打勾* @author: wdk* @Date: 2022/10/21 11:38**/public static WordSymbol getSymbol1(){return new WordSymbol("Wingdings 2","\u0052",XWPFRun.FontCharRange.ascii);}/*** @Title: getSymbol2* @Description: 常用符号2:框未勾* @Date: 2022/10/21 11:38**/public static WordSymbol getSymbol2(){return new WordSymbol("Wingdings 2","\u00A3",XWPFRun.FontCharRange.hAnsi);}
}

使用:

import com.demo.util.POIWordUtil;
import com.demo.util.WordSymbol;
import org.junit.Test;
import org.springframework.util.ResourceUtils;import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.*;public class WordTest {@Testpublic void test() throws Exception {Map<String, Object> wordDataMap = new HashMap<String, Object>();// 存储报表全部数据Map<String, Object> parametersMap = new HashMap<String, Object>();// 存储报表中不循环的数据List<Map<String, Object>> table1 = new ArrayList<Map<String, Object>>();Date date = new Date();SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日");SimpleDateFormat sdf2 = new SimpleDateFormat("yyyyMMdd");for(int i=1;i<5;i++){Map<String, Object> map = new HashMap<>();map.put("custName","XX有限公司");map.put("mcode","A1-D006-A0269-2-6");map.put("taskPro","新规");map.put("coefficient","5.0");map.put("designer","张三");WordSymbol sel = WordSymbol.getSymbol1();WordSymbol noSel = WordSymbol.getSymbol2();map.put("jsM1",i%2 == 0 ? sel : noSel);map.put("jsM2",i%2 != 0 ? sel : noSel);map.put("date",sdf.format(date));map.put("name","CAE放回弹");map.put("endTime",sdf.format(date));map.put("completeDate",sdf.format(date));map.put("eDgs",8);map.put("awHours",8);map.put("rwHours",7);map.put("approvalMan","李四");map.put("code", sdf2.format(date) + String.format("%03d", i));map.put("sendWorkers","王五");map.put("projectDate",sdf.format(date));table1.add(map);}wordDataMap.put("table1", table1);wordDataMap.put("parametersMap", parametersMap);wordDataMap.put("interval",3);//循环表格之间的回车数,默认间隔1个回车,用于手动调整布局wordDataMap.put("paging",3);//循环表格每循环几次分页,用于手动调整布局// 读取word模板FileInputStream fileInputStream = new FileInputStream(ResourceUtils.getFile("classpath:doc/printDispatchList.docx"));POIWordUtil template = new POIWordUtil(fileInputStream);// 替换数据template.replaceDocument(wordDataMap);//生成文件File outputFile=new File("D:\\work\\file\\派工单打印.docx");FileOutputStream fos  = new FileOutputStream(outputFile);template.getDocument().write(fos);}
}

java使用Apache poi根据word模板生成word报表(增加插入符号、控制分页功能)相关推荐

  1. apache poi使用例_使用java Apache poi 根据word模板生成word报表例子

    [实例简介] 使用java Apache poi 根据word模板生成word报表 仅支持docx格式的word文件,大概是word2010及以后版本,doc格式不支持. 使用说明:https://b ...

  2. 使用java Apache poi 根据word模板生成word报表

    使用java Apache poi 根据word模板生成word报表 使用poi读取word模板,替换word中的{text}标签,并根据自定义标签循环生成表格或表格中的行. 代码示例下载:https ...

  3. java 根据word模板生成word文件

    Java可以使用Apache POI库来生成Word文件,并且也可以使用freemarker等模板引擎来实现根据Word模板生成Word文件的功能. 下面是一个简单的示例代码,可以帮助您快速入门. 模 ...

  4. JAVA实现模板word文档导入,Java依据word模板生成word文档之后台解析和实现及部分代码(一)...

    Java根据word模板生成word文档之后台解析和实现及部分代码(一) 后台主要工作是解析XML定义的标签文件,并获取到数据集,放入到Map中,然后调用Jacob.jar中提供的相关方法来实现替换. ...

  5. 根据word模板生成word和PDF

    根据word模板生成word和PDF 需求:有一个固定的合同模板,在vue前台填写指定的信息,替换合同模板指定的内容 我们使用的默认模板内容如图: 我们在前端填写的字段就是合同名称.项目名称和项目金额 ...

  6. 使用word模板生成word文档的各类方案

    使用word模板生成word文档的各类方案 生成word的各种方案 word另存xml进行后续处理 2003版本word(.doc)的xml处理并生成word 2007版本word(.docx)的xm ...

  7. word模板生成word报表文档

    主要功能为根据word模板生成word报表文档,注意引用Interop.Word.dll; 首先要生成word程序对象 Word.Application app = new Word.Applicat ...

  8. C#根据word模板生成word表格报表文档

    主要功能为根据word模板生成word报表文档,注意引用Interop.Word.dll; 首先要生成word程序对象 Word.Application app = new Word.Applicat ...

  9. PHP 使用word模板生成word文档示例

    <?php namespace Home\Controller; use PhpOffice\PhpWord\TemplateProcessor; use Think\Controller; c ...

最新文章

  1. Python 进度条 tqdm
  2. UVA10881蚂蚁
  3. bzoj2002Bounce 弹飞绵羊
  4. Hive的六种UDF完整实例与使用方法汇总
  5. 与狼共舞·美女与野兽
  6. sklearn线性回归详解
  7. 论文浅尝 | 用异源监督进行关系抽取:一种表示学习方法
  8. Chrome谷歌插件开发-01
  9. sqlserver2012——XML查询
  10. 基于汉语短文本对话的立场检测系统理论与实践
  11. Running pip as root will break packages and permissions. You should install packages reliably by usi
  12. c语言中的EOF是什么意思
  13. 按右手定则求已经知三点的法向量
  14. 最全74HC04六反相器中文资料|引脚图及功能表|应用电路图
  15. 蓝桥杯练习题之数列特征
  16. windows10 安装office2021(预装正版)经验分享
  17. 苹果youtube无法连接网络_解决苹果手机Apple ID被禁止下载或无法连接到AppStore等问题...
  18. 机器学习Sklearn——红酒分类案例详解决策树模型参数
  19. 笔记本拆c面_继续拆解 C面下方还藏有玄机_神舟 战神GX8 PRO_笔记本评测-中关村在线...
  20. 华中科技大学计算机科学与技术学院郑强教授,华中科技大学教授声讨后勤被处分 校方:通报批评,取消2年评优...

热门文章

  1. PHP使用正则表达式匹配中文,有部分匹配不出来的解决办法
  2. android 如何实现一键清理
  3. Java 笔记【前言】
  4. originPro2021(6)如何修改Origin里图例的顺序
  5. 树莓派lite版开机注意事项
  6. linux下的cpu温度监控软件 lm-sensors
  7. 为何鲁大师为变成一个流氓软件?
  8. Acwing 4339 敌兵布阵 暴力 + 分块 + 线段树 + Zkw线段树 + 树状数组
  9. 机器学习与量化交易∙笔记(3)
  10. [Split The Tree][dfs序+树状数组求区间数的种数]