/* * Copyright 2014-2020 Sayi * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.yuanchu.mom.utils; import com.deepoove.poi.XWPFTemplate; import com.deepoove.poi.exception.RenderException; import com.deepoove.poi.policy.RenderPolicy; import com.deepoove.poi.render.compute.RenderDataCompute; import com.deepoove.poi.render.processor.DocumentProcessor; 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 org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTcPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STMerge; import java.util.Iterator; import java.util.List; /** * Hack for loop table row * * @author Sayi * */ public class HackLoopTableRenderPolicy implements RenderPolicy { private String prefix; private String suffix; private boolean onSameLine; public HackLoopTableRenderPolicy() { this(false); } public HackLoopTableRenderPolicy(boolean onSameLine) { this("[", "]", onSameLine); } public HackLoopTableRenderPolicy(String prefix, String suffix) { this(prefix, suffix, false); } public HackLoopTableRenderPolicy(String prefix, String suffix, boolean onSameLine) { this.prefix = prefix; this.suffix = suffix; this.onSameLine = onSameLine; } @Override public void render(ElementTemplate eleTemplate, Object data, XWPFTemplate template) { RunTemplate runTemplate = (RunTemplate) eleTemplate; XWPFRun run = runTemplate.getRun(); try { if (!TableTools.isInsideTable(run)) { throw new IllegalStateException( "The template tag " + runTemplate.getSource() + " must be inside a table"); } XWPFTableCell tagCell = (XWPFTableCell) ((XWPFParagraph) run.getParent()).getBody(); XWPFTable table = tagCell.getTableRow().getTable(); run.setText("", 0); int templateRowIndex = getTemplateRowIndex(tagCell); if (null != data && data instanceof Iterable) { Iterator iterator = ((Iterable) data).iterator(); XWPFTableRow templateRow = table.getRow(templateRowIndex); int insertPosition = templateRowIndex; TemplateResolver resolver = new TemplateResolver(template.getConfig().copy(prefix, suffix)); boolean firstFlag = true; while (iterator.hasNext()) { insertPosition = templateRowIndex++; XWPFTableRow nextRow = table.insertNewTableRow(insertPosition); setTableRow(table, templateRow, insertPosition); // double set row XmlCursor newCursor = templateRow.getCtRow().newCursor(); newCursor.toPrevSibling(); XmlObject object = newCursor.getObject(); nextRow = new XWPFTableRow((CTRow) object, table); if (!firstFlag) { // update VMerge cells for non-first row List tableCells = nextRow.getTableCells(); for (XWPFTableCell cell : tableCells) { CTTcPr tcPr = TableTools.getTcPr(cell); CTVMerge vMerge = tcPr.getVMerge(); if (null == vMerge) continue; if (STMerge.RESTART == vMerge.getVal()) { vMerge.setVal(STMerge.CONTINUE); } } } else { firstFlag = false; } setTableRow(table, nextRow, insertPosition); RenderDataCompute dataCompute = template.getConfig().getRenderDataComputeFactory() .newCompute(iterator.next()); List cells = nextRow.getTableCells(); cells.forEach(cell -> { List templates = resolver.resolveBodyElements(cell.getBodyElements()); new DocumentProcessor(template, resolver, dataCompute).process(templates); }); } } table.removeRow(templateRowIndex); afterloop(table, data); } catch (Exception e) { throw new RenderException("HackLoopTable for " + eleTemplate + "error: " + e.getMessage(), e); } } private int getTemplateRowIndex(XWPFTableCell tagCell) { XWPFTableRow tagRow = tagCell.getTableRow(); return onSameLine ? getRowIndex(tagRow) : (getRowIndex(tagRow) + 1); } protected void afterloop(XWPFTable table, Object data) { } @SuppressWarnings("unchecked") private void setTableRow(XWPFTable table, XWPFTableRow templateRow, int pos) { List rows = (List) ReflectionUtils.getValue("tableRows", table); rows.set(pos, templateRow); table.getCTTbl().setTrArray(pos, templateRow.getCtRow()); } private int getRowIndex(XWPFTableRow row) { List rows = row.getTable().getRows(); return rows.indexOf(row); } }