java使用poi绘制折线图和饼图(用数据绘制和使用excel生成的表格数据)

时间:2025-03-31 08:12:49
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; }