Skip to content

Commit

Permalink
Merge pull request #74 from DDS-GmbH/feature/sc-6127-template-generation
Browse files Browse the repository at this point in the history
sc-6127 Enhance poipath for insertion to generate templates dynamically
  • Loading branch information
AntonOellerer committed Jan 18, 2023
2 parents 77cb2b1 + 6432069 commit ce48db8
Show file tree
Hide file tree
Showing 10 changed files with 611 additions and 3 deletions.
72 changes: 71 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,74 @@ class TestReports {
}
```

## Defining XWPF/XSSF Datastructures

With version `2.0.0` one can now also define XWPF and XSSF data structures:

```java
package myreportingapp;

import static com.docutools.poipath.xssf.XSSFWorkbookWrapper.wrap;
import static com.docutools.poipath.xssf.XSSFBuilder.buildWorkbook;
import static com.docutools.poipath.xwpf.XWPFDocumentWrapper.wrap;
import static com.docutools.poipath.xwpf.XWPFBuilder.buildDocument;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import java.util.Objects;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class CreateTestDocuments {

@Test
@DisplayName("Modify XSSF cell")
void modifyCell() {
// Arrange
var red = IndexedColors.RED.getIndex();

// Act
var workbook = buildWorkbook()
.sheet()
.row(0)
.cell(0)
.value("Hello, World!", String.class)
.modify(cell -> {
var cellStyle = cell.getCellStyle();
if(cellStyle == null)
cellStyle = cell.getSheet().getWorkbook().createCellStyle();
cellStyle.setFillForegroundColor(red);
cell.setCellStyle(cellStyle);
})
.build();

// Assert
assertThat(wrap(workbook).sheet(0).row(0).cell(0).cellStyle().getFillForegroundColor(), is(red));
}

@Test
@DisplayName("Modify XWPF paragraph.")
void modifyParagraph() {
// Act
var document = buildDocument()
.paragraph()
.run("Hello, World!")
.modify(paragraph -> {
paragraph.setAlignment(ParagraphAlignment.CENTER);
})
.end()
.build();

// Assert
assertThat(Objects.requireNonNull(wrap(document).bodyElement(0).asParagraph()).paragraph().getAlignment(), is(ParagraphAlignment.CENTER));
}

}

```

## Feature Overview

### XSSF
Expand All @@ -55,6 +123,7 @@ class TestReports {
- [ ] Pictures or diagrams
- [ ] Header/footer
- [ ] Document/page settings
- [x] Define XSSF Datastructures

### XWPF

Expand All @@ -65,4 +134,5 @@ class TestReports {
- [ ] Header/footer
- [ ] Document/page settings
- [ ] Footer notes
- [ ] Table of contents
- [ ] Table of contents
- [x] Define XWPF Datastructures
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ plugins {
}

group = 'com.docutools'
version = '1.1.6'
version = '2.0.0'
sourceCompatibility = 17
targetCompatibility = 17

Expand Down
5 changes: 5 additions & 0 deletions src/main/java/com/docutools/poipath/xssf/CellWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;

Expand Down Expand Up @@ -67,4 +68,8 @@ public ZonedDateTime zonedDateTime() {
var date = cell.getDateCellValue();
return ZonedDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
}

public CellStyle cellStyle() {
return cell.getCellStyle();
}
}
128 changes: 128 additions & 0 deletions src/main/java/com/docutools/poipath/xssf/XSSFBuilder.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
package com.docutools.poipath.xssf;

import java.lang.reflect.InvocationTargetException;
import java.util.function.Consumer;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

/**
* Provides a simple builder pattern for defining XSSF data structures.
*
* @param <T> the XSSF type {@link XSSFWorkbook}, {@link XSSFSheet}, {@link XSSFRow}, ...
*/
public record XSSFBuilder<T>(XSSFBuilder<?> parent, T bodyElement) {

/**
* Gets the final {@link XSSFWorkbook}.
*
* @return {@link XSSFWorkbook}
*/
public XSSFWorkbook build() {
if (bodyElement instanceof XSSFWorkbook workbook) {
return workbook;
} else if (bodyElement instanceof XSSFSheet sheet) {
return sheet.getWorkbook();
} else if (bodyElement instanceof XSSFRow row) {
return row.getSheet().getWorkbook();
} else if (bodyElement instanceof XSSFCell cell) {
return cell.getSheet().getWorkbook();
}
throw new UnsupportedOperationException("Cannot get XSSFWorkbook from <%s>, call .end() to hit an upper hierarchy.".formatted(bodyElement));
}

/**
* Initializes a new {@link XSSFBuilder} for an empty {@link XSSFWorkbook}.
*
* @return {@link XSSFBuilder}
*/
public static XSSFBuilder<XSSFWorkbook> buildWorkbook() {
var workbook = new XSSFWorkbook();
return new XSSFBuilder<>(null, workbook);
}

/**
* Returns the {@link XSSFBuilder} for the XSSF element a hierarchy level above.
*
* @return {@link XSSFBuilder} or {@code null} when it's a {@link XSSFWorkbook}
*/
public XSSFBuilder<?> end() {
return parent;
}

/**
* Applies a given function on the XSSF element.
*
* @return {@code this}
*/
public XSSFBuilder<T> modify(Consumer<T> consumer) {
consumer.accept(bodyElement);
return this;
}

/**
* Creates a new {@link XSSFSheet} in the {@link XSSFWorkbook}.
*
* @return {@link XSSFBuilder} for {@link XSSFSheet}
*/
public XSSFBuilder<XSSFSheet> sheet() {
if (bodyElement instanceof XSSFWorkbook workbook) {
return new XSSFBuilder<>(this, workbook.createSheet());
}
throw isUnsupported(XSSFSheet.class);
}

/**
* Creates a new {@link XSSFRow}.
*
* @param number the row number, starting at 0
* @return the {@link XSSFBuilder} for {@link XSSFRow}
*/
public XSSFBuilder<XSSFRow> row(int number) {
if (bodyElement instanceof XSSFSheet sheet) {
return new XSSFBuilder<>(this, sheet.createRow(number));
}
throw isUnsupported(XSSFRow.class);
}

/**
* Creates a new {@link XSSFCell}.
*
* @param index the cell index, starting at 0
* @return the {@link XSSFBuilder} for {@link XSSFCell}
*/
public XSSFBuilder<XSSFCell> cell(int index) {
if (bodyElement instanceof XSSFRow row) {
return new XSSFBuilder<>(this, row.createCell(index));
}
throw isUnsupported(XSSFCell.class);
}

/**
* Tries to insert the given value into the {@link XSSFCell}.
*
* @param content the cell value
* @param clazz cell value Java type
* @param <V> cell value java type
* @return {@code this}
*/
public <V> XSSFBuilder<T> value(V content, Class<V> clazz) {
if (bodyElement instanceof XSSFCell cell) {
try {
var method = XSSFCell.class.getMethod("setCellValue", clazz);
method.invoke(cell, content);
return this;
} catch (NoSuchMethodException ignored) {
throw isUnsupported(clazz);
} catch (InvocationTargetException | IllegalAccessException e) {
throw new UnsupportedOperationException("Ran into Exception when calling setCellValue(%s)".formatted(clazz), e);
}
}
throw isUnsupported(String.class);
}

private RuntimeException isUnsupported(Class<?> unsupportedType) {
return new UnsupportedOperationException("Cannot add <%s> to <%s>".formatted(unsupportedType.getName(), bodyElement.getClass().getName()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,8 @@ public int numberOfSheets() {
return workbook.getNumberOfSheets();
}

public static XSSFWorkbookWrapper wrap(XSSFWorkbook workbook) {
return new XSSFWorkbookWrapper(workbook);
}

}
Loading

0 comments on commit ce48db8

Please sign in to comment.