Skip to content

Commit

Permalink
feat: add support for providing excel formats per cell
Browse files Browse the repository at this point in the history
Closes #93
  • Loading branch information
mlopezFC authored and paodb committed Feb 27, 2024
1 parent 5e78b24 commit 183882f
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.ArrayUtils;
Expand All @@ -57,6 +59,7 @@
import com.vaadin.flow.data.binder.BeanPropertySet;
import com.vaadin.flow.data.binder.PropertySet;
import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.function.ValueProvider;

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

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

public ExcelInputStreamFactory(GridExporter<T> exporter, String template) {
super(exporter, template, DEFAULT_TEMPLATE);
Expand Down Expand Up @@ -279,7 +283,7 @@ private void buildRow(T item, Sheet sheet, Cell startingCell) {
configureAlignment(column.getTextAlign(), currentCell);
}
currentColumn[0] = currentColumn[0] + 1;
buildCell(value, currentCell, column);
buildCell(value, currentCell, column, item);
});
}

Expand Down Expand Up @@ -331,31 +335,52 @@ protected void configureAlignment(ColumnTextAlign columnTextAlign, Cell currentC
}
}

private void buildCell(Object value, Cell cell, Column<T> column) {
String excelFormat =
(String) ComponentUtil.getData(column, GridExporter.COLUMN_EXCEL_FORMAT_DATA);
@SuppressWarnings("unchecked")
private void buildCell(Object value, Cell cell, Column<T> column, T item) {
ValueProvider<T,String> provider = null;
provider = (ValueProvider<T, String>) ComponentUtil.getData(column, GridExporter.COLUMN_EXCEL_FORMAT_DATA_PROVIDER);
String excelFormat;
Map<String,CellStyle> cellStyles = (Map<String, CellStyle>) ComponentUtil.getData(column, COLUMN_CELLSTYLE_MAP);
if (cellStyles==null) {
cellStyles = new HashMap<>();
ComponentUtil.setData(column, COLUMN_CELLSTYLE_MAP, cellStyles);
}
if (provider!=null) {
excelFormat = provider.apply(item);
} else {
excelFormat =
(String) ComponentUtil.getData(column, GridExporter.COLUMN_EXCEL_FORMAT_DATA);
}
if (value == null) {
PoiHelper.setBlank(cell);
} else if (value instanceof Number) {
excelFormat = (excelFormat!=null)?excelFormat:"0";
applyExcelFormat(cell, excelFormat);
cell.setCellValue(((Number) value).doubleValue());
applyExcelFormat(cell, excelFormat, cellStyles);
} else if (value instanceof Date) {
excelFormat = (excelFormat!=null)?excelFormat:"dd/MM/yyyy";
applyExcelFormat(cell, excelFormat);
applyExcelFormat(cell, excelFormat, cellStyles);
cell.setCellValue((Date) value);
} else if (value instanceof LocalDate) {
excelFormat = (excelFormat!=null)?excelFormat:"dd/MM/yyyy";
applyExcelFormat(cell, excelFormat);
applyExcelFormat(cell, excelFormat, cellStyles);
cell.setCellValue(
Date.from(((LocalDate) value).atStartOfDay(ZoneId.systemDefault()).toInstant()));
} else {
cell.setCellValue(value.toString());
}
}

private void applyExcelFormat(Cell cell, String excelFormat) {
private void applyExcelFormat(Cell cell, String excelFormat, Map<String, CellStyle> cellStyles) {
DataFormat format = cell.getSheet().getWorkbook().createDataFormat();
if (excelFormat!=null && cellStyles.get(excelFormat)==null) {
CellStyle cs = cell.getSheet().getWorkbook().createCellStyle();
cs.cloneStyleFrom(cell.getCellStyle());
cellStyles.put(excelFormat, cs);
cell.setCellStyle(cs);
} else if (excelFormat!=null) {
cell.setCellStyle(cellStyles.get(excelFormat));
}
cell.getCellStyle().setDataFormat(format.getFormat(excelFormat));
}

Expand Down Expand Up @@ -406,7 +431,7 @@ private void fillHeaderOrFooter(
(isHeader
? headerOrFooter.getLeft()
: transformToType(headerOrFooter.getLeft(), headerOrFooter.getRight()));
buildCell(value, cell, headerOrFooter.getRight());
buildCell(value, cell, headerOrFooter.getRight(), null);
configureAlignment(headerOrFooter.getRight().getTextAlign(), cell);
sheet.setActiveCell(
new CellAddress(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ public class GridExporter<T> implements Serializable {
static final String COLUMN_EXPORTED_PROVIDER_DATA = "column-value-exported-data";
static final String COLUMN_PARSING_FORMAT_PATTERN_DATA = "column-parsing-format-pattern-data";
static final String COLUMN_EXCEL_FORMAT_DATA = "column-excel-format-data";
static final String COLUMN_EXCEL_FORMAT_DATA_PROVIDER = "column-excel-format-data-provider";
static final String COLUMN_TYPE_DATA = "column-type-data";
static final String COLUMN_TYPE_NUMBER = "number";
static final String COLUMN_TYPE_DATE = "date";
Expand Down Expand Up @@ -452,6 +453,23 @@ public void setNumberColumnFormat(
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_NUMBER);
}

/**
* If the column is based on a String, it configures a DecimalFormat to parse a number from the
* value of the column so it can be converted to a Double, and then allows to specify the excel
* format to be applied to the cell when exported to excel with a provider, so the resulting cell
* is not a string but a number that can be used in formulas.
*
* @param column
* @param decimalFormat
* @param excelFormatProvider
*/
public void setNumberColumnFormatProvider(Column<T> column, DecimalFormat decimalFormat,
ValueProvider<T, String> excelFormatProvider) {
ComponentUtil.setData(column, COLUMN_PARSING_FORMAT_PATTERN_DATA, decimalFormat);
ComponentUtil.setData(column, COLUMN_EXCEL_FORMAT_DATA_PROVIDER, excelFormatProvider);
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_NUMBER);
}

/**
* If the column is based on a String, it configures a DateFormat to parse a date from the value
* of the column so it can be converted to a java.util.Date, and then allows to specify the excel
Expand All @@ -468,6 +486,23 @@ public void setDateColumnFormat(Column<T> column, DateFormat dateFormat, String
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_DATE);
}

/**
* If the column is based on a String, it configures a DateFormat to parse a date from the value
* of the column so it can be converted to a java.util.Date, and then allows to specify the excel
* format to be applied to the cell when exported to excel, so the resulting cell is not a string
* but a date that can be used in formulas.
*
* @param column
* @param dateFormat
* @param excelFormat
*/
public void setDateColumnFormatProvider(Column<T> column, DateFormat dateFormat,
ValueProvider<T, String> excelFormatProvider) {
ComponentUtil.setData(column, COLUMN_PARSING_FORMAT_PATTERN_DATA, dateFormat);
ComponentUtil.setData(column, COLUMN_EXCEL_FORMAT_DATA_PROVIDER, excelFormatProvider);
ComponentUtil.setData(column, COLUMN_TYPE_DATA, COLUMN_TYPE_DATE);
}

/**
* If the column is based on a number attribute of the item, rendered with a NumberRenderer, it
* configures the excel format to be applied to the cell when exported to excel, so the resulting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
import java.util.stream.Stream;
Expand Down Expand Up @@ -69,6 +70,10 @@ public GridExporterSimpleCustomTemplateDemo() throws EncryptedDocumentException,
grid.addColumn(item -> decimalFormat.format(item.getBudget() + (item.getBudget() / 2)))
.setHeader("Max. Budget")
.setTextAlign(ColumnTextAlign.END);
Column<Person> quantityColumn =
grid.addColumn(item -> decimalFormat.format(item.getBudget() + (new Random().nextInt(10))))
.setHeader("Quantity")
.setTextAlign(ColumnTextAlign.END);
Column<Person> dateColumn1 =
grid.addColumn(new LocalDateRenderer<>(Person::getFavDate, "dd/MM/yyyy"))
.setHeader("Fav Date")
Expand Down Expand Up @@ -104,6 +109,7 @@ public GridExporterSimpleCustomTemplateDemo() throws EncryptedDocumentException,
exporter.setCsvExportEnabled(false);
exporter.setNumberColumnFormat(minBudgetColumn, "$#.###,##");
exporter.setNumberColumnFormat(maxBudgetColumn, decimalFormat, "$#,###.##");
exporter.setNumberColumnFormatProvider(quantityColumn, decimalFormat, (person)->person.getBudget()>50000?"#,###.## \"kg\"":"#,###.## \"l\"");
exporter.setDateColumnFormat(dateColumn1, "dd/MM/yyyy");
exporter.setDateColumnFormat(dateColumn2, new SimpleDateFormat("dd/MM/yyyy"), "dd/MM/yyyy");
exporter.setFileName(
Expand Down

0 comments on commit 183882f

Please sign in to comment.