Skip to content

Commit 183882f

Browse files
mlopezFCpaodb
authored andcommitted
feat: add support for providing excel formats per cell
Closes #93
1 parent 5e78b24 commit 183882f

File tree

3 files changed

+75
-9
lines changed

3 files changed

+75
-9
lines changed

src/main/java/com/flowingcode/vaadin/addons/gridexporter/ExcelInputStreamFactory.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@
3030
import java.time.LocalDate;
3131
import java.time.ZoneId;
3232
import java.util.Date;
33+
import java.util.HashMap;
3334
import java.util.List;
35+
import java.util.Map;
3436
import java.util.stream.Collectors;
3537
import java.util.stream.Stream;
3638
import org.apache.commons.lang3.ArrayUtils;
@@ -57,6 +59,7 @@
5759
import com.vaadin.flow.data.binder.BeanPropertySet;
5860
import com.vaadin.flow.data.binder.PropertySet;
5961
import com.vaadin.flow.data.provider.DataProvider;
62+
import com.vaadin.flow.function.ValueProvider;
6063

6164
/**
6265
* @author mlopez
@@ -66,6 +69,7 @@ class ExcelInputStreamFactory<T> extends BaseInputStreamFactory<T> {
6669

6770
private static final Logger LOGGER = LoggerFactory.getLogger(ExcelInputStreamFactory.class);
6871
private static final String DEFAULT_TEMPLATE = "/template.xlsx";
72+
private static final String COLUMN_CELLSTYLE_MAP = "colum-cellstyle-map";
6973

7074
public ExcelInputStreamFactory(GridExporter<T> exporter, String template) {
7175
super(exporter, template, DEFAULT_TEMPLATE);
@@ -279,7 +283,7 @@ private void buildRow(T item, Sheet sheet, Cell startingCell) {
279283
configureAlignment(column.getTextAlign(), currentCell);
280284
}
281285
currentColumn[0] = currentColumn[0] + 1;
282-
buildCell(value, currentCell, column);
286+
buildCell(value, currentCell, column, item);
283287
});
284288
}
285289

@@ -331,31 +335,52 @@ protected void configureAlignment(ColumnTextAlign columnTextAlign, Cell currentC
331335
}
332336
}
333337

334-
private void buildCell(Object value, Cell cell, Column<T> column) {
335-
String excelFormat =
336-
(String) ComponentUtil.getData(column, GridExporter.COLUMN_EXCEL_FORMAT_DATA);
338+
@SuppressWarnings("unchecked")
339+
private void buildCell(Object value, Cell cell, Column<T> column, T item) {
340+
ValueProvider<T,String> provider = null;
341+
provider = (ValueProvider<T, String>) ComponentUtil.getData(column, GridExporter.COLUMN_EXCEL_FORMAT_DATA_PROVIDER);
342+
String excelFormat;
343+
Map<String,CellStyle> cellStyles = (Map<String, CellStyle>) ComponentUtil.getData(column, COLUMN_CELLSTYLE_MAP);
344+
if (cellStyles==null) {
345+
cellStyles = new HashMap<>();
346+
ComponentUtil.setData(column, COLUMN_CELLSTYLE_MAP, cellStyles);
347+
}
348+
if (provider!=null) {
349+
excelFormat = provider.apply(item);
350+
} else {
351+
excelFormat =
352+
(String) ComponentUtil.getData(column, GridExporter.COLUMN_EXCEL_FORMAT_DATA);
353+
}
337354
if (value == null) {
338355
PoiHelper.setBlank(cell);
339356
} else if (value instanceof Number) {
340357
excelFormat = (excelFormat!=null)?excelFormat:"0";
341-
applyExcelFormat(cell, excelFormat);
342358
cell.setCellValue(((Number) value).doubleValue());
359+
applyExcelFormat(cell, excelFormat, cellStyles);
343360
} else if (value instanceof Date) {
344361
excelFormat = (excelFormat!=null)?excelFormat:"dd/MM/yyyy";
345-
applyExcelFormat(cell, excelFormat);
362+
applyExcelFormat(cell, excelFormat, cellStyles);
346363
cell.setCellValue((Date) value);
347364
} else if (value instanceof LocalDate) {
348365
excelFormat = (excelFormat!=null)?excelFormat:"dd/MM/yyyy";
349-
applyExcelFormat(cell, excelFormat);
366+
applyExcelFormat(cell, excelFormat, cellStyles);
350367
cell.setCellValue(
351368
Date.from(((LocalDate) value).atStartOfDay(ZoneId.systemDefault()).toInstant()));
352369
} else {
353370
cell.setCellValue(value.toString());
354371
}
355372
}
356373

357-
private void applyExcelFormat(Cell cell, String excelFormat) {
374+
private void applyExcelFormat(Cell cell, String excelFormat, Map<String, CellStyle> cellStyles) {
358375
DataFormat format = cell.getSheet().getWorkbook().createDataFormat();
376+
if (excelFormat!=null && cellStyles.get(excelFormat)==null) {
377+
CellStyle cs = cell.getSheet().getWorkbook().createCellStyle();
378+
cs.cloneStyleFrom(cell.getCellStyle());
379+
cellStyles.put(excelFormat, cs);
380+
cell.setCellStyle(cs);
381+
} else if (excelFormat!=null) {
382+
cell.setCellStyle(cellStyles.get(excelFormat));
383+
}
359384
cell.getCellStyle().setDataFormat(format.getFormat(excelFormat));
360385
}
361386

@@ -406,7 +431,7 @@ private void fillHeaderOrFooter(
406431
(isHeader
407432
? headerOrFooter.getLeft()
408433
: transformToType(headerOrFooter.getLeft(), headerOrFooter.getRight()));
409-
buildCell(value, cell, headerOrFooter.getRight());
434+
buildCell(value, cell, headerOrFooter.getRight(), null);
410435
configureAlignment(headerOrFooter.getRight().getTextAlign(), cell);
411436
sheet.setActiveCell(
412437
new CellAddress(

src/main/java/com/flowingcode/vaadin/addons/gridexporter/GridExporter.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public class GridExporter<T> implements Serializable {
6666
static final String COLUMN_EXPORTED_PROVIDER_DATA = "column-value-exported-data";
6767
static final String COLUMN_PARSING_FORMAT_PATTERN_DATA = "column-parsing-format-pattern-data";
6868
static final String COLUMN_EXCEL_FORMAT_DATA = "column-excel-format-data";
69+
static final String COLUMN_EXCEL_FORMAT_DATA_PROVIDER = "column-excel-format-data-provider";
6970
static final String COLUMN_TYPE_DATA = "column-type-data";
7071
static final String COLUMN_TYPE_NUMBER = "number";
7172
static final String COLUMN_TYPE_DATE = "date";
@@ -452,6 +453,23 @@ public void setNumberColumnFormat(
452453
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_NUMBER);
453454
}
454455

456+
/**
457+
* If the column is based on a String, it configures a DecimalFormat to parse a number from the
458+
* value of the column so it can be converted to a Double, and then allows to specify the excel
459+
* format to be applied to the cell when exported to excel with a provider, so the resulting cell
460+
* is not a string but a number that can be used in formulas.
461+
*
462+
* @param column
463+
* @param decimalFormat
464+
* @param excelFormatProvider
465+
*/
466+
public void setNumberColumnFormatProvider(Column<T> column, DecimalFormat decimalFormat,
467+
ValueProvider<T, String> excelFormatProvider) {
468+
ComponentUtil.setData(column, COLUMN_PARSING_FORMAT_PATTERN_DATA, decimalFormat);
469+
ComponentUtil.setData(column, COLUMN_EXCEL_FORMAT_DATA_PROVIDER, excelFormatProvider);
470+
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_NUMBER);
471+
}
472+
455473
/**
456474
* If the column is based on a String, it configures a DateFormat to parse a date from the value
457475
* of the column so it can be converted to a java.util.Date, and then allows to specify the excel
@@ -468,6 +486,23 @@ public void setDateColumnFormat(Column<T> column, DateFormat dateFormat, String
468486
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_DATE);
469487
}
470488

489+
/**
490+
* If the column is based on a String, it configures a DateFormat to parse a date from the value
491+
* of the column so it can be converted to a java.util.Date, and then allows to specify the excel
492+
* format to be applied to the cell when exported to excel, so the resulting cell is not a string
493+
* but a date that can be used in formulas.
494+
*
495+
* @param column
496+
* @param dateFormat
497+
* @param excelFormat
498+
*/
499+
public void setDateColumnFormatProvider(Column<T> column, DateFormat dateFormat,
500+
ValueProvider<T, String> excelFormatProvider) {
501+
ComponentUtil.setData(column, COLUMN_PARSING_FORMAT_PATTERN_DATA, dateFormat);
502+
ComponentUtil.setData(column, COLUMN_EXCEL_FORMAT_DATA_PROVIDER, excelFormatProvider);
503+
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_DATE);
504+
}
505+
471506
/**
472507
* If the column is based on a number attribute of the item, rendered with a NumberRenderer, it
473508
* configures the excel format to be applied to the cell when exported to excel, so the resulting

src/test/java/com/flowingcode/vaadin/addons/gridexporter/GridExporterSimpleCustomTemplateDemo.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import java.time.ZoneId;
4242
import java.time.format.DateTimeFormatter;
4343
import java.util.Calendar;
44+
import java.util.Random;
4445
import java.util.concurrent.TimeUnit;
4546
import java.util.stream.IntStream;
4647
import java.util.stream.Stream;
@@ -69,6 +70,10 @@ public GridExporterSimpleCustomTemplateDemo() throws EncryptedDocumentException,
6970
grid.addColumn(item -> decimalFormat.format(item.getBudget() + (item.getBudget() / 2)))
7071
.setHeader("Max. Budget")
7172
.setTextAlign(ColumnTextAlign.END);
73+
Column<Person> quantityColumn =
74+
grid.addColumn(item -> decimalFormat.format(item.getBudget() + (new Random().nextInt(10))))
75+
.setHeader("Quantity")
76+
.setTextAlign(ColumnTextAlign.END);
7277
Column<Person> dateColumn1 =
7378
grid.addColumn(new LocalDateRenderer<>(Person::getFavDate, "dd/MM/yyyy"))
7479
.setHeader("Fav Date")
@@ -104,6 +109,7 @@ public GridExporterSimpleCustomTemplateDemo() throws EncryptedDocumentException,
104109
exporter.setCsvExportEnabled(false);
105110
exporter.setNumberColumnFormat(minBudgetColumn, "$#.###,##");
106111
exporter.setNumberColumnFormat(maxBudgetColumn, decimalFormat, "$#,###.##");
112+
exporter.setNumberColumnFormatProvider(quantityColumn, decimalFormat, (person)->person.getBudget()>50000?"#,###.## \"kg\"":"#,###.## \"l\"");
107113
exporter.setDateColumnFormat(dateColumn1, "dd/MM/yyyy");
108114
exporter.setDateColumnFormat(dateColumn2, new SimpleDateFormat("dd/MM/yyyy"), "dd/MM/yyyy");
109115
exporter.setFileName(

0 commit comments

Comments
 (0)