一、最终实现目标
二、实现方式
public void exportWord() throws IOException
{
ClassPathResource resource = new ClassPathResource("word/template-report-text.docx");
InputStream inputStream = resource.getInputStream();
List<BugVO> bugList = new ArrayList<>();
for (int i = 0; i < 5000; i++) {
BugVO bugVO = new BugVO();
bugVO.setSortIndex(i);
bugVO.setLine(i);
bugVO.setFilePath("E://haha//" + i);
bugVO.setMessage("你是哈哈" + i);
bugVO.setSourceCode("private String " + i);
bugVO.setBugSteps("第" + i + "步");
bugList.add(bugVO);
}
Configure config = Configure.builder().bind("bugList", new MyLoopRenderPolicy()).build();
XWPFTemplate template = XWPFTemplate.compile(inputStream, config).render(
new HashMap<String, Object>(){{
put("bugCatalogName", "haha");
put("subBugHeaderTitle", "hehe");
put("bugCount", "2222222");
put("bugDesc", "色色得瑟得瑟");
put("bugFix", "贝多芬的");
put("bugList", bugList);
}});
template.writeAndClose(new FileOutputStream("D:\\louddt\\workspace\\wisdom-city\\wisdom-city-business\\wisdom-city-business-gcgl\\src\\main\\resources\\word\\output.docx"));
}
public class BugVO
{
private int sortIndex;
private String filePath;
private String message;
private String sourceCode;
private String bugSteps;
private int line;
//get set
}
自定义表格渲染插件:MyLoopRenderPolicy
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.exception.RenderException;
import com.deepoove.poi.policy.RenderPolicy;
import com.deepoove.poi.render.compute.EnvModel;
import com.deepoove.poi.render.compute.RenderDataCompute;
import com.deepoove.poi.render.processor.DocumentProcessor;
import com.deepoove.poi.render.processor.EnvIterator;
import com.deepoove.poi.resolver.TemplateResolver;
import com.deepoove.poi.template.ElementTemplate;
import com.deepoove.poi.template.MetaTemplate;
import com.deepoove.poi.template.run.RunTemplate;
import com.deepoove.poi.util.ReflectionUtils;
import com.deepoove.poi.util.TableTools;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTRow;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.Vector;
public class MyLoopRenderPolicy implements RenderPolicy {
private static final String DEFAULT_MULTIPLE_PREFIX = "$(";
private static final String DEFAULT_MULTIPLE_SUFFIX = ")";
private static final String DEFAULT_PREFIX = "[";
private static final String DEFAULT_SUFFIX = "]";
private final String multiplePrefix;
private final String multipleSuffix;
public MyLoopRenderPolicy() {
this(DEFAULT_MULTIPLE_PREFIX, DEFAULT_MULTIPLE_SUFFIX, DEFAULT_PREFIX, DEFAULT_SUFFIX);
}
public MyLoopRenderPolicy(String multiplePrefix, String multipleSuffix, String prefix, String suffix) {
this.multiplePrefix = multiplePrefix;
this.multipleSuffix = multipleSuffix;
}
/**
* 渲染数据 将bugList中的数据通过表格渲染到word中
* @param eleTemplate template tag
* @param data render data
* @param template XWPFTemplate instance
*/
@Override
public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) {
System.out.println("start render==================================");
try {
RunTemplate runTemplate = runTemplate(eleTemplate);
XWPFRun run = runTemplate.getRun();
checkTargetIsTable(run, "Processing [" + runTemplate.getTagName()
+ "] failed, the target content is not a table");
XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody();
final XWPFTable table = tagCell.getTableRow().getTable();
if (data instanceof Iterable) {
run.setText("", 0);
TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(DEFAULT_PREFIX, DEFAULT_SUFFIX));
//读取模板所在起始行
int position = getRowIndex(tagCell.getTableRow());
List<XWPFTableRow> tempRows = getAllTemplateRow(table, position);
//保存第行内容,以便后续操作中获取光标
final XWPFTableRow firstTempRow = tempRows.get(0);
Iterator<?> dataIt = ((Iterable<?>) data).iterator();
boolean hasNextData = dataIt.hasNext();
int index = 0;
while (hasNextData) {
Object dt = dataIt.next();
hasNextData = dataIt.hasNext();
Iterator<XWPFTableRow> rowTempIt = tempRows.iterator();
boolean hasNextTempRow = rowTempIt.hasNext();
while (hasNextTempRow) {
XWPFTableRow tempRow = rowTempIt.next();
hasNextTempRow = rowTempIt.hasNext();
if (!table.addRow(tempRow, position)) {
throw new RenderException("create new table fail...");
}
//光标操作,移动光标到目标行,以便后续模板渲染
XmlCursor newCursor = firstTempRow.getCtRow().newCursor();
newCursor.toPrevSibling();
XmlObject object = newCursor.getObject();
XWPFTableRow newRow = new XWPFTableRow((CTRow) object, table);
newRow.getCtRow().set(object);
setTableRow(table, newRow, position);
List<XWPFTableCell> cells = newRow.getTableCells();
RenderDataCompute dataCompute = template.getConfig()
.getRenderDataComputeFactory()
.newCompute(EnvModel.of(dt, EnvIterator.makeEnv(index++, hasNextData || hasNextTempRow)));
cells.forEach(tableCell -> {
List<MetaTemplate> metaTemplates = resolver
.resolveBodyElements(tableCell.getBodyElements());
new DocumentProcessor(template, resolver, dataCompute)
.process(metaTemplates);
});
++position;
}
}
removeTableRow(table, position, tempRows.size());
}
} catch (Exception e) {
throw new RenderException("failed to render table multi-row template", e);
}
}
private List<XWPFTableRow> getAllTemplateRow(XWPFTable table, int startIndex) {
int tempRowNum = getMultipleRowNum();
List<XWPFTableRow> rows = table.getRows();
return new Vector<>(rows.subList(startIndex, startIndex + tempRowNum));
}
private void removeTableRow(XWPFTable table, int startIndex, int size) {
for (int i = 0; i < size; ++i) {
table.removeRow(startIndex);
}
}
private RunTemplate runTemplate(MetaTemplate template) {
if (!(template instanceof RunTemplate)) {
throw new ClassCastException("type conversion failed, template is not of type RunTemplate");
}
return (RunTemplate) template;
}
private int getMultipleRowNum() {
return 4;
}
private void checkTargetIsTable(XWPFRun run, String message) {
if (Objects.isNull(run) || !TableTools.isInsideTable(run)) {
throw new IllegalStateException(message);
}
}
@SuppressWarnings("unchecked")
private void setTableRow(XWPFTable table, XWPFTableRow row, int pos) {
List<XWPFTableRow> rows = (List<XWPFTableRow>) ReflectionUtils.getValue("tableRows", table);
rows.set(pos, row);
table.getCTTbl().setTrArray(pos, row.getCtRow());
}
private int getRowIndex(XWPFTableRow row) {
List<XWPFTableRow> rows = row.getTable().getRows();
return rows.indexOf(row);
}
}
三、效果