到目前为止,我可以使用 Java 中的 Apache POI 使用数据透视表引用创建数据透视图,这是一个饼图。但现在我想根据我的需要更改饼图上每个元素的颜色。我尝试在创建图表后添加数据系列但不起作用。谁能指导一下我吗
我尝试使用 Apache POI 的 OOXML 添加数据系列,但它不起作用。 我提到的是迄今为止我创建的代码及其输出。
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DataConsolidateFunction;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.AreaReference;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
import org.apache.poi.xddf.usermodel.chart.ChartTypes;
import org.apache.poi.xddf.usermodel.chart.LegendPosition;
import org.apache.poi.xddf.usermodel.chart.XDDFChartData;
import org.apache.poi.xddf.usermodel.chart.XDDFChartLegend;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFDataSourcesFactory;
import org.apache.poi.xddf.usermodel.chart.XDDFNumericalDataSource;
import org.apache.poi.xddf.usermodel.chart.XDDFPieChartData;
import org.apache.poi.xssf.usermodel.XSSFChart;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPivotTable;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos;
import org.openxmlformats.schemas.drawingml.x2006.main.STPresetColorVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STRectAlignment;
import org.openxmlformats.schemas.drawingml.x2006.main.STSchemeColorVal;
import org.openxmlformats.schemas.drawingml.x2006.main.STSystemColorVal;
public class PivotPieChart {
public static void main(String[] args) throws FileNotFoundException, IOException {
pieChart();
}
public static void pieChart() throws FileNotFoundException, IOException {
try (XSSFWorkbook wb = new XSSFWorkbook()) {
XSSFSheet sheet = wb.createSheet("PivotPieChart");
// Create row and put some cells in it. Rows and cells are 0 based.
Row row = sheet.createRow((short) 0);
Cell cell = row.createCell((short) 0);
cell.setCellValue("Letters");
cell = row.createCell((short) 1);
cell.setCellValue("Countries");
cell = row.createCell((short) 2);
cell.setCellValue("Data");
row = sheet.createRow((short) 1);
cell = row.createCell((short) 0);
cell.setCellValue("A");
cell = row.createCell((short) 1);
cell.setCellValue("Russia");
cell = row.createCell((short) 2);
cell.setCellValue(17098242);
row = sheet.createRow((short) 2);
cell = row.createCell((short) 0);
cell.setCellValue("A");
cell = row.createCell((short) 1);
cell.setCellValue("Canada");
cell = row.createCell((short) 2);
cell.setCellValue(9984670);
row = sheet.createRow((short) 3);
cell = row.createCell((short) 0);
cell.setCellValue("A");
cell = row.createCell((short) 1);
cell.setCellValue("USA");
cell = row.createCell((short) 2);
cell.setCellValue(9826675);
row = sheet.createRow((short) 4);
cell = row.createCell((short) 0);
cell.setCellValue("B");
cell = row.createCell((short) 1);
cell.setCellValue("Australia");
cell = row.createCell((short) 2);
cell.setCellValue(9596961);
row = sheet.createRow((short) 5);
cell = row.createCell((short) 0);
cell.setCellValue("B");
cell = row.createCell((short) 1);
cell.setCellValue("China");
cell = row.createCell((short) 2);
cell.setCellValue(8514877);
row = sheet.createRow((short) 6);
cell = row.createCell((short) 0);
cell.setCellValue("C");
cell = row.createCell((short) 1);
cell.setCellValue("Brazil");
cell = row.createCell((short) 2);
cell.setCellValue(7741220);
row = sheet.createRow((short) 7);
cell = row.createCell((short) 0);
cell.setCellValue("D");
cell = row.createCell((short) 1);
cell.setCellValue("India");
cell = row.createCell((short) 2);
cell.setCellValue(3287263);
AreaReference sourceDataAreaRef = new AreaReference("A1:C7", SpreadsheetVersion.EXCEL2007);
XSSFPivotTable pivotTable = sheet.createPivotTable(sourceDataAreaRef, new CellReference("A11"));
pivotTable.addRowLabel(0);
pivotTable.addRowLabel(1);
pivotTable.addColumnLabel(DataConsolidateFunction.SUM, 2);
XSSFSheet pivotSheet = (XSSFSheet)pivotTable.getParentSheet();
XSSFDrawing drawing = pivotSheet.createDrawingPatriarch();
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 4, 2, 10, 20);
XSSFChart chart = drawing.createChart(anchor);
String pivotTableName = pivotTable.getCTPivotTableDefinition().getName();
String qualifiedPivotSourceName = "[" + null + "]" + pivotSheet.getSheetName() + "!" + pivotTableName;
chart.getCTChartSpace().addNewPivotSource().setName(qualifiedPivotSourceName);
XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
chart.getCTChart ().getPlotArea ().getPieChartArray (0).addNewVaryColors().setVal(true);
chart.getCTChart ().getPlotArea ().getPieChartArray (0).addNewDLbls().addNewShowSerName().setVal(true);
// Write output to an excel file
try (FileOutputStream fileOut = new FileOutputStream("PivotPieChart.xlsx")) {
wb.write(fileOut);
}
}
}
}
上面提到的输出饼图是自动获取数据的。但我想设置自己的颜色,如下面的输出所示。
有人可以帮助我吗?谢谢!
您的代码似乎采用了Is it possible to create Pivot Chart with source data as Pivot Table using Apache POI?但更改为创建饼图而不是条形图。
但是你太简单化了。
首先,
qualifiedPivotSourceName
实际上应该是工作簿文件的名称,而不是“null”。
您确实需要类别数据和值数据以及一系列数据。否则不存在数据点,因此无法对数据点进行自定义着色。
您应该拥有真实的类别和值数据,而不仅仅是虚拟数据,以支持不提供数据透视图的电子表格应用程序。
所以我建议在您的代码中添加以下内容:
...
String workbookName = "PivotPieChart.xlsx";
...
XSSFChart chart = drawing.createChart(anchor);
String pivotTableName = pivotTable.getCTPivotTableDefinition().getName();
String qualifiedPivotSourceName = "[" + workbookName + "]" + pivotSheet.getSheetName() + "!" + pivotTableName;
chart.getCTChartSpace().addNewPivotSource().setName(qualifiedPivotSourceName);
XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
//dummy categories and values
// int rows = sourceDataAreaRef.getLastCell().getRow() - sourceDataAreaRef.getFirstCell().getRow();
// XDDFDataSource<String> categories = XDDFDataSourcesFactory.fromArray(new String[rows]);
// XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromArray(new Double[rows]);
//real categories and values for spreadsheet applications which are not providing pivot charts
XDDFDataSource<String> categories = XDDFDataSourcesFactory.fromStringCellRange(pivotSheet,
new CellRangeAddress(sourceDataAreaRef.getFirstCell().getRow() + 1, sourceDataAreaRef.getLastCell().getRow(),
sourceDataAreaRef.getFirstCell().getCol(), sourceDataAreaRef.getFirstCell().getCol()));
XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(pivotSheet,
new CellRangeAddress(sourceDataAreaRef.getFirstCell().getRow() + 1, sourceDataAreaRef.getLastCell().getRow(),
sourceDataAreaRef.getLastCell().getCol(), sourceDataAreaRef.getLastCell().getCol()));
//series
XDDFChartData.Series series = data.addSeries(categories, values);
//plot data
chart.plot(data);
//data point colors
int pointCount = series.getCategoryData().getPointCount();
for (int p = 0; p < pointCount; p++) {
chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDPt().addNewIdx().setVal(p);
chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).getDPtArray(p)
.addNewSpPr().addNewSolidFill().addNewSrgbClr().setVal(
org.apache.poi.xssf.usermodel.DefaultIndexedColorMap.getDefaultRGB(p+10));
}
...
// Write output to an excel file
try (FileOutputStream fileOut = new FileOutputStream("./" + workbookName)) {
wb.write(fileOut);
}
...
//data point colors
之后的代码将从org.apache.poi.xssf.usermodel.DefaultIndexedColorMap
获取的自定义颜色设置到每个数据点。您还可以为每种自定义颜色提供一个集合或一个 3 项字节数组。
示例:
...
// some rgb colors to choose
byte[][] colors = new byte[][] {
new byte[] {127,(byte)255, 127},
new byte[] {(byte)200, (byte)200, (byte)200},
new byte[] {(byte)255,(byte)255, 127},
new byte[] {(byte)255, 127, 127},
new byte[] {(byte)255, 0, 0},
new byte[] {0, (byte)255, 0},
new byte[] {0, 0, (byte)255},
new byte[] {80, 80, 80}
};
...