Skip to content

Commit

Permalink
Export: Delete delete/reused datasets tables when empty
Browse files Browse the repository at this point in the history
  • Loading branch information
ValentinFutterer committed Jan 25, 2024
1 parent 99b74d9 commit e3a2d4e
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.*;
import java.text.SimpleDateFormat;

Expand Down Expand Up @@ -35,7 +36,7 @@ public abstract class AbstractTemplateExportFunctions {
* @return
* @throws Exception
*/
public XWPFDocument loadTemplate (InputStream template, String startChar, String endChar) throws Exception{
public XWPFDocument loadTemplate(InputStream template, String startChar, String endChar) throws Exception {
//Extract document using Apache POI https://poi.apache.org/
XWPFDocument document = new XWPFDocument(template);

Expand Down Expand Up @@ -119,7 +120,7 @@ public void addReplacement(Map<String, String> replacements, String variable, Ob
* @throws XmlException
* @throws Exception
*/
public XWPFTableRow insertNewTableRow(XWPFTableRow sourceTableRow, int pos) throws XmlException, IOException {
public XWPFTableRow insertNewTableRow(XWPFTableRow sourceTableRow, int pos) throws XmlException, IOException {
XWPFTable table = sourceTableRow.getTable();
CTRow newCTRrow = CTRow.Factory.parse(sourceTableRow.getCtRow().newInputStream());
XWPFTableRow tableRow = new XWPFTableRow(newCTRrow, table);
Expand Down Expand Up @@ -152,7 +153,7 @@ static void insertTableCells(XWPFTable table, XWPFTableRow newRow, ArrayList<Str
* @param table
* @param replacements
*/
static void replaceTableVariables(XWPFTable table, Map<String, String> replacements){
static void replaceTableVariables(XWPFTable table, Map<String, String> replacements) {
//this replaces variables in tables (e.g. costcurrency)
List<XWPFTableRow> tableRows = table.getRows();
for (XWPFTableRow xwpfTableRow : tableRows) {
Expand Down Expand Up @@ -260,7 +261,7 @@ public XWPFDocument templateFormatting(XWPFDocument document, String startChar,
* @param startChar
* @param endChar
*/
public void formattingTable(List<XWPFTable> xwpfTables, String startChar, String endChar){
public void formattingTable(List<XWPFTable> xwpfTables, String startChar, String endChar) {
if (xwpfTables != null) {
for (XWPFTable xwpfTable : xwpfTables) {
for (XWPFTableRow row : xwpfTable.getRows()) {
Expand Down Expand Up @@ -297,20 +298,18 @@ public void formattingParagraph(List<XWPFParagraph> xwpfParagraphs, String start
if (!xwpfRunText.contains(endChar)) {
removeRunIndex.add(xwpfRuns.indexOf(xwpfRun));
mergeRun = true;
if (sb.length()>0) {
if (sb.length() > 0) {
sb.delete(0, sb.length());
}
sb.append(xwpfRunText);
}
}
else {
} else {
if (mergeRun) {
sb.append(xwpfRunText);
if (xwpfRunText.contains(endChar)) {
mergeRun = false;
xwpfRun.setText(sb.toString(),0);
}
else {
xwpfRun.setText(sb.toString(), 0);
} else {
removeRunIndex.add(xwpfRuns.indexOf(xwpfRun));
}
}
Expand All @@ -326,4 +325,143 @@ public void formattingParagraph(List<XWPFParagraph> xwpfParagraphs, String start
}
}
}

/**
* Removes a table inside a document or nested inside another table.
* For nested tables, this works only for depth 1.
* If the table is not to be found inside the doc or at depth 1, nothing happens.
*
* @param doc
* @param table
*/
public void removeTable(XWPFDocument doc, XWPFTable table) {
int pos = doc.getPosOfTable(table);
if (pos != -1) {
doc.removeBodyElement(pos);
} else { // table not found in document -> nestedTable
removeNestedTable(doc, table);
}
}

/**
* Removes a table which is nested inside another table. Max nested depth is 1.
*
* @param doc
* @param table
*/
private void removeNestedTable(XWPFDocument doc, XWPFTable table) {
for (XWPFTableCell cell : getAllOuterTableCells(doc)) {
for (XWPFTable nestedTable : cell.getTables()) {
if (nestedTable.equals(table)) {
int pos = cell.getTables().indexOf(nestedTable);
// dirty hack since POI XWPF does not offer functionality for removing nested tables
try {
Field beField = cell.getClass().getDeclaredField("tables");
beField.setAccessible(true);
((List<XWPFTable>) beField.get(cell)).remove(pos); // higher level representation
} catch (Exception ignored) {
}
cell.getCTTc().removeTbl(pos); // low level cell representation

return;
}
}
}
}

/**
* Removes a paragraph inside a document or inside a table.
* This will not work for paragraphs inside nested tables.
* If the paragraph is not to be found inside the doc or inside non nested tables, nothing happens.
*
* @param doc
* @param paragraph
*/
public void removeParagraph(XWPFDocument doc, XWPFParagraph paragraph) {
int pos = doc.getPosOfParagraph(paragraph);
if (pos != -1) {
doc.removeBodyElement(pos);
} else { // paragraph not found in document -> paragraph is inside table
removeParagraphInsideTable(doc, paragraph);
}
}

/**
* Removes a paragraph which is inside a table. Does not function for nested tables
*
* @param doc
* @param paragraphToRemove
*/
public void removeParagraphInsideTable(XWPFDocument doc, XWPFParagraph paragraphToRemove) {
for (XWPFTableCell cell : getAllOuterTableCells(doc)) {
for (XWPFParagraph paragraph : cell.getParagraphs()) {
if (paragraph.equals(paragraphToRemove)) {
int pos = cell.getParagraphs().indexOf(paragraph);
cell.removeParagraph(pos);
return;
}
}
}
}

/**
* Removes a table inside a document or nested inside another table. Also removes the paragraph above it.
* For nested tables, this works only for depth 1.
* If the table is not to be found inside the doc or at depth 1, nothing happens.
* If the there is no paragraph above the table, only the table will be removed.
*
* @param doc
* @param table
*/
public void removeTableAndParagraphAbove(XWPFDocument doc, XWPFTable table) {
// paragraph above the table
if (doc.getPosOfTable(table) != -1) {
int paragraphPos = doc.getPosOfTable(table) - 1;
if (doc.getBodyElements().get(paragraphPos).getElementType().equals(BodyElementType.PARAGRAPH)) {
doc.removeBodyElement(paragraphPos);
}
} else {
for (XWPFTableCell cell : getAllOuterTableCells(doc)) {
for (XWPFTable nestedTable : cell.getTables()) {
if (nestedTable.equals(table)) {
int paragraphPos = cell.getBodyElements().indexOf(table) - 1;
if (cell.getBodyElements().get(paragraphPos).getElementType().equals(BodyElementType.PARAGRAPH)) {
XWPFParagraph paragraphToRemove = (XWPFParagraph) cell.getBodyElements().get(paragraphPos);
cell.removeParagraph(cell.getParagraphs().indexOf(paragraphToRemove));
}
}
}
}
}
// delete unnecessary table
removeTable(doc, table);
}

/**
* Returns a list of all table cells of non nested tables in the document.
*
* @param doc
*/
public List<XWPFTableCell> getAllOuterTableCells(XWPFDocument doc) {
List<XWPFTableCell> tableCells = new ArrayList<>();
for (XWPFTable outerTable : doc.getTables()) {
for (XWPFTableRow row : outerTable.getRows()) {
tableCells.addAll(row.getTableCells());
}
}
return tableCells;
}

/**
* Returns a list of all tables and nested tables with depth 1.
*
* @param doc
*/
public List<XWPFTable> getAllTables(XWPFDocument doc) {
ArrayList<XWPFTable> tables = new ArrayList<>(doc.getTables());
for (XWPFTableCell cell : getAllOuterTableCells(doc)) {
tables.addAll(cell.getTables());
}
return tables;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTVMerge;

import java.lang.reflect.Field;
import java.text.NumberFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
Expand Down Expand Up @@ -706,8 +707,9 @@ protected static String format(long number) {
}

//All tables variables replacement
public void tableContent(List<XWPFTable> xwpfTables) {
for (XWPFTable xwpfTable : xwpfTables) {
// Takes care of filling tables and deletes certain empty tables
public void tableContent(XWPFDocument document, List<XWPFTable> xwpfTables) {
for (XWPFTable xwpfTable : new ArrayList<>(xwpfTables)) {
XWPFTableRow tableIdentifierRow = xwpfTable.getRow(1);
if (tableIdentifierRow != null) {

Expand All @@ -728,7 +730,7 @@ public void tableContent(List<XWPFTable> xwpfTables) {
composeTableNewDatasets(xwpfTable);
break;
case ("[reusedDatasetTable]"):
composeTableReusedDatasets(xwpfTable);
composeTableReusedDatasets(document, xwpfTable);
break;
case ("[datasetAccessTable]"):
composeTableDataAccess(xwpfTable);
Expand All @@ -740,14 +742,20 @@ public void tableContent(List<XWPFTable> xwpfTables) {
composeTableDatasetRepository(xwpfTable);
break;
case ("[datasetDeleteTable]"):
composeTableDatasetDeletion(xwpfTable);
composeTableDatasetDeletion(document, xwpfTable);
break;
case ("[costTable]"):
composeTableCost(xwpfTable);
break;
default:
break;
}
}
replaceTableVariables(xwpfTable, replacements);
}

// prevents replacing table variables of deleted tables
for (XWPFTable table : getAllTables(document)) {
replaceTableVariables(table, replacements);
}
}

Expand Down Expand Up @@ -824,7 +832,7 @@ public List<Dataset> getReusedDatasets(){
return datasets.stream().filter(dataset -> dataset.getSource().equals(EDataSource.REUSED)).collect(Collectors.toList());
}

public void composeTableReusedDatasets(XWPFTable xwpfTable){
public void composeTableReusedDatasets(XWPFDocument document, XWPFTable xwpfTable){
log.debug("Export steps: Reused Dataset Table");

List<Dataset> reusedDatasets = getReusedDatasets();
Expand Down Expand Up @@ -877,13 +885,10 @@ public void composeTableReusedDatasets(XWPFTable xwpfTable){
insertTableCells(xwpfTable, newRow, docVar);
}
xwpfTable.removeRow(xwpfTable.getRows().size() - 1);
xwpfTable.removeRow(1);
} else {
//clean row
ArrayList<String> emptyContent = new ArrayList<String>(Arrays.asList("", "", "", "", "", ""));
insertTableCells(xwpfTable, xwpfTable.getRows().get(xwpfTable.getRows().size() - 1), emptyContent);
removeTableAndParagraphAbove(document, xwpfTable);
}
//end of dynamic table rows code
xwpfTable.removeRow(1);
}

public void composeTableDataAccess(XWPFTable xwpfTable){
Expand All @@ -902,6 +907,7 @@ public void composeTableDataAccess(XWPFTable xwpfTable){
insertTableCells(xwpfTable, xwpfTable.getRows().get(xwpfTable.getRows().size() - 1), emptyContent);
}
xwpfTable.removeRow(1);
replaceTableVariables(xwpfTable, replacements);
}

private void insertComposeTableDataAccess(XWPFTable xwpfTable, List<Dataset> currentDatasets){
Expand Down Expand Up @@ -1100,7 +1106,7 @@ public void composeTableDatasetRepository(XWPFTable xwpfTable){
commitTableRows(xwpfTable);
}

public void composeTableDatasetDeletion(XWPFTable xwpfTable){
public void composeTableDatasetDeletion(XWPFDocument document, XWPFTable xwpfTable){
log.debug("Export steps: Dataset Deletion Table");

if (deletedDatasets.size() > 0) {
Expand Down Expand Up @@ -1141,12 +1147,11 @@ public void composeTableDatasetDeletion(XWPFTable xwpfTable){
insertTableCells(xwpfTable, newRow, docVar);
}
xwpfTable.removeRow(xwpfTable.getRows().size() - 1);
xwpfTable.removeRow(1);
} else {
//clean row
ArrayList<String> emptyContent = new ArrayList<String>(Arrays.asList("", "", "", "", ""));
insertTableCells(xwpfTable, xwpfTable.getRows().get(xwpfTable.getRows().size() - 1), emptyContent);
removeTableAndParagraphAbove(document, xwpfTable);
}
xwpfTable.removeRow(1);

}

public void composeTableCost(XWPFTable xwpfTable){
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,15 @@ public XWPFDocument exportTemplate(long dmpId) {
//in FWF template this replaces paragraphs within the template table
replaceTableVariables(templateTable, replacements);
//this replaces the tables with the main template table
tableContent(templateXwpfTables);
tableContent(document, templateXwpfTables);

return document;
}

private List<XWPFTable> parseContentTables(XWPFTable templateTable) {
List<XWPFTable> templateXwpfTables = new ArrayList<>();
for (XWPFTableRow row : templateTable.getRows()){
if (row.getTableCells().size() > 1){
if (row.getTableCells().size() > 1) {
templateXwpfTables.addAll(row.getCell(1).getTables());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public XWPFDocument exportTemplate(long dmpId) {
// TO DO: combine the function with the first row generation to avoid double
// code of similar modification.
log.debug("Export steps: Replace in table");
tableContent(xwpfTables);
tableContent(document, xwpfTables);

// Fourth step of the export: modify the content of the document's footer
log.debug("Export steps: Replace in footer");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public XWPFDocument exportTemplate(long dmpId) {
//Third step of the export: dynamic table in all sections will be added from row number two until the end of data list.
//TO DO: combine the function with the first row generation to avoid double code of similar modification.
log.debug("Export steps: Replace in table");
tableContent(xwpfTables);
tableContent(document, xwpfTables);

//Fourth step of the export: modify the content of the document's footer
log.debug("Export steps: Replace in footer");
Expand Down

0 comments on commit e3a2d4e

Please sign in to comment.