Skip to content
This repository has been archived by the owner on Mar 31, 2022. It is now read-only.

Commit

Permalink
Support XLSX export for pivot table #335
Browse files Browse the repository at this point in the history
  • Loading branch information
Flaurite committed Jul 20, 2021
1 parent 5beddcf commit b0328a5
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 50 deletions.
3 changes: 2 additions & 1 deletion pivot-table/pivot-table.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ archivesBaseName = 'jmix-pivot-table'
dependencies {
api project(':ui-export')

api 'org.apache.poi:poi'
implementation 'org.apache.poi:poi'
implementation 'org.apache.poi:poi-ooxml'

api 'org.webjars.bower:pivottable'
api 'org.webjars:jquery-ui-touch-punch'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.jmix.pivottable.component;


import io.jmix.pivottable.component.impl.PivotExcelExporter;
import io.jmix.pivottable.component.impl.PivotExcelExporter.ExportFormat;
import io.jmix.pivottable.model.Renderer;
import io.jmix.ui.download.Downloader;
import io.jmix.pivottable.model.extension.PivotData;
Expand Down Expand Up @@ -107,4 +109,16 @@ public interface PivotTableExtension {
* @return {@code true} if renderer is supported by the exporter
*/
boolean isRendererSupported(Renderer renderer);

/**
* @return export format {@code XLS} or {@code XLSX}
*/
ExportFormat getExportFormat();

/**
* Sets export format {@code XLS} or {@code XLSX}. The default value is {@code XLSX}.
*
* @param exportFormat format that should have exported file
*/
void setExportFormat(ExportFormat exportFormat);
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@
import io.jmix.pivottable.model.extension.PivotDataCell;
import io.jmix.pivottable.model.extension.PivotDataSeparatedCell;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
Expand Down Expand Up @@ -70,21 +71,27 @@ public class PivotExcelExporter {

public static final String DEFAULT_FILE_NAME = "pivotData";

protected HSSFWorkbook wb;
protected HSSFSheet sheet;
public enum ExportFormat {
XLS, XLSX;
}

protected ExportFormat exportFormat = ExportFormat.XLSX;

protected HSSFFont stdFont;
protected Workbook wb;
protected Sheet sheet;

protected HSSFCellStyle cellLabelBoldStyle;
protected Font stdFont;

protected HSSFCellStyle cellDateTimeStyle;
protected HSSFCellStyle boldCellDateTimeStyle;
protected CellStyle cellLabelBoldStyle;

protected HSSFCellStyle cellDateStyle;
protected HSSFCellStyle boldCellDateStyle;
protected CellStyle cellDateTimeStyle;
protected CellStyle boldCellDateTimeStyle;

protected HSSFCellStyle cellTimeStyle;
protected HSSFCellStyle boldCellTimeStyle;
protected CellStyle cellDateStyle;
protected CellStyle boldCellDateStyle;

protected CellStyle cellTimeStyle;
protected CellStyle boldCellTimeStyle;

protected String fileName;
protected MetaClass entityMetaClass;
Expand Down Expand Up @@ -137,7 +144,8 @@ protected void initNotifications(PivotTable pivotTable) {
}

/**
* Export to Xls.
* Exports pivot table data to the excel file. File format can be configured by
* {@link #setExportFormat(ExportFormat)}.
*
* @param pivotData pivot with aggregated data
* @param fileName file name
Expand Down Expand Up @@ -171,11 +179,12 @@ public void exportPivotTable(PivotData pivotData, String fileName) {
}

/**
* Export to Xls.
* Exports pivot table data to the excel file. File format can be configured by
* {@link #setExportFormat(ExportFormat)}.
*
* @param pivotData pivot with aggregated data
* @param fileName file name
* @param downloader ExportDisplay implementation
* @param downloader Downloader implementation
*/
public void exportPivotTable(PivotData pivotData, String fileName, Downloader downloader) {
checkNotNullArgument(pivotData);
Expand Down Expand Up @@ -234,34 +243,34 @@ protected void createRows(PivotData pivotData) {
break;
}

HSSFRow hssfRow = sheet.createRow(i);
Row excelRow = sheet.createRow(i);
List<PivotDataSeparatedCell> row = dataRows.get(i);
for (PivotDataSeparatedCell cell : row) {
HSSFCell hssfCell = hssfRow.createCell(cell.getIndexCol());
Cell excelCell = excelRow.createCell(cell.getIndexCol());

PivotDataCell.Type type = cell.getType();
switch (type) {
case NUMERIC:
hssfCell.setCellType(CellType.NUMERIC);
hssfCell.setCellValue(Double.parseDouble(cell.getValue()));
excelCell.setCellType(CellType.NUMERIC);
excelCell.setCellValue(Double.parseDouble(cell.getValue()));
if (cell.isBold()) {
hssfCell.setCellStyle(cellLabelBoldStyle);
excelCell.setCellStyle(cellLabelBoldStyle);
}
break;
case DATE_TIME:
initDateTimeCell(hssfCell, cell, dateTimeFormatter, cellDateTimeStyle, boldCellDateTimeStyle);
initDateTimeCell(excelCell, cell, dateTimeFormatter, cellDateTimeStyle, boldCellDateTimeStyle);
break;
case DATE:
initDateTimeCell(hssfCell, cell, dateFormatter, cellDateStyle, boldCellDateStyle);
initDateTimeCell(excelCell, cell, dateFormatter, cellDateStyle, boldCellDateStyle);
break;
case TIME:
initDateTimeCell(hssfCell, cell, timeFormatter, cellTimeStyle, boldCellTimeStyle);
initDateTimeCell(excelCell, cell, timeFormatter, cellTimeStyle, boldCellTimeStyle);
break;
case STRING:
hssfCell.setCellType(CellType.STRING);
hssfCell.setCellValue(cell.getValue());
excelCell.setCellType(CellType.STRING);
excelCell.setCellValue(cell.getValue());
if (cell.isBold()) {
hssfCell.setCellStyle(cellLabelBoldStyle);
excelCell.setCellStyle(cellLabelBoldStyle);
}
break;
}
Expand Down Expand Up @@ -313,36 +322,40 @@ protected void updateColumnSize(ExcelAutoColumnSizer[] sizers, PivotDataSeparate
}
}

protected void initDateTimeCell(HSSFCell hssfCell, PivotDataSeparatedCell cell, SimpleDateFormat formatter,
HSSFCellStyle cellStyle, HSSFCellStyle boldCellStyle) {
protected void initDateTimeCell(Cell excelCell, PivotDataSeparatedCell cell, SimpleDateFormat formatter,
CellStyle cellStyle, CellStyle boldCellStyle) {
if (formatter != null) {
try {
hssfCell.setCellValue(formatter.parse(cell.getValue()));
excelCell.setCellValue(formatter.parse(cell.getValue()));
if (cell.isBold()) {
hssfCell.setCellStyle(boldCellStyle);
excelCell.setCellStyle(boldCellStyle);
} else {
hssfCell.setCellStyle(cellStyle);
excelCell.setCellStyle(cellStyle);
}
return;
} catch (ParseException e) {
// ignore because we set it as string
}
}
// set as string
hssfCell.setCellType(CellType.STRING);
hssfCell.setCellValue(cell.getValue());
excelCell.setCellType(CellType.STRING);
excelCell.setCellValue(cell.getValue());
if (cell.isBold()) {
hssfCell.setCellStyle(cellLabelBoldStyle);
excelCell.setCellStyle(cellLabelBoldStyle);
}
}

protected void createWorkbookWithSheet() {
wb = new HSSFWorkbook();
if (exportFormat == ExportFormat.XLS) {
wb = new HSSFWorkbook();
} else {
wb = new XSSFWorkbook();
}
sheet = wb.createSheet("Export");
}

protected void createCellsStyle() {
HSSFFont boldFont = wb.createFont();
Font boldFont = wb.createFont();
boldFont.setBold(true);

stdFont = wb.createFont();
Expand Down Expand Up @@ -391,9 +404,17 @@ protected void export(Downloader downloader) {
fileName = DEFAULT_FILE_NAME;
}

downloader.download(new ByteArrayDataProvider(out.toByteArray(), uiProperties.getSaveExportedByteArrayDataThresholdBytes(),
DownloadFormat downloadFormat = exportFormat == ExportFormat.XLS
? DownloadFormat.XLS
: DownloadFormat.XLSX;

downloader.download(
new ByteArrayDataProvider(
out.toByteArray(),
uiProperties.getSaveExportedByteArrayDataThresholdBytes(),
coreProperties.getTempDir()),
fileName + ".xls", DownloadFormat.XLS);
fileName + "." + downloadFormat.getFileExt(),
downloadFormat);
}

protected void showNoDataWarning() {
Expand All @@ -413,7 +434,7 @@ protected boolean isPivotDataEmpty(PivotData pivotData) {
* @return true if exported table contains more than 65536 records
*/
public boolean isXlsMaxRowNumberExceeded(PivotData pivotData) {
return MAX_ROW_INDEX < pivotData.getAllRows().size();
return exportFormat == ExportFormat.XLS && MAX_ROW_INDEX < pivotData.getAllRows().size();
}

/**
Expand Down Expand Up @@ -468,4 +489,20 @@ public String getTimeParseFormat() {
public void setTimeParseFormat(String timeParseFormat) {
this.timeParseFormat = timeParseFormat;
}

/**
* @return export format {@code XLS} or {@code XLSX}
*/
public ExportFormat getExportFormat() {
return exportFormat;
}

/**
* Sets export format {@code XLS} or {@code XLSX}. The default value is {@code XLSX}.
*
* @param exportFormat format that should have exported file
*/
public void setExportFormat(ExportFormat exportFormat) {
this.exportFormat = exportFormat;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
package io.jmix.pivottable.component.impl;

import com.google.common.collect.Sets;
import io.jmix.core.common.util.Preconditions;
import io.jmix.pivottable.component.impl.PivotExcelExporter.ExportFormat;
import io.jmix.ui.download.Downloader;
import io.jmix.pivottable.component.PivotTable;
import io.jmix.pivottable.component.PivotTableExtension;
Expand All @@ -43,6 +45,9 @@ public class PivotTableExtensionImpl implements PivotTableExtension {
protected PivotTable pivotTable;

public PivotTableExtensionImpl(PivotTable pivotTable, PivotExcelExporter exporter) {
Preconditions.checkNotNullArgument(pivotTable);
Preconditions.checkNotNullArgument(exporter);

this.pivotTable = pivotTable;
this.excelExporter = exporter;
this.excelExporter.init(pivotTable);
Expand Down Expand Up @@ -124,6 +129,16 @@ public boolean isRendererSupported(Renderer renderer) {
return supportedRenderers.contains(renderer);
}

@Override
public ExportFormat getExportFormat() {
return excelExporter.getExportFormat();
}

@Override
public void setExportFormat(ExportFormat exportFormat) {
excelExporter.setExportFormat(exportFormat);
}

protected void setupParseFormats() {
if (excelExporter != null) {
excelExporter.setDateTimeParseFormat(getDateTimeParseFormat());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ import io.jmix.pivottable.component.impl.PivotExcelExporter
import io.jmix.pivottable.component.PivotTable
import io.jmix.pivottable.component.impl.PivotTableImpl
import io.jmix.pivottable.widget.serialization.PivotTableSerializer
import org.apache.poi.hssf.usermodel.HSSFCell
import org.apache.poi.hssf.usermodel.HSSFRow
import org.apache.poi.ss.usermodel.Cell
import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.Row
import spock.lang.Specification

class ExcelExporterTest extends Specification {
Expand Down Expand Up @@ -96,17 +96,19 @@ class ExcelExporterTest extends Specification {
exporter.exportPivotTable(pivotData, null)
then:
for (int i = 0; i < 3; i++) {
HSSFRow row = exporter.sheet.getRow(i)
Row row = exporter.sheet.getRow(i)
for (int j = 0; j < cellsCount; j++) {
HSSFCell cell = row.getCell(j)
Cell cell = row.getCell(j)
if ((i == 0 || i == 1) && (j == 0 || j == 1)
|| (i == 2 && j == 2)) {
assert cell.getCellTypeEnum() == CellType.BLANK
continue
}

assert cell.getCellTypeEnum() == CellType.STRING
assert cell.getCellStyle().getFont(exporter.wb).bold

def cellStyleIndex = cell.cellStyle.fontIndexAsInt
assert exporter.wb.getFontAt(cellStyleIndex).bold
}
}
}
Expand All @@ -119,12 +121,14 @@ class ExcelExporterTest extends Specification {
exporter.exportPivotTable(pivotData, null)
then:
for (int i = 3; i < rowsCount; i++) {
HSSFRow row = exporter.sheet.getRow(i)
Row row = exporter.sheet.getRow(i)
for (int j = 0; j < cellsCount; j++) {
HSSFCell cell = row.getCell(j)
Cell cell = row.getCell(j)
if (0 <= j && j < 3) {
assert cell.getCellTypeEnum() == CellType.STRING
assert cell.getCellStyle().getFont(exporter.wb).bold

def cellStyleIndex = cell.cellStyle.fontIndexAsInt
assert exporter.wb.getFontAt(cellStyleIndex).bold
continue
}

Expand All @@ -135,7 +139,8 @@ class ExcelExporterTest extends Specification {

cell.getCellTypeEnum() == CellType.NUMERIC
if (j == 9 || i == 7) {
assert cell.getCellStyle().getFont(exporter.wb).bold
def cellStyleIndex = cell.cellStyle.fontIndexAsInt
assert exporter.wb.getFontAt(cellStyleIndex).bold
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions ui-export/ui-export.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ archivesBaseName = 'jmix-ui-export'
dependencies {
api project(':ui')

implementation('org.apache.poi:poi:4.1.2')
implementation('org.apache.poi:poi-ooxml:4.1.2')
implementation('org.apache.poi:poi')
implementation('org.apache.poi:poi-ooxml')
implementation('com.google.code.gson:gson')

testRuntimeOnly 'org.slf4j:slf4j-simple'
Expand Down

0 comments on commit b0328a5

Please sign in to comment.