項目開發過程中,客戶提出一堆導出報表的需求,需要導出word格式,頁眉還需要加上客戶公司的logo,試了幾種方案,最后選擇了用 Apache poi 加上自定義標簽的方式實現。
目前功能還比較簡單,一些復雜的表格做不了,但是已經基本滿足項目需求了。
使用poi讀取word模板,替換word中的{text}標簽,並根據自定義標簽循環生成表格或表格中的行。
代碼示例下載:https://download.csdn.net/download/u012775558/10306308
注意,僅支持docx格式的word文件,大概是word2010及以后版本,doc格式不支持。
word模板需要有固定的格式,下面是幾個示例與代碼實現.
基礎文本替換示例
只是最基礎的文本替換
模板如下:
生成報表如下:
表格內部循環生成行
注意:
- 表格第一行通過合並單元格的方式,設置為只有兩個單元格,第一個單元格填寫foreachTableRow標簽,第二個單元格填寫要替換的數據List名稱,本例中是table1或table2,注意名稱要和你后台wordDataMap中存入的key值相同。
- 表格第二行是表頭。
- 表格第三行需要通過合並單元格的方式,設置為只有一個單元格,填寫上foreachRows標簽,代表從這一行以下開始循環替換。
- 表格第四行是要替換的數據,在map中的key值。
模板如下:
生成報表如下:
可以給表格加上表頭和表尾數據,只需要把數據放入parametersMap(存儲報表中不循環的數據)中即可。
表格內部行添加序號示例
你也可以給行加上序號,但是不能直接輸入序號,而是通過word的插入編號的功能插入編號,生成的表格才會有編號。
模板如下:
生成報表如下:
也可以給表格加上表頭和表尾數據,只需要把數據放入parametersMap(存儲報表中不循環的數據)中即可。
循環生成表格示例
注意:
- 表格第一行通過合並單元格的方式,設置為只有兩個單元格,第一個單元格填寫foreachTable標簽,第二個單元格填寫要替換的數據List名稱,本例中是table1。
- 表格其他部分只需要將要替換的數據用標簽替換即可。
模板如下:
生成報表如下
使用方法如下
使用maven搭建項目,引入poi相關jar包。
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.13</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.13</version>
</dependency>
代碼如下
- 工具類 WordTemplate
/**
* @Title: WordTemplate2.java
* @Package: com.highdata.templateTools
* @Description: TODO
* @author: Juveniless
* @date: 2017年11月27日 下午3:23:13
*/
package com.hidata.tool;
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.BodyElementType;
import org.apache.poi.xwpf.usermodel.IBodyElement;
import org.apache.poi.xwpf.usermodel.PositionInParagraph;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
/**
*
* 對docx文件中的文本及表格中的內容進行替換 --模板僅支持對 {key} 標簽的替換
*
* @ClassName: WordTemplate
* @Description: TODO(!!!使用word2013 docx文件)
* @author Juveniless
* @date: 2017年11月27日 下午3:25:56
* <br>(1)word模板注意頁邊距的問題,存在問題:比如頁邊距默認為3cm,畫表格時,仍然可以通過
* 拖拽,把表格邊框拖動到看起來就像頁邊距只有1cm的樣子,但是實際上此時頁邊距還是3cm,生成的
* word報表的頁邊距還是會按照3cm來生成。解決辦法,在word文件里,設置好頁邊距,如果需要表格
* 兩邊頁邊距很窄,需要在word里設置頁邊距窄一點,而不是直接拖動表格邊框來實現。
*
*/
public class WordTemplate {
private XWPFDocument document;
public XWPFDocument getDocument() {
return document;
}
public void setDocument(XWPFDocument document) {
this.document = document;
}
/**
* 初始化模板內容
*
* @author Juveniless
* @date 2017年11月27日 下午3:59:22
* @param inputStream
* 模板的讀取流(docx文件)
* @throws IOException
*
*/
public WordTemplate(InputStream inputStream) throws IOException {
document = new XWPFDocument(inputStream);
}
/**
* 將處理后的內容寫入到輸出流中
*
* @param outputStream
* @throws IOException
*/
public void write(OutputStream outputStream) throws IOException {
document.write(outputStream);
}
/**
* 根據dataMap對word文件中的標簽進行替換; <br><br>
* !!!!***需要注意dataMap的數據格式***!!!! <br><br>
* 對於需要替換的普通標簽數據標簽(不需要循環)-----必須在dataMap中存儲一個key為parametersMap的map,
* 來存儲這些不需要循環生成的數據,比如:表頭信息,日期,制表人等。 <br><br>
* 對於需要循環生成的表格數據------key自定義,value為 --ArrayList<Map<String, String>>
* @author Juveniless
* @date 2017年11月27日 下午3:29:27
* @param dataMap
*
*/
public void replaceDocument(Map<String, Object> dataMap) {
if (!dataMap.containsKey("parametersMap")) {
System.out.println("數據源錯誤--數據源(parametersMap)缺失");
return;
}
@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) {
System.out
.println("文檔中第"
+ (curT + 1)
+ "個表格模板錯誤,模板表格第一行需要設置2個單元格,"
+ "第一個單元格存儲表格類型(##{foreachTable}## 或者 ##{foreachTableRow}##),第二個單元格定義數據源。");
return;
}
String tableType = tableCells.get(0).getText();
String dataSource = tableCells.get(1).getText();
System.out.println("讀取到數據源:"+dataSource);
if (!dataMap.containsKey(dataSource)) {
System.out.println("文檔中第" + (curT + 1) + "個表格模板數據源缺失");
return;
}
@SuppressWarnings("unchecked")
List<Map<String, Object>> tableDataList = (List<Map<String, Object>>) dataMap
.get(dataSource);
if ("##{foreachTable}##".equals(tableType)) {
// System.out.println("循環生成表格");
addTableInDocFooter(table, tableDataList, parametersMap, 1);
} else if ("##{foreachTableRow}##".equals(tableType)) {
// System.out.println("循環生成表格內部的行");
addTableInDocFooter(table, tableDataList, parametersMap, 2);
}
} else if (tableText.indexOf("{") > -1) {
// 沒有查找到##{foreach標簽,查找到了普通替換數據的{}標簽,該表格只需要簡單替換
addTableInDocFooter(table, null, parametersMap, 3);
} else {
// 沒有查找到任何標簽,該表格是一個靜態表格,僅需要復制一個即可。
addTableInDocFooter(table, null, null, 0);
}
curT++;
}
} else if (BodyElementType.PARAGRAPH.equals(body.getElementType())) {// 處理段落
// System.out.println("獲取到段落");
XWPFParagraph ph = body.getBody().getParagraphArray(curP);
if (ph != null) {
// htmlText = htmlText+readParagraphX(ph);
addParagraphInDocFooter(ph, null, parametersMap, 0);
curP++;
}
}
}
// 處理完畢模板,刪除文本中的模板內容
for (int a = 0; a < templateBodySize; a++) {
document.removeBodyElement(0);
}
}
/**
* 根據 模板表格 和 數據list 在word文檔末尾生成表格
* @author Juveniless
* @date 2017年12月6日 上午10:12:05
* @param templateTable 模板表格
* @param list 循環數據集
* @param parametersMap 不循環數據集
* @param flag (0為靜態表格,1為表格整體循環,2為表格內部行循環,3為表格不循環僅簡單替換標簽即可)
*
*/
public void addTableInDocFooter(XWPFTable templateTable, List<Map<String, Object>> list,
Map<String, Object> parametersMap, int flag) {
if (flag == 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();// 添加回車換行
replaceTable(newCreateTable, map);//替換標簽
}
} else if (flag == 2) {// 表格表格內部行循環
XWPFTable newCreateTable = document.createTable();// 創建新表格,默認一行一列
List<XWPFTableRow> TempTableRows = templateTable.getRows();// 獲取模板表格所有行
int tagRowsIndex = 0;// 標簽行indexs
for (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();// 添加回車換行
}
}
/**
* 根據 模板段落 和 數據 在文檔末尾生成段落
*
* @author Juveniless
* @date 2017年11月27日 上午11:49:42
* @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替換段落元素內的{**}標簽
* @author Juveniless
* @date 2017年12月4日 下午3:09:00
* @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));
insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
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 textString=beginRunText.substring(0, beginIndex) + getValueBykey(key.toString(),parametersMap)
+ beginRunText.substring(endIndex + 1);
insertNewRun.setText(textString);
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
//處理中間的run
for (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());
// 設置文本
insertNewRun.setText(getValueBykey(key.toString(),parametersMap));
xWPFParagraph.removeRun(beginRunIndex + 1);//移除原始的run
}else {
// 該run標簽為**{**或者 {** ,替換key后,還需要加上原始key前的文本
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(beginRunIndex);
insertNewRun.getCTR().setRPr(beginRun.getCTR().getRPr());
// 設置文本
String textString=beginRunText.substring(0,beginRunText.indexOf("{"))+getValueBykey(key.toString(),parametersMap);
insertNewRun.setText(textString);
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));//原始run
XWPFRun insertNewRun = xWPFParagraph.insertNewRun(removeRunList.get(i));
insertNewRun.getCTR().setRPr(xWPFRun.getCTR().getRPr());
insertNewRun.setText("");
xWPFParagraph.removeRun(removeRunList.get(i) + 1);//移除原始的run
}
}// 處理${**}被分成多個run
replaceParagraph( 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格式
*
* @author Juveniless
* @date 2017年11月27日 下午3:41:02
* @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格式
*
* @author Juveniless
* @date 2017年11月27日 下午3:43:08
* @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
* @author Juveniless
* @date 2017年11月27日 下午3:47:17
* @param newRun
* 新創建的的文本節點
* @param templateRun
* 模板文本節點
*
*/
private void CopyRun(XWPFRun newRun, XWPFRun templateRun) {
newRun.getCTR().setRPr(templateRun.getCTR().getRPr());
// 設置文本
newRun.setText(templateRun.text());
}
/**
* 根據參數parametersMap對表格的一行進行標簽的替換
*
* @author Juveniless
* @date 2017年11月23日 下午2:09:24
* @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}標簽
* @author Juveniless
* @date 2017年12月4日 下午2:47:36
* @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);
}
}
}
}
private String getValueBykey(String key, Map<String, Object> map) {
String returnValue="";
if (key != null) {
try {
returnValue=map.get(key)!=null ? map.get(key).toString() : "";
} catch (Exception e) {
// TODO: handle exception
System.out.println("key:"+key+"***"+e);
returnValue="";
}
}
return returnValue;
}
}
- **使用 **
package com.hidata.tool;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Test {
public static void main(String[] args) throws IOException {
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>>();
Map<String, Object> map1=new HashMap<>();
map1.put("name", "張三");
map1.put("age", "23");
map1.put("email", "12121@qq.com");
Map<String, Object> map2=new HashMap<>();
map2.put("name", "李四");
map2.put("age", "45");
map2.put("email", "45445@qq.com");
Map<String, Object> map3=new HashMap<>();
map3.put("name", "Tom");
map3.put("age", "34");
map3.put("email", "6767@qq.com");
table1.add(map1);
table1.add(map2);
table1.add(map3);
List<Map<String, Object>> table2 = new ArrayList<Map<String, Object>>();
Map<String, Object> map4=new HashMap<>();
map4.put("name", "tom");
map4.put("number", "sd1234");
map4.put("address", "上海");
Map<String, Object> map5=new HashMap<>();
map5.put("name", "seven");
map5.put("number", "sd15678");
map5.put("address", "北京");
Map<String, Object> map6=new HashMap<>();
map6.put("name", "lisa");
map6.put("number", "sd9078");
map6.put("address", "廣州");
table2.add(map4);
table2.add(map5);
table2.add(map6);
parametersMap.put("userName", "JUVENILESS");
parametersMap.put("time", "2018-03-24");
parametersMap.put("sum", "3");
wordDataMap.put("table1", table1);
wordDataMap.put("table2", table2);
wordDataMap.put("parametersMap", parametersMap);
File file = new File("D:\\Workspaces\\Eclipse 2017\\wordTemplate\\doc\\模板.docx");//改成你本地文件所在目錄
// 讀取word模板
FileInputStream fileInputStream = new FileInputStream(file);
WordTemplate template = new WordTemplate(fileInputStream);
// 替換數據
template.replaceDocument(wordDataMap);
//生成文件
File outputFile=new File("D:\\Workspaces\\Eclipse 2017\\wordTemplate\\doc\\輸出.docx");//改成你本地文件所在目錄
FileOutputStream fos = new FileOutputStream(outputFile);
template.getDocument().write(fos);
}
}