Skip to content

Commit

Permalink
Enable writing of double values in excel
Browse files Browse the repository at this point in the history
Up until now, all placeholders were resolved to strings,
which meant that it was not possible to insert double values
dynamically.

To fix this, the SXSSFWriter and the ExcelGenerator are refactored in such a way that Scalar Placeholders
containing doubles are inserted as double values into the
cells.
  • Loading branch information
AntonOellerer committed May 16, 2024
1 parent 335402c commit f4e16f0
Show file tree
Hide file tree
Showing 9 changed files with 71 additions and 14 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ dependencies {
implementation 'com.codepoetics:protonpack:1.16'
implementation("com.google.guava:guava:32.1.2-jre")

implementation 'io.github.jbock-java:either:1.5.2'

testImplementation('org.junit.jupiter:junit-jupiter:5.10.0')
testImplementation("org.hamcrest:hamcrest:2.2")
testImplementation("com.docutools:poipath:2.0.0")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private PlaceholderData format(Locale locale, PlaceholderData original) {
/**
* Overwrite of the {@link Object#toString()} method, forcing any subclass to implement it,
* since its required for resolving {@link com.docutools.jocument.impl.IterablePlaceholderData}
* when no loop-end is present
* when no loop-end is present.
*
* @return a {@link String}
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import com.docutools.jocument.impl.ParsingUtils;
import com.docutools.jocument.impl.excel.interfaces.ExcelWriter;
import com.docutools.jocument.impl.excel.util.ExcelUtils;
import com.docutools.jocument.impl.word.WordUtilities;
import com.google.common.collect.Lists;
import java.util.Iterator;
import java.util.LinkedList;
Expand All @@ -20,7 +19,6 @@
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;


/**
Expand Down Expand Up @@ -83,8 +81,8 @@ private void generate() {
excelWriter.newRow(row);
for (Cell cell : row) {
if (ExcelUtils.containsPlaceholder(cell)) {
var newCellText = ExcelUtils.replacePlaceholders(cell, resolver);
excelWriter.addCell(cell, newCellText);
var newCellValue = ExcelUtils.replacePlaceholders(cell, resolver);
newCellValue.ifLeftOrElse(stringValue -> excelWriter.addCell(cell, stringValue), doubleValue -> excelWriter.addCell(cell, doubleValue));
} else if (ExcelUtils.isSimpleCell(cell)) {
excelWriter.addCell(cell);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ public void newSheet(Sheet sheet) {
currentSheet.setVerticallyCenter(sheet.getVerticallyCenter());

// copy auto filters to new sheet
if(sheet instanceof XSSFSheet xssfSheet) {
if (sheet instanceof XSSFSheet xssfSheet) {
var autoFilter = xssfSheet.getCTWorksheet().getAutoFilter();
if(autoFilter != null) {
if (autoFilter != null) {
var ref = autoFilter.getRef();
var range = CellRangeAddress.valueOf(ref);
currentSheet.setAutoFilter(range);
Expand Down Expand Up @@ -240,6 +240,19 @@ public void addCell(Cell templateCell, String newCellText) {
addCell(templateCell, newCellText, 0);
}

@Override
public void addCell(Cell templateCell, double newCellValue) {
//todo merge with addCell(Cell, String, int)
logger.trace("Creating new cell {} {} with text {}",
templateCell.getColumnIndex(), templateCell.getRow().getRowNum(), newCellValue);
var newCell = currentRow.createCell(templateCell.getColumnIndex(), templateCell.getCellType());
newCell.setCellComment(templateCell.getCellComment());
newCell.setCellStyle(cellStyleMap.computeIfAbsent((int) templateCell.getCellStyle().getIndex(), i -> copyCellStyle(templateCell.getCellStyle())));
newCell.setHyperlink(templateCell.getHyperlink());
currentSheet.setColumnWidth(templateCell.getColumnIndex(), templateCell.getSheet().getColumnWidth(templateCell.getColumnIndex()));
newCell.setCellValue(newCellValue);
}

@Override
public void addCell(Cell templateCell, String newCellText, int columnOffset) {
logger.trace("Creating new cell {} {} with text {}",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,21 @@ public interface ExcelWriter {
void addRowOffset(int size);

/**
* Create a new cell from the templateCell with the specified cell text. This has to be done e.g. for template cells in loops which have to be used
* multiple times.
* Create a new cell from the templateCell with the specified cell text.
*
* @param templateCell The template cell to create the new cell from
* @param newCellText The text to insert into the cell
*/
void addCell(Cell templateCell, String newCellText);

/**
* Create a new cell from the templateCell with the specified cell value.
*
* @param templateCell The template cell to create the new cell from
* @param newCellValue The text to insert into the cell
*/
void addCell(Cell templateCell, double newCellValue);

/**
* Create a new cell from the templateCell with the specified cell text and the specified offset. This has to be done e.g. for template cells in
* loops which have to be used multiple times.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.docutools.jocument.impl.excel.util;

import com.docutools.jocument.PlaceholderData;
import com.docutools.jocument.PlaceholderResolver;
import com.docutools.jocument.impl.DocumentImpl;
import com.docutools.jocument.impl.ParsingUtils;
import com.docutools.jocument.impl.ScalarPlaceholderData;
import io.jbock.util.Either;
import java.util.Locale;
import java.util.Optional;
import java.util.Spliterator;
Expand All @@ -26,15 +28,32 @@ private ExcelUtils() {
* @param resolver {@link PlaceholderResolver} used to resolve the placeholders found in value.
* @return String with replaced placeholders.
*/
public static String replacePlaceholders(Cell cell, PlaceholderResolver resolver) {
public static Either<String, Double> replacePlaceholders(Cell cell, PlaceholderResolver resolver) {
String cellValue = getCellContentAsString(cell);
Optional<PlaceholderData> firstPlaceholderData = resolveCell(cellValue, resolver);
if (firstPlaceholderData.isPresent()
&& firstPlaceholderData.get() instanceof ScalarPlaceholderData<?> scalarPlaceholderData
&& scalarPlaceholderData.getRawValue() instanceof Number number) {
return Either.right(number.doubleValue());
}
var matcher = ParsingUtils.matchPlaceholders(cellValue);
return matcher.replaceAll(matchResult -> resolver.resolve(matchResult.group(1))
return Either.left(matcher.replaceAll(matchResult -> resolver.resolve(matchResult.group(1))
.orElse(new ScalarPlaceholderData<>("-"))
.toString()
.toString())
);
}

private static Optional<PlaceholderData> resolveCell(String cellValue, PlaceholderResolver resolver) {
if (cellValue == null || !cellValue.startsWith("{{") && !cellValue.endsWith("}}")) {
return Optional.empty();
}
var matchingResults = ParsingUtils.matchPlaceholders(cellValue).results().toList();
if (matchingResults.size() != 1) {
return Optional.empty();
}
return resolver.resolve(matchingResults.get(0).group(1));
}

public static String getPlaceholder(Cell cell) {
return ParsingUtils.stripBrackets(cell.getStringCellValue());
}
Expand Down
19 changes: 19 additions & 0 deletions src/test/java/com/docutools/jocument/excel/AutomatedXlsxTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,23 @@ void keepAutoFilters() throws InterruptedException, IOException {
assertThat(rangeAddress.isInRange(sheet.row(0).cell(0).cell()), is(true));
}

@Test
void insertNumericValue() throws InterruptedException, IOException {
// Arrange
Template template = Template.fromClassPath("/templates/excel/NumericValues.xlsx")
.orElseThrow();
PlaceholderResolver resolver = new ReflectionResolver(SampleModelData.ENTERPRISE);

// Act
Document document = template.startGeneration(resolver);
document.blockUntilCompletion(5_000L); // 5 seconds

// Assert
assertThat(document.completed(), is(true));
var xssfWorkbook = TestUtils.getXSSFWorkbookFromDocument(document);
var xssf = new XSSFWorkbookWrapper(xssfWorkbook);
var sheet = xssf.sheet(0);
assertThat(sheet.row(0).cell(0).doubleValue(), is(5.0));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import com.docutools.jocument.sample.placeholders.QuotesBlockPlaceholder;
import com.docutools.poipath.PoiPath;
import com.docutools.poipath.xssf.XSSFWorkbookWrapper;
import com.docutools.poipath.xwpf.XWPFDocumentWrapper;
import java.io.IOException;
import java.time.LocalDate;
import java.time.Period;
Expand Down Expand Up @@ -139,7 +138,7 @@ void shouldResolveUserProfilePlaceholders() throws InterruptedException, IOExcep
assertThat(firstSheet.row(3).cell(0).stringValue(), equalTo("Last Name"));
assertThat(firstSheet.row(3).cell(1).stringValue(), equalTo("Picard"));
assertThat(firstSheet.row(4).cell(0).stringValue(), equalTo("Age"));
assertThat(firstSheet.row(4).cell(1).stringValue(), equalTo(String.valueOf(Period.between(LocalDate.of(1948, 9, 23), LocalDate.now()).getYears())));
assertThat(firstSheet.row(4).cell(1).doubleValue(), equalTo((double) Period.between(LocalDate.of(1948, 9, 23), LocalDate.now()).getYears()));
assertThat(firstSheet.row(4).cell(2).stringValue(), equalTo(DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.US).format(LocalDate.of(1948, 9, 23))));
}

Expand Down
Binary file not shown.

0 comments on commit f4e16f0

Please sign in to comment.