仅通过POI的话,只能实现折线图和散点图
但POI还支持Open Xml,通过这种方式可以实现很多类型的chart
效果参考:
POI版本
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.17</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>ooxml-schemas</artifactId>
<version>1.3</version>
</dependency>
代码
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.poi.ss.usermodel.charts.AxisCrosses;
import org.apache.poi.ss.usermodel.charts.AxisPosition;
import org.apache.poi.ss.usermodel.charts.ChartDataSource;
import org.apache.poi.ss.usermodel.charts.DataSources;
import org.apache.poi.ss.usermodel.charts.LegendPosition;
import org.apache.poi.ss.usermodel.charts.LineChartSeries;
import org.apache.poi.ss.util.CellRangeAddress;
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.XSSFSheet;
import org.apache.poi.xssf.usermodel.charts.XSSFChartAxis;
import org.apache.poi.xssf.usermodel.charts.XSSFChartLegend;
import org.apache.poi.xssf.usermodel.charts.XSSFLineChartData;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBoolean;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDispBlanksAs;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDispBlanksAs;
public class XSSFUtils {
public static void test(XSSFSheet sheet) {
Map<String, Object> params = new HashMap<String, Object> ();
// 图表位置(B36左上角:AA53左上角)
int[] position = new int[] {getColumnIndexByAddress("B"), 35, getColumnIndexByAddress("AA"), 52};
// x轴坐标区域(B60:B90)
int[] xAxisRange = new int[] {59, 89, getColumnIndexByAddress("B"), getColumnIndexByAddress("B")};
// 每个系列的数据(D60:D90、J60:J90、P60:P90)
// 每个系列的标题(D59、J59、P59)
List<Integer[]> seriesDataRangeList = new ArrayList<Integer[]>();
seriesDataRangeList .add(new Integer[] {59, 89, getColumnIndexByAddress("D"), getColumnIndexByAddress("D"),
58, getColumnIndexByAddress("D")});
seriesDataRangeList .add(new Integer[] {59, 89, getColumnIndexByAddress("J"), getColumnIndexByAddress("J"),
58, getColumnIndexByAddress("J")});
seriesDataRangeList .add(new Integer[] {59, 89, getColumnIndexByAddress("P"), getColumnIndexByAddress("P"),
58, getColumnIndexByAddress("P")});
params.put("chartPosition", position);
params.put("xAxisRange", xAxisRange);
params.put("seriesDataRangeList ", seriesDataRangeList );
createLineChart(sheet, params);
}
/**
* create line chart
* @param sheet
* @param params
* chartPosition int[]{startRow, endRow, startCol, endCol}
* xAxisRange int[]{startRow, endRow, startCol, endCol}
* seriesDataRangeList List<Integer[]>{startRow, endRow, startCol, endCol, titleRow, titleCol}
*/
private static void createLineChart(XSSFSheet sheet, Map<String, Object> params) {
int[] position = (int[]) params.get("chartPosition");
int[] xAxisRange = (int[]) params.get("xAxisRange");
List<Integer[]> seriesDataRangeList = (List<Integer[]>) params.get("seriesDataRangeList ");
XSSFDrawing drawing = sheet.createDrawingPatriarch();
XSSFClientAnchor anchor =
drawing.createAnchor(0, 0, 0, 0, position[0], position[1], position[2], position[3]);
XSSFChart chart = drawing.createChart(anchor);
XSSFChartLegend legned = chart.getOrCreateLegend();
legned.setPosition(LegendPosition.TOP);
// set blank values as gaps
CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
disp.setVal(STDispBlanksAs.GAP);
chart.getCTChart().setDispBlanksAs(disp);
XSSFLineChartData chartData = chart.getChartDataFactory().createLineChartData();
XSSFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
XSSFChartAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
bottomAxis.setCrosses(AxisCrosses.AUTO_ZERO);
bottomAxis.setNumberFormat("yyyy/m/d");
leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
leftAxis.setMinimum(0);
// 设置x轴坐标区域(B60:B90)
ChartDataSource<String> xAxisData =
DataSources.fromStringCellRange(sheet,
new CellRangeAddress(xAxisRange[0], xAxisRange[1], xAxisRange[2], xAxisRange[3]));
// 设置数据区域,即每个系列的数据(D60:D90、J60:J90、P60:P90)
for (Integer[] seriesDataRange : seriesDataRangeList ) {
ChartDataSource<Number> yAxisData =
DataSources.fromNumericCellRange(sheet,
new CellRangeAddress(seriesDataRange[0], seriesDataRange[1], seriesDataRange[2], seriesDataRange[3]));
LineChartSeries series = chartData.addSeries(xAxisData, yAxisData);
// 设置每个系列的标题(D59、J59、P59)
series.setTitle(sheet.getRow(seriesDataRange[4]).getCell(seriesDataRange[5]).getStringCellValue());
}
chart.plot(chartData, bottomAxis, leftAxis);
// unsmooth series(好像必须写在polt方法之后)
CTPlotArea plotArea = chart.getCTChart().getPlotArea();
for (CTLineChart ch : plotArea.getLineChartList()) {
for (CTLineSer ser : ch.getSerList()) {
CTBoolean ctBool = CTBoolean.Factory.newInstance();
ctBool.setVal(false);
ser.setSmooth(ctBool);
}
}
}
/**
* get column index by column address
*/
public static int getColumnIndexByAddress(String columnAddress) {
int colNum = 0;
for (int i = 0; i < columnAddress.length(); i++) {
char ch = columnAddress.charAt(columnAddress.length() - 1 - i);
colNum += (ch - 'A' + 1) * Math.pow(26, i);
}
return colNum - 1;
}
}