package org.devgateway.toolkit.web.excelcharts;
import org.apache.poi.ss.usermodel.Chart;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.charts.AxisCrosses;
import org.apache.poi.ss.usermodel.charts.AxisPosition;
import org.apache.poi.ss.usermodel.charts.ChartAxis;
import org.apache.poi.ss.usermodel.charts.ChartDataSource;
import org.apache.poi.ss.usermodel.charts.ValueAxis;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.devgateway.toolkit.web.excelcharts.util.CustomChartDataFactory;
import org.devgateway.toolkit.web.excelcharts.util.CustomChartDataFactoryDefault;
import java.util.ArrayList;
import java.util.List;
/**
* @author idobre
* @since 8/16/16
*
* Class that returns Workbook with a chart based on categories/values
* provided.
*
* Examples of usage:
*
* private static final List<?> categories = Arrays.asList( "cat 1", "cat
* 2", "cat 3" );
*
* private static final List<List<? extends Number>> values =
* Arrays.asList( Arrays.asList(5, 7, 10), Arrays.asList(20, 12, 10) );
*
* final ExcelChart excelChart = new ExcelChartDefault("line chart",
* ChartType.line, categories, values); final Workbook workbook =
* excelChart.createWorkbook();
*
* OR
*
* final ExcelChart excelChart = new ExcelChartDefault("stacked chart",
* ChartType.stackedcol, categories, values); final Workbook workbook =
* excelChart.createWorkbook();
*/
public class ExcelChartDefault implements ExcelChart {
private final ChartType type;
private final String title;
private final List<?> categories;
private final List<List<? extends Number>> values;
private final Workbook workbook;
private final List<String> seriesTitle;
private static final int COLUMNWIDTH = 3500;
public ExcelChartDefault(final String title, final ChartType type, final List<?> categories,
final List<List<? extends Number>> values) {
for (List<? extends Number> value : values) {
if (categories.size() != value.size()) {
throw new IllegalArgumentException("categories and value size should match!");
}
}
this.title = title;
this.type = type;
this.categories = categories;
this.values = values;
this.workbook = new XSSFWorkbook();
this.seriesTitle = new ArrayList<>();
}
@Override
public Workbook createWorkbook() {
final ExcelChartSheet excelChartSheet = new ExcelChartSheetDefault(workbook, type.toString());
final Chart chart = excelChartSheet.createChartAndLegend();
addCategories(excelChartSheet);
addValues(excelChartSheet);
final CustomChartDataFactory customChartDataFactory = new CustomChartDataFactoryDefault();
final CustomChartData chartData = customChartDataFactory.createChartData(type, title);
final ChartDataSource<?> categoryDataSource = excelChartSheet.getCategoryChartDataSource();
final List<ChartDataSource<Number>> valuesDataSource = excelChartSheet.getValuesChartDataSource();
for (int i = 0; i < valuesDataSource.size(); i++) {
final ChartDataSource<Number> valueDataSource = valuesDataSource.get(i);
if (seriesTitle.isEmpty()) {
chartData.addSeries(categoryDataSource, valueDataSource);
} else {
chartData.addSeries(seriesTitle.get(i), categoryDataSource, valueDataSource);
}
}
// we don't have any axis for a pie chart
if (type.equals(ChartType.pie)) {
chart.plot(chartData);
} else {
// Use a category axis for the bottom axis.
final ChartAxis bottomAxis = chart.getChartAxisFactory().createCategoryAxis(AxisPosition.BOTTOM);
final ValueAxis leftAxis = chart.getChartAxisFactory().createValueAxis(AxisPosition.LEFT);
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
chart.plot(chartData, bottomAxis, leftAxis);
}
return workbook;
}
@Override
public void configureSeriesTitle(final List<String> seriesTitle) {
if (values.size() != seriesTitle.size()) {
throw new IllegalArgumentException("seriesTitle and values size should match!");
}
this.seriesTitle.addAll(seriesTitle);
}
/**
* Add a row with the categories.
*/
private void addCategories(final ExcelChartSheet excelChartSheet) {
final Row row = excelChartSheet.createRow();
if (categories.isEmpty()) {
excelChartSheet.writeCell("No data", row, 0);
return;
}
int coll = 0;
for (Object category : categories) {
excelChartSheet.writeCell(category, row, coll);
excelChartSheet.setColumnWidth(coll, COLUMNWIDTH);
coll++;
}
}
/**
* Add one or multiple rows with the values.
*/
private void addValues(final ExcelChartSheet excelChartSheet) {
if (values.isEmpty()) {
final Row row = excelChartSheet.createRow();
excelChartSheet.writeCell(0, row, 0);
return;
}
for (List<? extends Number> value : values) {
final Row row = excelChartSheet.createRow();
int coll = 0;
for (Number val : value) {
excelChartSheet.writeCell(val, row, coll++);
}
}
}
}