一、制作word模版,${xxxx}是一会要替换的内容,最下面的表格是要插入数据,根据是否以$开头来判断是需要替换还是插入数据,
- 注意如果是需要循环插入数据,制作的表格模版需要一行全部输入井号#,格式样式可以对#设置
- 表格中${header}和${hearder2}是放入需要替换的图片
- 替换数据的格式样式同$的一样
- 如果需要根据数据再确定需要在哪替换图片,可以使用带ImgAgain的方法,原理是数据先替换为*{}占位符,再替换一遍
- 一些设置参数,看getWord方法参数
- 支持:段落插表格(有两个插入表格的方法)
- 支持公式:看六,得具体分析
- 不支持特殊格式:如上下标、双行合一等
- 复制表格时及循环插入不支持特殊样式:如高亮、艺术字体、快速样式(复制表格,循环时无法复制高亮样式)等
- 复制表格时,若字体原来为默认五号,则复制是变为10号字体,应为10.5,但只支持传整数 :(
- 表格中特殊符号:#、$、{、}、,使用时需注意,在循环插入数据的单元格内 [ ] 中括号也是特殊符号
- 循环插数据的表格列数支持多或少;支持调换列的顺序
- 循环插数据的表格行中每个单元格都要有#
- 在循环单元格内允许有多个段落,单插入数据的段落需是单独段落,且#号开头
- 循环插数据的以#开头,后面跟 [ ] ,里面写数据顺序的序号(注意第一列是以零0开头),若按默认循序则不用加 [ ] ,若在数据长度内的单元格又不想填数据则中括号没填-1及 [-1]
- 循环插数据的数据格式样式同#,所以模板可以自定义#格式样式
循环数据行举例:
结果:
下面是测试模板
二、添加poi所需要的jar包文件,我用的maven对jar包进行管理
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.15</version>
</dependency>
三、由于poi自身bug,会出现图片无法显示问题,这里需要自定义一个类继承XWPFDocument类,接下来使用的都是我们自己创建的这个类来操作word对象,这个
类对XWPFDocument进行了继承,所以不用担心会有什么问题
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;
import java.io.IOException;
import java.io.InputStream;
/*******************************************
*
* @Package com.cccuu.project.myUtils
* @Author duan
* @Date 2018/3/29 17:55
* @Version V1.0
*******************************************/
public class CustomXWPFDocument extends XWPFDocument {
public CustomXWPFDocument(InputStream in) throws IOException {
super(in);
}
public CustomXWPFDocument() {
super();
}
public CustomXWPFDocument(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();
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("测试");
}
}
四、接下来就是导出word的工具类了
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* <b> 通过word模板生成新的word工具类
* </b><br><br><i>Description</i> :
* <br><br>Date: 2019/12/9 ${time} <br>Author : dxl
*/
public class WordGrtUtil {
public static void main(String[] args) throws Exception {
// wordGrtUtil.copyTbaleByLoop("C:\\Users\\00\\Desktop\\baogao\\testmodel.docx",0,4,"C:\\Users\\00\\Desktop\\baogao\\testmodel-copy.docx");
// WordGrtUtil wordGrtUtil=new WordGrtUtil();
Map<String, Object> params = new HashMap<String, Object>();
params.put("${position}", "*{aaa}");
params.put("${name}", "222段然涛222");
params.put("${sex}", "男");
params.put("${national}", "汉族");
params.put("${birthday}", "生日");
params.put("${address}", "许昌");
params.put("${height}", "165cm");
params.put("${biYeDate}", "1994-02-03");
params.put("${landscape}", "团员");
params.put("${zhuanYe}", "社会工作");
params.put("${xueLi}", "本科");
params.put("${school}", "江西科技师范大学");
params.put("${phone}", "177");
params.put("${eMail}", "157");
try{
Map<String,Object> header = new HashMap<String, Object>();
header.put("width", 50);
header.put("height", 50);
header.put("type", "jpg");
header.put("content", inputStream2ByteArray(new FileInputStream("C:\\Users\\00\\Desktop\\baogao\\tupian\\垂直度.jpg"), true));
params.put("${tihuan}",header);
params.put("*{aaa}",header);
// Map<String,Object> header2 = new HashMap<String, Object>();
// header2.put("width", 100);
// header2.put("height", 150);
// header2.put("type", "jpg");
// header2.put("content", WordUtils.inputStream2ByteArray(new FileInputStream("C:/Users/Administrator/Desktop/jar包/22.jpg"), true));
// params.put("${header2}",header2);
List<String[]> testList = new ArrayList<String[]>();
testList.add(new String[]{"1","1AA","1BB","1CC"});
testList.add(new String[]{"2","2AA","2BB","2CC"});
testList.add(new String[]{"3","3AA","3BB","3CC"});
testList.add(new String[]{"4","4AA","4BB","4CC"});
String modelPath="C:\\Users\\00\\Desktop\\baogao\\testmodel3.docx"; //模板文件位置
String stroePath="C:\\Users\\00\\Desktop\\baogao\\aaaa.docx"; //模板文件位置
String fileName= new String("测试文档.docx".getBytes("UTF-8"),"iso-8859-1"); //生成word文件的文件名
List<List<Integer>> mergeRowLists = new ArrayList<>();
WordGrtUtil.getWordStore(modelPath,params,testList,stroePath,false,0,2,false,null);
// wordGrtUtil.getWord(path,params,testList,fileName);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 根据模板生成word 并存储
* @param srcPath 模板的路径
* @param params 需要替换的参数
* @param tableList 需要循环插入的参数
* @param storePath 生成的word文件存储路径,包含文件名全称
* @param isCopyTable 是否需要循环复制表格,
* @param copyTableIndex 复制第几个表格,若copyTable为false,后两个参数随便填
* @param copyTableNum 复制几个表格
* @param isMergeRow 是否自动合并行
* @param mergeRowLists List<Integer>应包含三个,第一个为要合并的列,第二个合并的起始行,第三个合并的结束行
*/
public static void getWordStore(String srcPath, Map<String, Object> params, List<String[]> tableList, String storePath,boolean isCopyTable,int copyTableIndex,int copyTableNum,boolean isMergeRow,List<List<Integer>> mergeRowLists) throws Exception {
File file = new File(srcPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(isCopyTable){
String temPath = file.getParentFile()+"/tem"+System.currentTimeMillis()+file.getName();
copyTbaleByLoop(srcPath,copyTableIndex,copyTableNum,temPath);
File fileTem = new File(temPath);
InputStream is = new FileInputStream(fileTem);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInPara(doc, params); //替换文本里面的变量
OutputStream os = new FileOutputStream(storePath);
doc.write(os);
close(os);
close(is);
File fileDel = new File(temPath);
if(fileDel.exists()){
fileDel.delete();
}
}else {
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInPara(doc, params); //替换文本里面的变量
OutputStream os = new FileOutputStream(storePath);
doc.write(os);
close(os);
close(is);
}
}
/**
* 根据模板生成word 不存储直接下载
* @param srcPath 模板的路径
* @param params 需要替换的参数
* @param tableList 需要插入的参数
* @param fileName 生成word文件的文件名
* @param response
* @param isCopyTable 是否需要循环复制表格,
* @param copyTableIndex 复制第几个表格,若copyTable为false,后两个参数随便填
* @param copyTableNum 复制几个表格
* @param isMergeRow 是否自动合并行
* @param mergeRowLists List<Integer>应包含三个,第一个为要合并的列,第二个合并的起始行,第三个合并的结束行
*/
public static void getWordDown(String srcPath, Map<String, Object> params, List<String[]> tableList, String fileName, HttpServletResponse response,boolean isCopyTable,int copyTableIndex,int copyTableNum,boolean isMergeRow,List<List<Integer>> mergeRowLists) throws Exception {
fileName= new String(fileName.getBytes("UTF-8"),"iso-8859-1");
File file = new File(srcPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(isCopyTable){
String temPath = file.getParentFile()+"/tem"+System.currentTimeMillis()+file.getName();
copyTbaleByLoop(srcPath,copyTableIndex,copyTableNum,temPath);
File fileTem = new File(temPath);
InputStream is = new FileInputStream(fileTem);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInPara(doc, params); //替换文本里面的变量
OutputStream os = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(os);
close(os);
close(is);
File fileDel = new File(temPath);
if(fileDel.exists()){
fileDel.delete();
}
}else {
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInPara(doc, params); //替换文本里面的变量
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
OutputStream os = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(os);
close(os);
close(is);
}
}
/**
* 根据模板生成word 存储并下载
* @param srcPath 模板的路径
* @param params 需要替换的参数
* @param tableList 需要插入的参数
* @param fileName 生成word文件的文件名
* @param response
* @param isCopyTable 是否需要循环复制表格,
* @param copyTableIndex 复制第几个表格,若copyTable为false,后两个参数随便填
* @param copyTableNum 复制几个表格
* @param isMergeRow 是否自动合并行
* @param mergeRowLists List<Integer>应包含三个,第一个为要合并的列,第二个合并的起始行,第三个合并的结束行
*/
public static void getWordStoreAndDown(String srcPath, Map<String, Object> params, List<String[]> tableList, String storePath, String fileName, HttpServletResponse response,boolean isCopyTable,int copyTableIndex,int copyTableNum,boolean isMergeRow,List<List<Integer>> mergeRowLists) throws Exception {
fileName= new String(fileName.getBytes("UTF-8"),"iso-8859-1");
File file = new File(srcPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(isCopyTable){
String temPath = file.getParentFile()+"/tem"+System.currentTimeMillis()+file.getName();
copyTbaleByLoop(srcPath,copyTableIndex,copyTableNum,temPath);
File fileTem = new File(temPath);
InputStream is = new FileInputStream(fileTem);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInPara(doc, params); //替换文本里面的变量
OutputStream oss = new FileOutputStream(temPath);
OutputStream osd = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(oss);
doc.write(osd);
close(oss);
close(osd);
close(is);
File fileDel = new File(temPath);
if(fileDel.exists()){
fileDel.delete();
}
}else {
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInPara(doc, params); //替换文本里面的变量
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
OutputStream oss = new FileOutputStream(storePath);
OutputStream osd = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(oss);
doc.write(osd);
close(oss);
close(osd);
close(is);
}
}
/**
* 根据模板生成word 并存储
* 因为有的地方替换图片不确定,先替换成其他占位符,在替换掉
* @param srcPath 模板的路径
* @param params 需要替换的参数
* @param tableList 需要循环插入的参数
* @param storePath 生成的word文件存储路径,包含文件名全称
* @param isCopyTable 是否需要循环复制表格,
* @param copyTableIndex 复制第几个表格,若copyTable为false,后两个参数随便填
* @param copyTableNum 复制几个表格
* @param isMergeRow 是否自动合并行
* @param mergeRowLists List<Integer>应包含三个,第一个为要合并的列,第二个合并的起始行,第三个合并的结束行
*/
public static void getWordStoreImgAgain(String srcPath, Map<String, Object> params, List<String[]> tableList, String storePath,boolean isCopyTable,int copyTableIndex,int copyTableNum,boolean isMergeRow,List<List<Integer>> mergeRowLists) throws Exception {
File file = new File(srcPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(isCopyTable){
String temPath = file.getParentFile()+"/tem"+System.currentTimeMillis()+file.getName();
copyTbaleByLoop(srcPath,copyTableIndex,copyTableNum,temPath);
File fileTem = new File(temPath);
InputStream is = new FileInputStream(fileTem);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInParaImgAgain(doc, params); //替换文本里面的变量
OutputStream os = new FileOutputStream(storePath);
doc.write(os);
close(os);
close(is);
File fileDel = new File(temPath);
if(fileDel.exists()){
fileDel.delete();
}
}else {
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInParaImgAgain(doc, params); //替换文本里面的变量
OutputStream os = new FileOutputStream(storePath);
doc.write(os);
close(os);
close(is);
}
}
/**
* 根据模板生成word 不存储直接下载
* 因为有的地方替换图片不确定,先替换成其他占位符,在替换掉
* @param srcPath 模板的路径
* @param params 需要替换的参数
* @param tableList 需要插入的参数
* @param fileName 生成word文件的文件名
* @param response
* @param isCopyTable 是否需要循环复制表格,
* @param copyTableIndex 复制第几个表格,若copyTable为false,后两个参数随便填
* @param copyTableNum 复制几个表格
* @param isMergeRow 是否自动合并行
* @param mergeRowLists List<Integer>应包含三个,第一个为要合并的列,第二个合并的起始行,第三个合并的结束行
*/
public static void getWordDownImgAgain(String srcPath, Map<String, Object> params, List<String[]> tableList, String fileName, HttpServletResponse response,boolean isCopyTable,int copyTableIndex,int copyTableNum,boolean isMergeRow,List<List<Integer>> mergeRowLists) throws Exception {
fileName= new String(fileName.getBytes("UTF-8"),"iso-8859-1");
File file = new File(srcPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(isCopyTable){
String temPath = file.getParentFile()+"/tem"+System.currentTimeMillis()+file.getName();
copyTbaleByLoop(srcPath,copyTableIndex,copyTableNum,temPath);
File fileTem = new File(temPath);
InputStream is = new FileInputStream(fileTem);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInParaImgAgain(doc, params); //替换文本里面的变量
OutputStream os = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(os);
close(os);
close(is);
File fileDel = new File(temPath);
if(fileDel.exists()){
fileDel.delete();
}
}else {
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInParaImgAgain(doc, params); //替换文本里面的变量
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
OutputStream os = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(os);
close(os);
close(is);
}
}
/**
* 根据模板生成word 存储并下载
* 因为有的地方替换图片不确定,先替换成其他占位符,在替换掉
* @param srcPath 模板的路径
* @param params 需要替换的参数
* @param tableList 需要插入的参数
* @param fileName 生成word文件的文件名
* @param response
* @param isCopyTable 是否需要循环复制表格,
* @param copyTableIndex 复制第几个表格,若copyTable为false,后两个参数随便填
* @param copyTableNum 复制几个表格
* @param isMergeRow 是否自动合并行
* @param mergeRowLists List<Integer>应包含三个,第一个为要合并的列,第二个合并的起始行,第三个合并的结束行
*/
public static void getWordStoreAndDownImgAgain(String srcPath, Map<String, Object> params, List<String[]> tableList, String storePath, String fileName, HttpServletResponse response,boolean isCopyTable,int copyTableIndex,int copyTableNum,boolean isMergeRow,List<List<Integer>> mergeRowLists) throws Exception {
fileName= new String(fileName.getBytes("UTF-8"),"iso-8859-1");
File file = new File(srcPath);
if(!file.getParentFile().exists()){
file.getParentFile().mkdirs();
}
if(isCopyTable){
String temPath = file.getParentFile()+"/tem"+System.currentTimeMillis()+file.getName();
copyTbaleByLoop(srcPath,copyTableIndex,copyTableNum,temPath);
File fileTem = new File(temPath);
InputStream is = new FileInputStream(fileTem);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
replaceInParaImgAgain(doc, params); //替换文本里面的变量
OutputStream oss = new FileOutputStream(temPath);
OutputStream osd = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(oss);
doc.write(osd);
close(oss);
close(osd);
close(is);
File fileDel = new File(temPath);
if(fileDel.exists()){
fileDel.delete();
}
}else {
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
replaceInParaImgAgain(doc, params); //替换文本里面的变量
replaceInTable(doc, params,tableList,isMergeRow,mergeRowLists); //替换表格里面的变量
OutputStream oss = new FileOutputStream(storePath);
OutputStream osd = response.getOutputStream();
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
doc.write(oss);
doc.write(osd);
close(oss);
close(osd);
close(is);
}
}
/**
* <b> 循环复制Word中的表格
* </b><br><br><i>Description</i> :
* @param srcPath 模板路径, srcTableIndex 模板中复制目标表格的下标, copyNum 复制个数, storePath 存储路径(包含文件名全称)
* @return void
* <br><br>Date: 2019/12/9 13:21 <br>Author : dxl
*/
public static void copyTbaleByLoop(String srcPath, int srcTableIndex,int copyNum,String storePath) throws Exception {
File file = new File(srcPath);
InputStream is = new FileInputStream(file);
CustomXWPFDocument doc = new CustomXWPFDocument(is);
XWPFTable sourceTable = doc.getTableArray(srcTableIndex);
for(int j = 0; j < copyNum; j++){
XWPFTable tableOne = doc.createTable();
for(int i = 0; i < sourceTable.getRows().size(); i++){
copy(tableOne,sourceTable.getRow(i),i);
}
doc.createParagraph();
tableOne.removeRow(tableOne.getRows().size()-1);
}
OutputStream os = new FileOutputStream(storePath);
doc.write(os);
close(os);
close(is);
}
/**
* 替换段落里面的变量
* @param doc 要替换的文档
* @param params 参数
*/
private static void replaceInPara(CustomXWPFDocument doc, Map<String, Object> params) throws IOException {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
// List<XWPFParagraph> paragraphs = doc.getParagraphs();
// for(int i = paragraphs.size()-1; i >= 0; i--){
// replaceInPara(paragraphs.get(i), params, doc);
// insertTableInParaFromAtherDoc("C:\\Users\\00\\Desktop\\baogao\\testmodel4.docx",0,doc,paragraphs.get(i),false);
// }
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
replaceInPara(para, params, doc);
}
}
/**
* 替换段落里面的变量
* @param doc 要替换的文档
* @param params 参数
*/
private static void replaceInParaImgAgain(CustomXWPFDocument doc, Map<String, Object> params) {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
replaceInPara(para, params, doc);
replaceImgAgain(para, params, doc);
}
}
/**
* 替换段落里面的变量
*
* @param para 要替换的段落
* @param params 参数
*/
private static void replaceInPara(XWPFParagraph para, Map<String, Object> params, CustomXWPFDocument doc) {
List<XWPFRun> runs;
Matcher matcher;
if (matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
int start = -1;
int end = -1;
String str = "";
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
if ((runText.length() > 0 && runText.contains("${"))
|| (runText.length() > 0 && '$' == runText.charAt(runText.length() - 1) && i+1 <runs.size() && '$' == runs.get(i+1).toString().charAt(0))) {
start = i;
}
if (runText.length() > 0 && runText.contains("}")) {
if (start != -1) {
end = i;
break;
}
}
}
for(int i = start; i <= end; i++){
str = str + runs.get(i).toString();
}
//去掉标识符开始之后到结束的run,保留第一个run是为了使用run的样式
for (int i = start+1; i <= end; i++) {
para.removeRun(i);
i--;
end--;
}
for (Map.Entry<String, Object> entry : params.entrySet()) {
String key = entry.getKey();
if (str.indexOf(key) != -1) {
Object value = entry.getValue();
if (value instanceof String) {
str = str.replace(key, value.toString());
para.getRuns().get(start).setText(str,0);//替换保留的第一个run中的内容,若没有0就变为插入了
break;
} else if (value instanceof Map) {
str = str.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);
try {
//int ind = doc.addPicture(byteInputStream,picType);
//doc.createPicture(ind, width , height,para);
doc.addPictureData(byteInputStream, picType);
if(start == 0){
para.getRuns().get(0).setText("",0);
doc.createPicture(doc.getAllPictures().size() - 1, width, height, para,start);
}else {
para.removeRun(start);
doc.createPicture(doc.getAllPictures().size() - 1, width, height, para,start-1);
}
break;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
if (matcher(para.getParagraphText()).find()) {
replaceInPara(para, params, doc);
}
}
/**
* 为表格插入数据,行数不够添加新行
* 说明:当表格中出现一行中每一个单元格都为'#'时,认为需要循环插入
* @param tableList 插入数据集合
*/
private static void insertTable(XWPFTable table, List<String[]> tableList,boolean isMergeRow,List<List<Integer>> mergeRowLists) {
int headRowNum = 0;
int tailRowNum = 0;
List<XWPFTableRow> rows = table.getRows();
List<Integer> cellOrder = new ArrayList<>();
for(int i = 0; i < rows.size(); i++){
String flagHead = "";
String flagFor = "";
for(int j = 0; j < rows.get(i).getTableCells().size(); j++){
String cellText = rows.get(i).getTableCells().get(j).getText().replace(" ","");
if(cellText.length() > 0){
if(cellText.contains("#")){
flagHead = flagHead + "#";
}
if(cellText.contains("#[") && cellText.contains("]") && cellText.indexOf("]") > cellText.indexOf("[")+1
&& cellOrder.size() < rows.get(i).getTableCells().size()){
cellOrder.add(Integer.valueOf(cellText.substring(cellText.indexOf("[")+1,cellText.indexOf("]"))));
}else if(cellText.contains("#") && cellOrder.size() < rows.get(i).getTableCells().size()){
cellOrder.add(null);
}
}
//删除循环单元格内多余段落,不想单元格内有默认数据放开注释
// List<XWPFParagraph> paragraphs = rows.get(i).getTableCells().get(j).getParagraphs();
// if(paragraphs.size() > 1){
// for(int k = paragraphs.size()-1; k >= 0; k--){
// if(!paragraphs.get(k).getText().contains("#")){
// rows.get(i).getTableCells().get(j).removeParagraph(k);
// }
// }
// }
//删除循环单元格内要替换段落后的多余run
if(rows.get(i).getTableCells().get(j).getParagraphs().size() > 0){
for(XWPFParagraph paragraph : rows.get(i).getTableCells().get(j).getParagraphs()){
if(paragraph.getText().indexOf("#") == 0){
for(int k = paragraph.getRuns().size()-1; k > 0; k--){
paragraph.removeRun(k);
}
}
}
}
flagFor = flagFor + "#";
}
if(flagFor.equals(flagHead)){
headRowNum = i;
break;
}
}
if(headRowNum > 0){
tailRowNum = rows.size()- headRowNum - 1;
//创建行,根据需要插入的数据添加新行,不处理表头
for (int i = 0; i < tableList.size(); i++) {
copy(table,table.getRow(headRowNum),headRowNum+1+i);
}
//遍历表格插入数据
int length = table.getRows().size();
for (int i = headRowNum; i < length - tailRowNum - 1; i++) {
XWPFTableRow newRow = table.getRow(i);
List<XWPFTableCell> cells = newRow.getTableCells();
for (int j = 0; j < cells.size(); j++) {
XWPFTableCell cell = cells.get(j);
String s ="";
if(j < tableList.get(i - headRowNum).length){
if(cellOrder.get(j) != null && !cellOrder.get(j).equals(-1)){
s = tableList.get(i - headRowNum)[cellOrder.get(j)];
}else if(cellOrder.get(j) != null &&cellOrder.get(j).equals(-1)){
s = "";
}else {
s = tableList.get(i - headRowNum)[j];
}
}else if(cellOrder.get(j) != null && !cellOrder.get(j).equals(-1)){
s = tableList.get(i - headRowNum)[cellOrder.get(j)];
}
for(XWPFParagraph paragraph : cell.getParagraphs()){
if(paragraph.getText().contains("#")){
paragraph.getRuns().get(0).setText(s,0);
}
}
}
}
table.removeRow(table.getRows().size()-1-tailRowNum);
if(isMergeRow && mergeRowLists.size() > 0){
for(List<Integer> listInts : mergeRowLists){
mergeCellsRow(table,listInts.get(0),listInts.get(1),listInts.get(2));
}
}
// mergeCellsCol(table,1,2,3);
}
}
/**
* 替换表格里面的变量
* @param doc 要替换的文档
* @param params 参数
*/
private static void replaceInTable(CustomXWPFDocument doc, Map<String, Object> params, List<String[]> tableList,boolean isMergeRow,List<List<Integer>> mergeRowLists) {
Iterator<XWPFTable> iterator = doc.getTablesIterator();
XWPFTable table;
List<XWPFTableRow> rows;
List<XWPFTableCell> cells;
List<XWPFParagraph> paras;
while (iterator.hasNext()) {
table = iterator.next();
if (table.getRows().size() > 1) {
insertTable(table,tableList,isMergeRow,mergeRowLists);
//判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入
// if (matcher(table.getText()).find()) {
rows = table.getRows();
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paras = cell.getParagraphs();
for (XWPFParagraph para : paras) {
replaceInPara(para, params, doc);
}
}
}
}
}
}
/**
* <b> 再次替换图片
* </b><br><br><i>Description</i> : 因为有的地方替换图片不确定,先替换成其他占位符,在替换掉
* @param para 要替换的段落
* @param params 参数
* @param doc 文档
* @return void
* <br><br>Date: 2019/12/9 15:54 <br>Author : dxl
*/
private static void replaceImgAgain(XWPFParagraph para, Map<String, Object> params, CustomXWPFDocument doc) {
List<XWPFRun> runs;
if (matcherStar(para.getParagraphText()).find()) {
runs = para.getRuns();
int start = -1;
int end = -1;
String str = "";
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
if ((runText.length() > 0 && runText.contains("*{"))
|| (runText.length() > 0 && '*' == runText.charAt(runText.length() - 1) && i+1 <runs.size() && '$' == runs.get(i+1).toString().charAt(0))) {
start = i;
}
if (runText.length() > 0 && runText.contains("}")) {
if (start != -1) {
end = i;
break;
}
}
}
for(int i = start; i <= end; i++){
str = str + runs.get(i).toString();
}
//去掉标识符开始之后到结束的run,保留第一个run是为了使用run的样式
for (int i = start+1; i <= end; i++) {
para.removeRun(i);
i--;
end--;
}
for (Map.Entry<String, Object> entry : params.entrySet()) {
String key = entry.getKey();
if (str.indexOf(key) != -1) {
Object value = entry.getValue();
if (value instanceof String) {
str = str.replace(key, value.toString());
para.getRuns().get(start).setText(str,0);//替换保留的第一个run中的内容,若没有0就变为插入了
break;
} else if (value instanceof Map) {
str = str.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);
try {
//int ind = doc.addPicture(byteInputStream,picType);
//doc.createPicture(ind, width , height,para);
doc.addPictureData(byteInputStream, picType);
if(start == 0){
para.getRuns().get(0).setText("",0);
doc.createPicture(doc.getAllPictures().size() - 1, width, height, para,start);
}else {
para.removeRun(start);
doc.createPicture(doc.getAllPictures().size() - 1, width, height, para,start-1);
}
break;
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
if (matcher(para.getParagraphText()).find()) {
replaceInPara(para, params, doc);
}
}
/**
* 正则匹配字符串
*
* @param str
* @return
*/
private static Matcher matcher(String str) {
Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher;
}
/**
* 正则匹配字符串
*
* @param str
* @return
*/
private static Matcher matcherStar(String str) {
Pattern pattern = Pattern.compile("\\*\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher;
}
/**
* 根据图片类型,取得对应的图片类型代码
*
* @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;
}
/**
* 将输入流中的数据写入字节数组
*
* @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) {
e2.getStackTrace();
}
}
}
return byteArray;
}
/**
* 关闭输入流
*
* @param is
*/
private static void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 关闭输出流
*
* @param os
*/
private static void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* <b> 复制表格
* </b><br><br><i>Description</i> :
* @param table, sourceRow, rowIndex
* @return void
* <br><br>Date: 2019/12/9 13:23 <br>Author : dxl
*/
public static void copy(XWPFTable table,XWPFTableRow sourceRow,int rowIndex){
//在表格指定位置新增一行
XWPFTableRow targetRow = table.insertNewTableRow(rowIndex);
//复制行属性
targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr());
List<XWPFTableCell> cellList = sourceRow.getTableCells();
if (null == cellList) {
return;
}
//复制列及其属性和内容
XWPFTableCell targetCell = null;
for (XWPFTableCell sourceCell : cellList) {
targetCell = targetRow.addNewTableCell();
//处理一个单元格内有多个段落
List<XWPFParagraph> paragraphs = sourceCell.getParagraphs();
if(paragraphs.size() > 1){
for(int i = 1; i < paragraphs.size(); i++){
targetCell.addParagraph();
}
}
//列属性
targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
//段落属性
if(sourceCell.getParagraphs()!=null&&sourceCell.getParagraphs().size()>0){
for(int i = 0; i < sourceCell.getParagraphs().size();i++){
targetCell.getParagraphs().get(i).getCTP().setPPr(sourceCell.getParagraphs().get(i).getCTP().getPPr());
if(sourceCell.getParagraphs().get(i).getRuns()!=null&&sourceCell.getParagraphs().get(i).getRuns().size()>0){
for(int j = 0; j < sourceCell.getParagraphs().get(i).getRuns().size(); j++){
XWPFRun cellR = targetCell.getParagraphs().get(i).createRun();
cellR.setText(sourceCell.getParagraphs().get(i).getRuns().get(j).getText(0));
cellR.setBold(sourceCell.getParagraphs().get(i).getRuns().get(j).isBold());
cellR.setColor(sourceCell.getParagraphs().get(i).getRuns().get(j).getColor());
if(sourceCell.getParagraphs().get(i).getRuns().get(j).getFontSize() == -1){
cellR.setFontSize(10);
}else {
cellR.setFontSize(sourceCell.getParagraphs().get(i).getRuns().get(j).getFontSize());
}
cellR.setCapitalized(sourceCell.getParagraphs().get(i).getRuns().get(j).isCapitalized());
cellR.setDoubleStrikethrough(sourceCell.getParagraphs().get(i).getRuns().get(j).isDoubleStrikeThrough());
cellR.setEmbossed(sourceCell.getParagraphs().get(i).getRuns().get(j).isEmbossed());
cellR.setFontFamily(sourceCell.getParagraphs().get(i).getRuns().get(j).getFontFamily());
cellR.setImprinted(sourceCell.getParagraphs().get(i).getRuns().get(j).isImprinted());
cellR.setItalic(sourceCell.getParagraphs().get(i).getRuns().get(j).isItalic());
cellR.setKerning(sourceCell.getParagraphs().get(i).getRuns().get(j).getKerning());
cellR.setShadow(sourceCell.getParagraphs().get(i).getRuns().get(j).isShadowed());
cellR.setStrikeThrough(sourceCell.getParagraphs().get(i).getRuns().get(j).isStrikeThrough());
cellR.setSmallCaps(sourceCell.getParagraphs().get(i).getRuns().get(j).isSmallCaps());
cellR.setSubscript(sourceCell.getParagraphs().get(i).getRuns().get(j).getSubscript());
cellR.setTextPosition(sourceCell.getParagraphs().get(i).getRuns().get(j).getTextPosition());
cellR.setUnderline(sourceCell.getParagraphs().get(i).getRuns().get(j).getUnderline());
}
}else{
targetCell.setText(sourceCell.getText());
}
}
}else{
targetCell.setText(sourceCell.getText());
}
}
}
/**
* <b> 在段落中插入表格
* </b><br><br><i>Description</i> : 表格单元格中建段落再插入表格,原段落会挤到下一个段落,用isDelNullPara控制删除空原段落,
* isDelNullPara为true时要注意循环迭代,最好倒序循环para,插入表格后还有对para操作时也要注意,可能isDelNullPara要设为false
* @param sourceTable 要插入的源表格
* @param targetDoc 要插入的文档
* @param para 要插入表格的段落
* @param isDelNullPara 是否删除para为空是多出来的空段落
* @return void
* <br><br>Date: 2019/12/12 11:39 <br>Author : dxl
*/
public static void insertTableInPara(XWPFTable sourceTable,CustomXWPFDocument targetDoc,XWPFParagraph para,boolean isDelNullPara){
XmlCursor cursor = para.getCTP().newCursor();
XWPFTable tableOne = targetDoc.insertNewTbl(cursor);
for(int i = 0; i < sourceTable.getRows().size(); i++){
copy(tableOne,sourceTable.getRow(i),i+1);
}
if(isDelNullPara){
if(para.getText() != null && para.getText().length() > 0){
}else {
targetDoc.removeBodyElement(targetDoc.getPosOfParagraph(para));
}
}
tableOne.removeRow(0);
}
/**
* <b> 在段落中插入表格--源表格来源于其他Word
* </b><br><br><i>Description</i> : 表格单元格中建段落再插入表格,原段落会挤到下一个段落,用isDelNullPara控制删除空原段落,
* isDelNullPara为true时要注意循环迭代,最好倒序循环para,插入表格后还有对para操作时也要注意,可能isDelNullPara要设为false
* @param srcPath 源表格所在源Word的路径
* @param tableIndex 源表格所在源Word中是第几个,即下标
* @param targetDoc 要插入的文档
* @param para 要插入表格的段落
* @param isDelNullPara 是否删除para为空是多出来的空段落
* @return void
* <br><br>Date: 2019/12/12 11:39 <br>Author : dxl
*/
public static void insertTableInParaFromAtherDoc(String srcPath,int tableIndex,CustomXWPFDocument targetDoc,XWPFParagraph para,boolean isDelNullPara) throws IOException {
XmlCursor cursor = para.getCTP().newCursor();
File file = new File(srcPath);
InputStream is = new FileInputStream(file);
CustomXWPFDocument srcDoc = new CustomXWPFDocument(is);
XWPFTable sourceTable = srcDoc.getTableArray(tableIndex);
XWPFTable tableOne = targetDoc.insertNewTbl(cursor);
for(int i = 0; i < sourceTable.getRows().size(); i++){
copy(tableOne,sourceTable.getRow(i),i+1);
tableOne.removeRow(0);
}
if(isDelNullPara){
if(para.getText() != null && para.getText().length() > 0){
}else {
targetDoc.removeBodyElement(targetDoc.getPosOfParagraph(para));
}
}
close(is);
}
/**
* @Description: 跨列合并
*/
public static void mergeCellsCol(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);
}
}
}
/**
* @Description: 跨行合并
*/
public static void mergeCellsRow(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);
}
}
}
}
五、最后生成的word文档
六、Word中公式解析(好似得具体公式具体分析)
6.1需要在上面依赖基础上添加依赖
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.4</version>
</dependency>
6.2以最简单的公式为例:
在WordGrtUtil中的代码测试的
/**
* 替换段落里面的变量
* @param doc 要替换的文档
* @param params 参数
*/
private static void replaceInPara(CustomXWPFDocument doc, Map<String, Object> params) {
Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
System.out.println(".........000.......: "+para.getCTP().getOMathList());
if(para.getCTP().getOMathList().size() > 0){
System.out.println("..........111......: "+para.getCTP().getOMathList().get(0).getSSubSupList().get(0).getE().getRList().get(0).getT2List().get(0).getStringValue());
System.out.println("........222........: "+para.getCTP().getOMathList().get(0).getSSubSupList().get(0).getSub().getRList().get(0).getT2List().get(0).getStringValue());
System.out.println("........333........: "+para.getCTP().getOMathList().get(0).getSSubSupList().get(0).getSup().getRList().get(0).getT2List().get(0).getStringValue());
para.getCTP().getOMathList().get(0).getSSubSupList().get(0).getSup().getRList().get(0).getT2List().get(0).setStringValue("www");
}
replaceInPara(para, params, doc);
}
}
6.3打印为:
.........000.......: []
.........000.......: [<m:sSubSup xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
<m:sSubSupPr>
<m:ctrlPr>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
</m:ctrlPr>
</m:sSubSupPr>
<m:e>
<m:r>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
<m:t>a</m:t>
</m:r>
</m:e>
<m:sub>
<m:r>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
<m:t>n</m:t>
</m:r>
</m:sub>
<m:sup>
<m:r>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
<m:t>m</m:t>
</m:r>
</m:sup>
</m:sSubSup>, <m:sSubSup xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape">
<m:sSubSupPr>
<m:ctrlPr>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
</m:ctrlPr>
</m:sSubSupPr>
<m:e>
<m:r>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
<m:t>b</m:t>
</m:r>
</m:e>
<m:sub>
<m:r>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
<m:t>y</m:t>
</m:r>
</m:sub>
<m:sup>
<m:r>
<w:rPr>
<w:rFonts w:ascii="Cambria Math" w:hAnsi="Cambria Math"/>
</w:rPr>
<m:t>x</m:t>
</m:r>
</m:sup>
</m:sSubSup>]
..........111......: a
........222........: n
........333........: m
.........000.......: []
6.4分析:
- 第二个000行打印为有公式时的集合(两个),第一和第三000为空 [ ];
- 公式是以<m:sSubSup 开头的,所以 para.getCTP().getOMathList() 之后要拿到 SSubSup 集合,对应为如 para.getCTP().getOMathList().get(0).getSSubSupList() ;
- 可以看到公式中的 “a” 在<m:sSubSup 标签下三层标签<m:e> <m:r> <m:t> 中,获得每一层都有对应的方法,如getE().getRList().get(0).getT2List() ,其中有的方法返回是集合有的不是;
- 拿到<m:t> 后就可以拿到具体的公式中的值了(a),如getE().getRList().get(0).getT2List().get(0).getStringValue() ;
- 111输出打印的就是..........111......: a
- 同理 上标 “m” 在<m:sup> <m:r> <m:t> 标签中,getSup().getRList().get(0).getT2List().get(0).getStringValue() 拿到 “ m”值;
- 同理拿到 “n”的值;
- 注意:每个标签都有对应的获取方法,通常应为标签中冒号后字符的对应如<m:sup> 对应 getSup(), <m:r> 对应getRList();
- 改变值时使用getStringValue() 对应的 setStringValue() 即可,如:para.getCTP().getOMathList().get(0).getSSubSupList().get(0).getSup().getRList().get(0).getT2List().get(0).setStringValue("www");
- 新建公式是,应该是按照这个标签层层新增,方法以 add 开头,每个标签都有对应的方法,对应关系应该同 8;
6.5修改结果
七、段落(单元格)插入表格
7.1原word
7.2另外word制定表格
7.3插入表格
在方法replaceInPara中遍历段落时使用insertTableInParaFromAtherDoc方法插入7.2中的表格;具体解释看方法注释
结果如下: