java使用poi绘制折线图和饼图(用数据绘制和使用excel生成的表格数据)
import com.gideon.entity.ChartPosition;
import com.gideon.entity.LineChart;
import com.gideon.entity.PieChart;
import org.apache.poi.xddf.usermodel.chart.*;
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.openxmlformats.schemas.drawingml.x2006.chart.CTDLbls;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDLblPos;
import java.util.Arrays;
import java.util.List;
/**
* @author GideonYeung
* @date 2020/12/3 17:13
*/
public class ChartUtils {
private static XSSFChart createDrawingPatriarch(XSSFSheet sheet, ChartPosition chartPosition, String chartTitle) {
//创建一个画布
XSSFDrawing drawing = sheet.createDrawingPatriarch();
//前偏移量四个默认0
XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, chartPosition.getCol1(), chartPosition.getRow1(), chartPosition.getCol2(), chartPosition.getRow2());
//创建一个chart对象
XSSFChart chart = drawing.createChart(anchor);
//标题
chart.setTitleText(chartTitle);
//标题是否覆盖图表
chart.setTitleOverlay(false);
return chart;
}
/**
* 创建饼图
*
* @param sheet 图表
* @see 饼图数据的封装
* @see 饼图的坐标位置
*/
public static void createPie(XSSFSheet sheet, ChartPosition chartPosition, PieChart pieChart) {
String titleName = pieChart.getTitleName();
List<String> titleList = pieChart.getTitleList();
List<Integer> dataList = pieChart.getDataList();
XSSFChart chart = createDrawingPatriarch(sheet, chartPosition, titleName);
//图例位置
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.LEFT);
//CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
//分类轴标数据,
XDDFDataSource<String> countries = XDDFDataSourcesFactory.fromArray(titleList.toArray(new String[]{}));
XDDFNumericalDataSource<Integer> values = XDDFDataSourcesFactory.fromArray(dataList.toArray(new Integer[]{}));
XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
//设置为可变颜色
data.setVaryColors(true);
//图表加载数据
data.addSeries(countries, values);
//绘制
chart.plot(data);
CTDLbls ctdLbls = chart.getCTChart().getPlotArea().getPieChartArray(0).getSerArray(0).addNewDLbls();
ctdLbls.addNewShowVal().setVal(false);
ctdLbls.addNewShowLegendKey().setVal(false);
//类别名称
ctdLbls.addNewShowCatName().setVal(true);
//百分比
ctdLbls.addNewShowSerName().setVal(false);
ctdLbls.addNewShowPercent().setVal(true);
//引导线
ctdLbls.addNewShowLeaderLines().setVal(true);
//分隔符为分行符
ctdLbls.setSeparator("\n");
//数据标签内
ctdLbls.addNewDLblPos().setVal(STDLblPos.Enum.forString("inEnd"));
}
/**
* 创建折线图
*
* @param sheet 图表
* @see 饼图数据的封装
* @see 饼图的坐标位置
*/
public static void createLine(XSSFSheet sheet, ChartPosition chartPosition, LineChart lineChart) {
List<Object> xAxisList = lineChart.getXAxisList();
List<String> chartTitleList = lineChart.getTitleList();
List<List<Integer>> chartDataList = lineChart.getDataList();
String chartTitle = lineChart.getChartTitle();
XSSFChart chart = createDrawingPatriarch(sheet, chartPosition, chartTitle);
//图例位置
XDDFChartLegend legend = chart.getOrAddLegend();
legend.setPosition(LegendPosition.TOP);
//分类轴标(X轴),标题位置
XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
//值(Y轴)轴,标题位置
XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
//LINE:折线图,
XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromArray(Arrays.copyOf(xAxisList.toArray(), xAxisList.toArray().length, String[].class));
for (int i = 0; i < chartDataList.size(); i++) {
List<Integer> floats = chartDataList.get(i);
XDDFNumericalDataSource<Integer> dataSource = XDDFDataSourcesFactory.fromArray(floats.toArray(new Integer[]{}));
//图表加载数据,折线
XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(countries, dataSource);
series.setTitle(chartTitleList.get(i), null);
//直线
series.setSmooth(false);
//设置标记大小
series.setMarkerSize((short) 6);
}
//绘制
chart.plot(data);
if (chartDataList.size() == 1) {
chart.getCTChart().getPlotArea().getLineChartArray(0).addNewVaryColors().setVal(false);
}
}
/**
* 根据列名获取列值(例如getColumnIndexByAddress("A"),返回1代表第一列),具体打开可以看到excel字母
*/
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;
}