19 package org.sleuthkit.autopsy.report.modules.datasourcesummaryexport;
21 import java.lang.reflect.Constructor;
22 import java.lang.reflect.InvocationTargetException;
23 import java.util.Arrays;
24 import java.util.List;
25 import org.apache.poi.ss.usermodel.Sheet;
26 import org.apache.poi.ss.util.CellRangeAddress;
27 import org.apache.poi.xddf.usermodel.chart.LegendPosition;
28 import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
29 import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
30 import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
31 import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
32 import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
33 import org.apache.poi.xssf.usermodel.XSSFChart;
34 import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
35 import org.apache.poi.xssf.usermodel.XSSFDrawing;
36 import org.apache.poi.xssf.usermodel.XSSFSheet;
37 import org.openxmlformats.schemas.drawingml.x2006.chart.CTPieChart;
48 class PieChartExport
implements ExcelItemExportable, ExcelSheetExport {
50 private static final int DEFAULT_ROW_SIZE = 20;
51 private static final int DEFAULT_COL_SIZE = 10;
52 private static final int DEFAULT_ROW_PADDING = 1;
53 private static final int DEFAULT_COL_OFFSET = 1;
55 private final ExcelTableExport<PieChartItem, ? extends CellModel> tableExport;
56 private final int colOffset;
57 private final int rowPadding;
58 private final int colSize;
59 private final int rowSize;
60 private final String chartTitle;
61 private final String sheetName;
73 PieChartExport(String keyColumnHeader,
74 String valueColumnHeader, String valueFormatString,
76 List<PieChartItem> slices) {
77 this(keyColumnHeader, valueColumnHeader, valueFormatString, chartTitle, chartTitle, slices,
78 DEFAULT_COL_OFFSET, DEFAULT_ROW_PADDING, DEFAULT_COL_SIZE, DEFAULT_ROW_SIZE);
97 PieChartExport(String keyColumnHeader,
98 String valueColumnHeader, String valueFormatString,
99 String chartTitle, String sheetName,
100 List<PieChartItem> slices,
101 int colOffset,
int rowPadding,
int colSize,
int rowSize) {
103 this.tableExport =
new ExcelTableExport<>(chartTitle,
105 new ColumnModel<>(keyColumnHeader, (slice) ->
new DefaultCellModel<>(slice.getLabel())),
106 new ColumnModel<>(valueColumnHeader, (slice) ->
new DefaultCellModel<>(slice.getValue(), null, valueFormatString))
109 this.colOffset = colOffset;
110 this.rowPadding = rowPadding;
111 this.colSize = colSize;
112 this.rowSize = rowSize;
113 this.chartTitle = chartTitle;
114 this.sheetName = sheetName;
118 public String getSheetName() {
123 public void renderSheet(Sheet sheet, ExcelExport.WorksheetEnv env) throws ExcelExport.ExcelExportException {
124 write(sheet, 0, 0, env);
128 public ItemDimensions write(Sheet sheet,
int rowStart,
int colStart, ExcelExport.WorksheetEnv env) throws ExcelExportException {
129 if (!(sheet instanceof XSSFSheet)) {
130 throw new ExcelExportException(
"Sheet must be an XSSFSheet in order to write.");
133 XSSFSheet xssfSheet = (XSSFSheet) sheet;
136 ItemDimensions tableDimensions = tableExport.write(xssfSheet, rowStart + rowPadding, colStart, env);
138 XSSFDrawing drawing = xssfSheet.createDrawingPatriarch();
140 int chartColStart = colStart + 2 + colOffset;
143 XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, chartColStart, rowStart + rowPadding, chartColStart + colSize + 1, rowStart + rowSize + 1);
145 XSSFChart chart = drawing.createChart(anchor);
146 chart.setTitleText(chartTitle);
147 chart.setTitleOverlay(
false);
148 XDDFChartLegend legend = chart.getOrAddLegend();
149 legend.setPosition(LegendPosition.RIGHT);
152 XDDFDataSource<String> cat = XDDFDataSourcesFactory.fromStringCellRange(xssfSheet,
153 new CellRangeAddress(tableDimensions.getRowStart() + 1, tableDimensions.getRowEnd(),
154 tableDimensions.getColStart(), tableDimensions.getColStart()));
156 XDDFNumericalDataSource<Double> val = XDDFDataSourcesFactory.fromNumericCellRange(xssfSheet,
157 new CellRangeAddress(tableDimensions.getRowStart() + 1, tableDimensions.getRowEnd(),
158 tableDimensions.getColStart() + 1, tableDimensions.getColStart() + 1));
168 XDDFPieChartData data;
170 Constructor<XDDFPieChartData> constructor = XDDFPieChartData.class.getConstructor(CTPieChart.class);
171 constructor.setAccessible(
true);
172 data = constructor.newInstance(chart.getCTChart().getPlotArea().addNewPieChart());
173 }
catch (NoSuchMethodException | InvocationTargetException | InstantiationException | IllegalAccessException | IllegalArgumentException ex) {
174 throw new ExcelExportException(
"Error while instantiating chart data.", ex);
177 data.setVaryColors(
true);
178 data.addSeries(cat, val);
181 if (!chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).isSetDLbls()) {
182 chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();
185 chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowVal().setVal(
true);
186 chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowSerName().setVal(
false);
187 chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowCatName().setVal(
true);
188 chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowPercent().setVal(
true);
189 chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDLbls().addNewShowLegendKey().setVal(
false);
193 return new ItemDimensions(rowStart, colStart, Math.max(tableDimensions.getRowEnd(), rowStart + rowSize) + rowPadding, chartColStart + colSize);