一、製作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中的表格;具體解釋看方法註釋
結果如下: