maven依赖
<!-- poi-tl -->
<!-- http://deepoove.com/poi-tl/ -->
<dependency>
<groupId>com.deepoove</groupId>
<artifactId>poi-tl</artifactId>
<version>1.7.1</version>
</dependency>
package com.ruoyi.common.utils.poi;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.data.*;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.data.style.TableStyle;
import com.ruoyi.common.utils.poi.custom.CustomListRenderPolicyWP;
import com.ruoyi.common.utils.poi.custom.CustomTableRenderPolicyWP;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* description: PoiTlUtils <br>
* date: 2020/2/10 14:26 <br>
* author: <br>
* version: 1.0 <br>
*/
public class PoiTlUtils {
public static void main(String[] args){
Map<String,Object> map = new HashMap<>();
ArrayList<String[]> strings = new ArrayList<>();
String[] heard = new String[]{"t1","t2"};
String[] row1 = new String[]{"r1","r2"};
String[] row2 = new String[]{"s1","s2"};
strings.add(row1);
strings.add(row2);
MiniTableRenderData miniTableRenderData = list2Table(heard, strings);
map.put("test",miniTableRenderData);
try {
CustomTableRenderPolicy customTableRenderPolicy = new CustomTableRenderPolicy();
ITableToolsMCImpl tableToolsMC = new ITableToolsMCImpl();
customTableRenderPolicy.setMergeCells(true);
customTableRenderPolicy.setiTableToolsMC(tableToolsMC);
createDocByTemplateName("test.docx","D:\\ruoyi\\resultPath\\test.docx",map,customTableRenderPolicy);
} catch (Exception e) {
e.printStackTrace();
}
}
/** 功能描述: 根据指定的模板和数据生成docx文件到指定的路径
* @param templateName
* @param docPath
* @param data
* @return: void
* @Author:
* @Date: 2020/2/20 14:31
*/
public static void createDocByTemplateName(String templateName,
String docPath,
Object data) throws Exception{
String docTemplatePath = PoiTlUtils.class.getClassLoader()
.getResource("docTemplates/" + templateName).getPath(); // 模板文件的路径
createDocByTemplate(docTemplatePath,docPath,data,null);
}
public static void createDocByTemplateName(String templateName,String docPath,
Object data,CustomTableRenderPolicy customTableRenderPolicy) throws Exception{
String docTemplatePath = PoiTlUtils.class.getClassLoader()
.getResource("docTemplates/" + templateName).getPath(); // 模板文件的路径
createDocByTemplate(docTemplatePath,docPath,data,customTableRenderPolicy);
}
public static void createDocByTemplate(String docTemplatePath,
String docPath,
Object data,CustomTableRenderPolicy customTableRenderPolicy) throws Exception{
if(customTableRenderPolicy == null){
customTableRenderPolicy = new CustomTableRenderPolicy();
customTableRenderPolicy.setMergeCells(false);
}
// 自定义表格控件覆盖原有控件
Configure config = Configure.newBuilder()
.addPlugin('#', customTableRenderPolicy)
.addPlugin('+', new CustomTableRenderPolicyWP()) // zidingyibaioghhe
.addPlugin('>', new CustomListRenderPolicyWP()) // 自定义列表
.build();
// 生成报告doc文件
XWPFTemplate template = XWPFTemplate
.compile(docTemplatePath,config)
.render(data);
FileOutputStream out = new FileOutputStream(docPath);
template.write(out);
out.flush();
out.close();
template.close();
}
public static MiniTableRenderData list2Table(
String[] headerArr,
List<String[]> datas){
// 通用样式
TableStyle tableStyle = new TableStyle();
tableStyle.setAlign(STJc.Enum.forInt(2));
RowRenderData header = null;
if(headerArr != null){
List<TextRenderData> headerDatas = new ArrayList();
for (String headerText: headerArr){
headerDatas.add(new TextRenderData(headerText));
}
header = new RowRenderData(headerDatas,"eeeeee"); // 表头
}
List<RowRenderData> rows = new ArrayList<>();
for (String[] dataRow: datas){
List<TextRenderData> rowData = new ArrayList();
for (String cellData: dataRow){
rowData.add(new TextRenderData( cellData)); // 每行
}
RowRenderData row = new RowRenderData(rowData,null); // 行数据
rows.add(row);
}
MiniTableRenderData tableRenderData = new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_MEDIUM_FULL);
return tableRenderData;
}
public static MiniTableRenderData list2Table4Pcr2(
String[] headerArr,
List<String[]> datas){
// 通用样式
TableStyle tableStyle = new TableStyle();
tableStyle.setAlign(STJc.Enum.forInt(2));
RowRenderData header = null;
if(headerArr != null){
List<TextRenderData> headerDatas = new ArrayList();
for (String headerText: headerArr){
headerDatas.add(new TextRenderData(headerText));
}
header = new RowRenderData(headerDatas,"d3dce9"); // 表头
}
String backgroundColor = "ffffff";
List<RowRenderData> rows = new ArrayList<>();
for (int i = 0; i < datas.size(); i++) {
String[] dataRow = datas.get(i);
List<TextRenderData> rowData = new ArrayList();
for (String cellData: dataRow){
rowData.add(new TextRenderData( cellData)); // 每行
}
if (i == datas.size() - 1) backgroundColor = "d3dce9";
RowRenderData row = new RowRenderData(rowData,backgroundColor); // 行数据
rows.add(row);
}
MiniTableRenderData tableRenderData = new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_FULL);
return tableRenderData;
}
/** 功能描述: map 列表转表格
* @param headerArr
* @param cellKeyArr
* @param mapLists
* @return: com.deepoove.poi.data.MiniTableRenderData
* @Author:
* @Date: 2020/2/16 16:21
*/
public static MiniTableRenderData listMap2Table(
String[] headerArr, String[] cellKeyArr,
List<Map<String,String>>... mapLists){
List<Map<String,String>> mapList = new ArrayList<>();
for (List<Map<String,String>> list: mapLists){
mapList.addAll(list);
}
// 表头单元格样式
Style style = new Style();
style.setBold(true); // 加粗
// 表头样式
TableStyle headerStyle = new TableStyle();
headerStyle.setAlign(STJc.Enum.forInt(2)); // 文字居中
headerStyle.setBackgroundColor("eeeeee");
// 内容样式
TableStyle contentStyle = new TableStyle();
contentStyle.setAlign(STJc.Enum.forInt(2)); // 文字居中
CellRenderData cellRenderData = new CellRenderData();
List<TextRenderData> headerDatas = new ArrayList();
for (String headerText: headerArr){
TextRenderData textRenderData = new TextRenderData(headerText,style);
headerDatas.add(new TextRenderData(headerText,style));
}
RowRenderData header = new RowRenderData(headerDatas,"eeeeee"); // 表头
header.setRowStyle(headerStyle);
List<RowRenderData> rows = new ArrayList<>();
for (Map<String,String> map: mapList){
List<TextRenderData> rowData = new ArrayList();
for (String cellKey: cellKeyArr){
rowData.add(new TextRenderData(map.get(cellKey))); // 每行
}
RowRenderData row = new RowRenderData(rowData,null); // 行数据
row.setRowStyle(contentStyle);
rows.add(row);
}
MiniTableRenderData tableRenderData = new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_MEDIUM_FULL);
tableRenderData.setNoDatadesc("无");
return tableRenderData;
}
/* 功能描述: String 列表转带序号的表格
* @param headerArr 必须是偶数个 [序号 , 名字 , 序号 , 名字]
* @param strList
* @return: com.deepoove.poi.data.MiniTableRenderData
* @Author:
* @Date: 2020/2/15 17:51
*
* 例子: 序号 名字 序号 名字
* 1 张三 3 李四
* 2 王五 4 赵柳
*/
public static MiniTableRenderData listStr2TableWithNum(
String[] headerArr,
List<String> strList){
Style style = new Style();
style.setBold(true); // 加粗
// 表头
List<TextRenderData> headerDatas = new ArrayList();
for (String headerText: headerArr){
headerDatas.add(new TextRenderData(headerText,style));
}
RowRenderData header = new RowRenderData(headerDatas,"eeeeee"); // 表头
// 内容
// 算出来除去序号多少列
int leiCount = headerArr.length / 2;
if (strList.size() < leiCount){
leiCount = strList.size();
}
// 算出来应该占多少行
int hangCount = strList.size()%leiCount==0?strList.size() / leiCount:strList.size() / leiCount +1;
List<RowRenderData> rows = new ArrayList<>();
for (int hangNum = 1; hangNum <= hangCount; hangNum++) {
int num = hangNum;
List<TextRenderData> rowData = new ArrayList();
for (int lieNum = 1; lieNum <= leiCount; lieNum++) {
if (strList.size() >= num){
rowData.add(new TextRenderData(String.valueOf(num))); // 每行
rowData.add(new TextRenderData(strList.get(num - 1))); // 每行
}else {
rowData.add(new TextRenderData("")); // 每行
rowData.add(new TextRenderData("")); // 每行
}
num += hangCount;
}
RowRenderData row = new RowRenderData(rowData, null); // 行数据
rows.add(row);
}
MiniTableRenderData tableRenderData =
new MiniTableRenderData(header,rows,MiniTableRenderData.WIDTH_A4_MEDIUM_FULL); // 列宽
return tableRenderData;
}
/* 功能描述: 文本列表 转 doc列表 带字体颜色
* @param textList
* @param color "FFFFFF"
* @param fontSize 9 - 小五
* @return: com.deepoove.poi.data.NumbericRenderData
* @Author:
* @Date: 2020/2/13 20:40
*/
public static NumbericRenderData list2DocList(List<String> textList,Style style){
List<TextRenderData> list = new ArrayList<TextRenderData>();
for (String text: textList){
TextRenderData data = new TextRenderData(text);
if (style != null){
data.setStyle(style);
}
list.add(data);
}
return new NumbericRenderData(NumbericRenderData.FMT_DECIMAL,list); // NumbericRenderData.FMT_DECIMAL 数字列表
}
public static NumbericRenderData list2DocList(List<String> textList,
String color,
int fontSize){
Style style = new Style();
style.setColor(color);
style.setFontSize(fontSize);
return list2DocList(textList,style);
}
public static NumbericRenderData list2DocList(List<String> textList){
return list2DocList(textList,null);
}
public static Style createStyle(String fontFamily, int fontSize, String color){
Style style = new Style();
if (fontSize != 0) style.setFontSize(fontSize);
if (fontFamily != null) style.setFontFamily(fontFamily);
style.setColor(color);
return style;
}
}
自定义poi-tl模板插件
CustomTableRenderPolicy:
package com.ruoyi.common.utils.poi;
import com.deepoove.poi.data.CellRenderData;
import com.deepoove.poi.data.MiniTableRenderData;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/** 自定义word表格 -- 自定义poi-tl模板插件
* description: CustomTableRenderPolicy <br>
* date: 2020/2/28 13:47 <br>
* author: <br>
* version: 1.0 <br>
*/
public class CustomTableRenderPolicy extends AbstractRenderPolicy<MiniTableRenderData> {
private boolean isMergeCells;
private ITableToolsMC iTableToolsMC;
public ITableToolsMC getiTableToolsMC() {
return iTableToolsMC;
}
public void setiTableToolsMC(ITableToolsMC iTableToolsMC) {
this.iTableToolsMC = iTableToolsMC;
}
public boolean isMergeCells() {
return isMergeCells;
}
public void setMergeCells(boolean mergeCells) {
isMergeCells = mergeCells;
}
@Override
protected void afterRender(RenderContext<MiniTableRenderData> context) {
// 清空模板标签
clearPlaceholder(context, true);
}
@Override
public void doRender(RenderContext<MiniTableRenderData> context)
throws Exception {
NiceXWPFDocument doc = context.getXWPFDocument();
XWPFRun run = context.getRun();
Object data = context.getData();
MiniTableRenderData miniTableRenderData = (MiniTableRenderData) data;
// 当前位置的容器
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
List<CellRenderData> headerCellList = miniTableRenderData.getHeader().getCells();
List<RowRenderData> rowsDataList = miniTableRenderData.getRows();
// 定义行列
int colCount = headerCellList.size(),
rowCount = rowsDataList.size() == 0?rowsDataList.size() + 2:rowsDataList.size() + 1;
// 定义列宽
// String[] colWidthArr = new String[]{"1960","7670","5820","1640","1700"};
// 创建表格
// 当前位置插入表格
XWPFTable table = bodyContainer.insertNewTable(run, rowCount, colCount);
// setTableWidth(table,"18790");
// 设置表头
XWPFTableRow headerRow = table.getRow(0);
setRowHeight(headerRow,"400");
for (int colNum = 0;colNum < colCount; colNum++){
XWPFTableCell cell = headerRow.getCell(colNum);
// cell = cellCenterY(cell);
setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
if (miniTableRenderData.getHeader().getRowStyle() != null){
cell.setColor(miniTableRenderData.getHeader().getRowStyle().getBackgroundColor());
}
cell.setText(headerCellList.get(colNum).getCellText().getText());
}
// 向表格添加数据
for (int rowNum = 1;rowNum < rowCount;rowNum++){
XWPFTableRow row = table.getRow(rowNum);
if (rowsDataList.size() > 0){
List<CellRenderData> cellDataList = rowsDataList.get(rowNum -1).getCells();
for (int colNum = 0;colNum < colCount; colNum++){
XWPFTableCell cell = row.getCell(colNum);
setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
cell.setText(cellDataList.get(colNum).getCellText().getText());
if (rowsDataList.get(rowNum -1).getRowStyle() != null){
cell.setColor(rowsDataList.get(rowNum -1).getRowStyle().getBackgroundColor());
}
}
}else {
XWPFTableCell cell = row.getCell(0);
setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
cell.setText("无数据");
TableTools.mergeCellsHorizonal(table, rowNum, 0, colCount - 1); // 水平合并
}
}
// 定义表格宽度、边框和样式
TableTools.widthTable(table, MiniTableRenderData.WIDTH_A4_MEDIUM_FULL, colCount);
TableTools.borderTable(table, 4);
// TODO 调用XWPFTable API操作表格:data对象可以包含任意你想要的数据,包括图片文本等
// TODO 调用MiniTableRenderPolicy.Helper.renderRow方法快速方便的渲染一行数据
// TODO 调用TableTools类方法操作表格,比如合并单元格
// ......
// TableTools.mergeCellsHorizonal(table, 0, 0, 7); // 水平合并
// 合并第0列的第2行到第4行的单元格
// TableTools.mergeCellsVertically(table, 0, 2, 4);
if(isMergeCells){
iTableToolsMC.mergeCells(table);
}
}
private void setTableWidth(XWPFTable table, String width) {
// 定义表格宽度
CTTblPr tblPr = table.getCTTbl().getTblPr();
tblPr.getTblW().setType(STTblWidth.DXA);
tblPr.getTblW().setW(new BigInteger(width));
}
// 设置列宽和水平垂直居中
public void setCellWidthAndXYAlign(XWPFTableCell cell, STVerticalJc.Enum typeEnum, STJc.Enum vAlign, String width) {
CTTc cttc = cell.getCTTc();
CTTcPr cellPr = cttc.addNewTcPr();
cellPr.addNewVAlign().setVal(typeEnum);
cttc.getPList().get(0).addNewPPr().addNewJc().setVal(vAlign);
if(!StringUtils.isEmpty(width)){
CTTblWidth tblWidth = cellPr.isSetTcW() ? cellPr.getTcW() : cellPr.addNewTcW();
tblWidth.setType(STTblWidth.DXA);
tblWidth.setW(new BigInteger(width));
}
}
// 设置表格样式
public void setCellStyle(XWPFTableCell cell,boolean bold) {
XWPFParagraph p = cell.addParagraph();
XWPFRun headRun = p.createRun();
headRun.setBold(bold);// 是否粗体
}
private void setRowHeight(XWPFTableRow row, String height){
CTTrPr trPr = row.getCtRow().addNewTrPr();
CTHeight ht = trPr.addNewTrHeight();
ht.setVal(new BigInteger(height));
}
private List<String[]> getList (){
List<String[]> list = new ArrayList<>();
String[] arr1 = new String[]{"1.1","1.2","1.3","1.4","1.5"};
String[] arr2 = new String[]{"2.1","2.2","2.3","2.4","2.5"};
String[] arr3 = new String[]{"3.1","3.2","3.3","3.4","3.5"};
String[] arr4 = new String[]{"4.1","4.2","4.3","4.4","4.5"};
String[] arr5 = new String[]{"5.1","5.2","5.3","5.4","5.5"};
list.add(arr1);
list.add(arr2);
list.add(arr3);
list.add(arr4);
list.add(arr5);
return list;
}
}
CustomListRenderPolicyWP:
package com.ruoyi.common.utils.poi.custom;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.TextRenderData;
import com.deepoove.poi.data.style.Style;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.MiniTableRenderPolicy;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
import java.math.BigInteger;
import java.util.List;
/** 自定义word表格 -- 自定义poi-tl模板插件
* description: CustomTableRenderPolicy <br>
* date: 2020/2/28 13:47 <br>
* author: <br>
* version: 1.0 <br>
*/
public class CustomListRenderPolicyWP extends AbstractRenderPolicy<MyListDataWP> {
@Override
protected void afterRender(RenderContext<MyListDataWP> context) {
// 清空模板标签
clearPlaceholder(context, true);
}
@Override
public void doRender(RenderContext<MyListDataWP> context) throws Exception {
XWPFRun run = context.getRun();
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
XWPFParagraph paragraph = bodyContainer.insertNewParagraph(run);
MyListDataWP data = context.getData();
paragraphList(paragraph,bodyContainer,data);//
}
/** 功能描述: 在当前位置插入多个段落组成的列表
* @param paragraph
* @param bodyContainer
* @param dataWP
* @return: void
* @Author:
* @Date: 2020/3/25 14:02
*/
private void paragraphList(XWPFParagraph paragraph,
BodyContainer bodyContainer,
MyListDataWP dataWP){
List<TextRenderData> textList = dataWP.getTextList();
int firstLineIndent = dataWP.getFirstLineIndent() * 200;
paragraph.setFirstLineIndent(firstLineIndent); // 首行缩进 具体怎么换算的不清楚
XWPFRun pRun = paragraph.createRun();
// p.setAlignment(ParagraphAlignment.CENTER); // 居中
// p.setSpacingBefore(1000); // 段前
for (int i = 0; i < textList.size() - 1; i++) {
TextRenderData text = textList.get(i);
XWPFParagraph p = bodyContainer.insertNewParagraph(pRun);
paragraph.setFirstLineIndent(firstLineIndent); // 首行缩进 具体怎么换算的不清楚
XWPFRun r = p.createRun();
r.setText(text.getText());
setRunStyle(r,text.getStyle());
}
TextRenderData text = textList.get(textList.size() - 1);
pRun.setText(text.getText());
setRunStyle(pRun,text.getStyle());
}
/* 功能描述: 为 run设置style
* @param run
* @param style
* @return: void
* @Author:
* @Date: 2020/3/25 14:03
*/
private void setRunStyle(XWPFRun run,Style style){
if (style != null){
run.setColor(style.getColor());
run.setFontFamily(style.getFontFamily());
if (style.getFontSize() != 0){
run.setFontSize(style.getFontSize());
}
}
}
}
CustomTableRenderPolicyWP:
package com.ruoyi.common.utils.poi.custom;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.policy.DynamicTableRenderPolicy;
import com.deepoove.poi.policy.MiniTableRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.math.BigInteger;
import java.util.List;
/** 自定义word表格 -- 自定义poi-tl模板插件
* description: CustomTableRenderPolicy <br>
* date: 2020/2/28 13:47 <br>
* author: <br>
* version: 1.0 <br>
*/
public class CustomTableRenderPolicyWP extends DynamicTableRenderPolicy {
@Override
public void render(XWPFTable table, Object data) {
if (null == data) return;
MiniTableDataWP tableDataWP = (MiniTableDataWP) data;
int dataStartRowNum = tableDataWP.getDataStartRowNum(); // 数据从第几行开始填充
int colCount = tableDataWP.getColCount(); // 总列数
List<RowRenderData> rowDataList = tableDataWP.getRowDataList();
if (null != rowDataList && rowDataList.size() > 0) {
table.removeRow(dataStartRowNum);
// 循环插入行
for (int i = 0; i < rowDataList.size(); i++) {
XWPFTableRow insertNewTableRow = table.insertNewTableRow(dataStartRowNum);
for (int j = 0; j < colCount; j++) { // 循环初始化每列的单元格
setCellXYAlign(insertNewTableRow.createCell(),STVerticalJc.CENTER,STJc.CENTER); // 内容水平垂直剧中
}
// 合并单元格
// TableTools.mergeCellsHorizonal(table, dataStartRowNum, 0, 3);
MiniTableRenderPolicy.Helper.renderRow(table, dataStartRowNum, rowDataList.get(i));
dataStartRowNum ++;
}
// 垂直合并
// TableTools.mergeCellsVertically(table,0,4,5); // 合并 第0列 的 4~5行
if (tableDataWP.getMergeCellsVerticallyDataList() != null
&& tableDataWP.getMergeCellsVerticallyDataList().size() > 0){
for (MergeCellsVerticallydata mergeCellsVerticallydata: tableDataWP.getMergeCellsVerticallyDataList()){
TableTools.mergeCellsVertically(table,
mergeCellsVerticallydata.getCellNum(),
mergeCellsVerticallydata.getStartRowNum(),
mergeCellsVerticallydata.getEndRowNum()); // 垂直合并
}
}
}else {
table.removeRow(dataStartRowNum);
XWPFTableRow insertNewTableRow = table.insertNewTableRow(dataStartRowNum);
for (int j = 0; j < colCount; j++) { // 循环初始化每列的单元格
XWPFTableCell cell = insertNewTableRow.createCell();
cell.setText("/");
setCellXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER); // 内容水平垂直剧中
}
}
}
// 设置单元格 水平垂直居中
public void setCellXYAlign(XWPFTableCell cell, STVerticalJc.Enum typeEnum, STJc.Enum vAlign) {
CTTc cttc = cell.getCTTc();
CTTcPr cellPr = cttc.addNewTcPr();
cellPr.addNewVAlign().setVal(typeEnum);
cttc.getPList().get(0).addNewPPr().addNewJc().setVal(vAlign);
}
}
自定义样式相关:
MergeCellsVerticallydata:
package com.ruoyi.common.utils.poi.custom;
import lombok.Data;
/** 垂直合并
* description: mergeCellsVerticallydata <br>
* date: 2020/3/11 10:50 <br>
* author: <br>
* version: 1.0 <br>
*/
@Data
public class MergeCellsVerticallydata {
private int cellNum; // 第几列
private int startRowNum; // 开始行
private int endRowNum; // 结束行
public MergeCellsVerticallydata(int cellNum,int startRowNum,int endRowNum){
this.cellNum = cellNum;
this.startRowNum = startRowNum;
this.endRowNum = endRowNum;
}
}
MiniTableDataWP:
package com.ruoyi.common.utils.poi.custom;
import com.deepoove.poi.data.RowRenderData;
import lombok.Data;
import java.util.List;
/** 针对自定义poi-tl插件封装的word表格实体
* description: CustomTableWP <br>
* date: 2020/3/10 15:15 <br>
* author: <br>
* version: 1.0 <br>
*/
@Data
public class MiniTableDataWP {
private int colCount; // 总列数
private int dataStartRowNum; // 从第几行开始填充数据
List<RowRenderData> rowDataList; // 数据
List<MergeCellsVerticallydata> mergeCellsVerticallyDataList; // 需要合并行的数据
public MiniTableDataWP(int dataStartRowNum, int colCount, List<RowRenderData> rowDataList){
this.colCount = colCount;
this.dataStartRowNum = dataStartRowNum;
this.rowDataList = rowDataList;
}
}
MyListDataWP:
package com.ruoyi.common.utils.poi.custom;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.data.TextRenderData;
import lombok.Data;
import java.util.List;
/* 功能描述: 针对自定义poi-tl插件封装的word列表实体
* @param null
* @return:
* @Author:
* @Date: 2020/3/25 13:05
*/
@Data
public class MyListDataWP {
List<TextRenderData> textList;
int firstLineIndent; // 首行缩进
public MyListDataWP(List<TextRenderData> textList,int firstLineIndent){
this.textList = textList;
this.firstLineIndent = firstLineIndent;
}
}
使用例子1:
//这是要输出到word中的数据集map
Map<String,Object> templateMap = Maps.newHashMap();
templateMap.put("age","1");
//这是生成word的模版路径
String templateFileName = "pcr/PCR_REPORT_TEMPLATE_8.docx";
ArrayList<String[]> strings = new ArrayList<>();//这是word中表格行数据集
List<GeneraResultsItem> generaResultsItemList = genera.getGeneraResults().getGeneraResultsItemList();//业务代码,查询出要绑定的数据源
if(generaResultsItemList != null && !generaResultsItemList.isEmpty()){
int len = generaResultsItemList.size() -1;
for (int i = 0; i < len; i++) {
GeneraResultsItem generaResultsItem = generaResultsItemList.get(i);
GeneraResultsItem generaResultsItem1 = generaResultsItemList.get(i+1);
GeneraResultsItem generaResultsItem2 = generaResultsItemList.get(i+2);
String[] row = new String[]{generaResultsItem.getItemName()+"("+generaResultsItem.getGeneraItemResults()+")"
,generaResultsItem1.getItemName()+"("+generaResultsItem1.getGeneraItemResults()+")"
,generaResultsItem2.getItemName()+"("+generaResultsItem2.getGeneraItemResults()+")"};//这是一行数据
strings.add(row);//放到数组中
i += 2;
}
}
List<RowRenderData> rows = PoiTlUtils.list2Table(new String[]{"", "", ""}, strings).getRows();//获取所有的表格数据,第一个参数为表格表头数组
//创建自定义插件表格数据源对象
MiniTableDataWP miniTableDataWP = new MiniTableDataWP(0,3,rows);
//存放到map中
templateMap.put("tables",miniTableDataWP);
例子1模版中使用方法:
普通字段绑定:
表格部分绑定:
例子2:
templateFileName = "pcr/PCR_REPORT_TEMPLATE_6.docx";//模版路径
templateMap.put("age","1");
//表格的表头
String[] heard = new String[]{"项目","数据(CT)","结果","项目","数据(CT)","结果"};
//表的行数据源
ArrayList<String[]> strings = new ArrayList<>();
List<GeneraResultsItem> generaResultsItemList = genera.getGeneraResults().getGeneraResultsItemList();
if(generaResultsItemList != null && !generaResultsItemList.isEmpty()){
int size = generaResultsItemList.size();
int len = size /2 ;
for (int i = 0; i < len; i++) {
GeneraResultsItem generaResultsItem = generaResultsItemList.get(i);
GeneraResultsItem generaResultsItem1 = generaResultsItemList.get(i+len);
String[] row = new String[]{generaResultsItem.getItemName(),"No Ct",generaResultsItem.getGeneraItemResults()
,generaResultsItem1.getItemName(),"No Ct",generaResultsItem1.getGeneraItemResults()};
strings.add(row);
}
}
templateMap.put("tables",PoiTlUtils.list2Table(heard,strings));
20200702补充基础类:
import com.deepoove.poi.data.CellRenderData;
import com.deepoove.poi.data.MiniTableRenderData;
import com.deepoove.poi.data.RowRenderData;
import com.deepoove.poi.policy.AbstractRenderPolicy;
import com.deepoove.poi.render.RenderContext;
import com.deepoove.poi.util.TableTools;
import com.deepoove.poi.xwpf.BodyContainer;
import com.deepoove.poi.xwpf.BodyContainerFactory;
import com.deepoove.poi.xwpf.NiceXWPFDocument;
import com.ruoyi.common.utils.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
/** 自定义word表格 -- 自定义poi-tl模板插件
* description: CustomTableRenderPolicy <br>
* version: 1.0 <br>
*/
public class CustomTableRenderPolicy extends AbstractRenderPolicy<MiniTableRenderData> {
private boolean isMergeCells;
private ITableToolsMC iTableToolsMC;
public ITableToolsMC getiTableToolsMC() {
return iTableToolsMC;
}
public void setiTableToolsMC(ITableToolsMC iTableToolsMC) {
this.iTableToolsMC = iTableToolsMC;
}
public boolean isMergeCells() {
return isMergeCells;
}
public void setMergeCells(boolean mergeCells) {
isMergeCells = mergeCells;
}
@Override
protected void afterRender(RenderContext<MiniTableRenderData> context) {
// 清空模板标签
clearPlaceholder(context, true);
}
@Override
public void doRender(RenderContext<MiniTableRenderData> context)
throws Exception {
NiceXWPFDocument doc = context.getXWPFDocument();
XWPFRun run = context.getRun();
Object data = context.getData();
MiniTableRenderData miniTableRenderData = (MiniTableRenderData) data;
// 当前位置的容器
BodyContainer bodyContainer = BodyContainerFactory.getBodyContainer(run);
List<CellRenderData> headerCellList = miniTableRenderData.getHeader().getCells();
List<RowRenderData> rowsDataList = miniTableRenderData.getRows();
// 定义行列
int colCount = headerCellList.size(),
rowCount = rowsDataList.size() == 0?rowsDataList.size() + 2:rowsDataList.size() + 1;
// 定义列宽
// String[] colWidthArr = new String[]{"1960","7670","5820","1640","1700"};
// 创建表格
// 当前位置插入表格
XWPFTable table = bodyContainer.insertNewTable(run, rowCount, colCount);
// setTableWidth(table,"18790");
// 设置表头
XWPFTableRow headerRow = table.getRow(0);
setRowHeight(headerRow,"400");
for (int colNum = 0;colNum < colCount; colNum++){
XWPFTableCell cell = headerRow.getCell(colNum);
// cell = cellCenterY(cell);
setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
if (miniTableRenderData.getHeader().getRowStyle() != null){
cell.setColor(miniTableRenderData.getHeader().getRowStyle().getBackgroundColor());
}
cell.setText(headerCellList.get(colNum).getCellText().getText());
}
// 向表格添加数据
for (int rowNum = 1;rowNum < rowCount;rowNum++){
XWPFTableRow row = table.getRow(rowNum);
if (rowsDataList.size() > 0){
List<CellRenderData> cellDataList = rowsDataList.get(rowNum -1).getCells();
for (int colNum = 0;colNum < colCount; colNum++){
XWPFTableCell cell = row.getCell(colNum);
setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
cell.setText(cellDataList.get(colNum).getCellText().getText());
if (rowsDataList.get(rowNum -1).getRowStyle() != null){
cell.setColor(rowsDataList.get(rowNum -1).getRowStyle().getBackgroundColor());
}
}
}else {
XWPFTableCell cell = row.getCell(0);
setCellWidthAndXYAlign(cell,STVerticalJc.CENTER,STJc.CENTER,null);
cell.setText("无数据");
TableTools.mergeCellsHorizonal(table, rowNum, 0, colCount - 1); // 水平合并
}
}
// 定义表格宽度、边框和样式
TableTools.widthTable(table, MiniTableRenderData.WIDTH_A4_MEDIUM_FULL, colCount);
TableTools.borderTable(table, 4);
// TODO 调用XWPFTable API操作表格:data对象可以包含任意你想要的数据,包括图片文本等
// TODO 调用MiniTableRenderPolicy.Helper.renderRow方法快速方便的渲染一行数据
// TODO 调用TableTools类方法操作表格,比如合并单元格
// ......
// TableTools.mergeCellsHorizonal(table, 0, 0, 7); // 水平合并
// 合并第0列的第2行到第4行的单元格
// TableTools.mergeCellsVertically(table, 0, 2, 4);
if(isMergeCells){
iTableToolsMC.mergeCells(table);
}
}
private void setTableWidth(XWPFTable table, String width) {
// 定义表格宽度
CTTblPr tblPr = table.getCTTbl().getTblPr();
tblPr.getTblW().setType(STTblWidth.DXA);
tblPr.getTblW().setW(new BigInteger(width));
}
// 设置列宽和水平垂直居中
public void setCellWidthAndXYAlign(XWPFTableCell cell, STVerticalJc.Enum typeEnum, STJc.Enum vAlign, String width) {
CTTc cttc = cell.getCTTc();
CTTcPr cellPr = cttc.addNewTcPr();
cellPr.addNewVAlign().setVal(typeEnum);
cttc.getPList().get(0).addNewPPr().addNewJc().setVal(vAlign);
if(!StringUtils.isEmpty(width)){
CTTblWidth tblWidth = cellPr.isSetTcW() ? cellPr.getTcW() : cellPr.addNewTcW();
tblWidth.setType(STTblWidth.DXA);
tblWidth.setW(new BigInteger(width));
}
}
// 设置表格样式
public void setCellStyle(XWPFTableCell cell,boolean bold) {
XWPFParagraph p = cell.addParagraph();
XWPFRun headRun = p.createRun();
headRun.setBold(bold);// 是否粗体
}
private void setRowHeight(XWPFTableRow row, String height){
CTTrPr trPr = row.getCtRow().addNewTrPr();
CTHeight ht = trPr.addNewTrHeight();
ht.setVal(new BigInteger(height));
}
private List<String[]> getList (){
List<String[]> list = new ArrayList<>();
String[] arr1 = new String[]{"1.1","1.2","1.3","1.4","1.5"};
String[] arr2 = new String[]{"2.1","2.2","2.3","2.4","2.5"};
String[] arr3 = new String[]{"3.1","3.2","3.3","3.4","3.5"};
String[] arr4 = new String[]{"4.1","4.2","4.3","4.4","4.5"};
String[] arr5 = new String[]{"5.1","5.2","5.3","5.4","5.5"};
list.add(arr1);
list.add(arr2);
list.add(arr3);
list.add(arr4);
list.add(arr5);
return list;
}
}
public interface ITableToolsMC {
void mergeCells(XWPFTable table);
}
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.XWPFTable;
public class ITableToolsMCImpl implements ITableToolsMC {
@Override
public void mergeCells( XWPFTable table) {
// 合并第0列的第0行到第1行的单元格
TableTools.mergeCellsVertically(table, 0, 0, 1);
}
}
如有不足请留言补充