POI导出excel生成图表(折线图、饼图、柱状图)

近期做的需求中有个统计页面,页面中要求导出统计数据时连同图表一起导出到excel中,项目中用到的是阿里的easyExcel,查阅资料后发现easyExcel中没有很好的画图表的解决方案。POI到是提供了不错的解决方案,代码如下:

  • 数据查询
/**
     * 按用户统计数据导出
     *
     * @param condition
     * @return
     */
    public ResultResponse<String> exportExcelByUser(EventAlarmStaticsCondition condition) {
        // 查询数据
        ResultResponse<List<JSONObject>> response = eventAlarmStaticsByUser(condition);
        if(response.checkFailed() || CollectionUtils.isEmpty(response.getData())){
            return ResultResponse.success("");
        }

        List<String> heads = new ArrayList<>();
        // 获取要导出的表头数据
        List<EventTypeEntity> typeList = getEventTypeEntityList();
        List<String> titles = typeList.stream().map(EventTypeEntity::getEventName).collect(Collectors.toList());
        heads.add(Constants.NAME);
        heads.add(Constants.TOTAL_EVENT);
        heads.add(Constants.AVG_TIME);
        heads.addAll(titles);

        List<JSONObject> objectList = response.getData();
        // 柱状图y轴事件总数数据
        List<Double> lineYDataList = new ArrayList<>();
        // 柱状图y轴平均处理时长数据
        List<Double> timeYDataList = new ArrayList<>();
        // 填充折线图y轴数据
        for (JSONObject jsonObject : objectList) {
            lineYDataList.add(jsonObject.getDoubleValue(Constants.TOTAL_COUNT));
            timeYDataList.add(jsonObject.getDoubleValue(Constants.TOTAL_AVG_TIME));
        }

        // 创建wb并绘制折线图、饼图、柱状图
        XSSFWorkbook wb = new XSSFWorkbook();
        XSSFSheet sheet = wb.createSheet(ExportFileConstant.eventStaticsNamePrefix);
        drawSheetTable(wb, sheet, heads, response.getData(), Constants.USER_NAME);

        // 柱状图
        ExcelUtils.createBarChart(sheet, lineYDataList, ExportFileConstant.staticsCount, 1, objectList.size(), 0, 0, 4, 30, 0, 10 );
        ExcelUtils.createBarChart(sheet, timeYDataList, ExportFileConstant.staticsEfficiency, 1, objectList.size(), 0, 0, 4, 30, 11, 22 );
        // 上传文件
        String url = upload(wb, ExportFileConstant.eventStaticsNamePrefix);
        return ResultResponse.successData(url);
    }
    
        /**
     * 上传文件
     *
     * @param wb
     * @param fileName
     * @return
     */
    private String upload (XSSFWorkbook wb, String fileName){
        String filePath = fileConfig.getCreatFilePath() + fileName + ExcelTypeEnum.XLSX.getValue();
        try {
            DownloadUtil.createFolderIfNotExists(fileConfig.getCreatFilePath());
            FileOutputStream outputStream = new FileOutputStream(filePath);
            wb.write(outputStream);
            outputStream.close();
        } catch (Exception e) {
            log.error("Failed to upload data,exception:{}", e);
            return null;
        }
        //上传到s3
        return s3Service.fileUpload(filePath, fileName + ExcelTypeEnum.XLSX.getValue(), S3Tag.shortTerm);
    }
  • 向sheet中写入数据

/**
     * sheet数据
     *
     * @param sheet
     * @param titleList
     * @param dataList
     * @return
     */
    private boolean drawSheetTable(XSSFWorkbook wb, XSSFSheet sheet, List<String> titleList, List<JSONObject> dataList, String groupType) {
        boolean result = true;

        // 设置样式以及字体样式
        XSSFCellStyle headerStyle = ExcelUtils.createHeadCellStyle(wb);
        XSSFCellStyle contentStyle = ExcelUtils.createContentCellStyle(wb);
        XSSFCellStyle intStyle = ExcelUtils.createContentNumericalCellStyle(wb,"#,##0");

        // 获取事件类型数据
        List<EventTypeEntity> typeList = getEventTypeEntityList();
        List<Integer> countList = new ArrayList<>();
        for (EventTypeEntity type : typeList) {
            String eventType = Constants.EVENT_TYPE + type.getEventType();
            int count = 0;
            for (JSONObject jsonObject : dataList) {
                count += jsonObject.getIntValue(eventType);
            }
            countList.add(count);
        }
        countList.add(dataList.stream().mapToInt(jsonObject -> jsonObject.getIntValue(Constants.TOTAL_COUNT)).sum());
        countList.add(dataList.stream().mapToInt(jsonObject -> jsonObject.getIntValue(Constants.TOTAL_AVG_TIME)).sum());

        // 根据数据创建excel第一行标题行
        XSSFRow row0 = sheet.createRow(0);
        for (int i = 0; i < titleList.size(); i++) {
            // 设置标题
            row0.createCell(i).setCellValue(titleList.get(i));
            // 设置标题行样式
            row0.getCell(i).setCellStyle(headerStyle);
        }
        // 填充数据
        String period = Constants.PERIOD.equals(groupType) ? Constants.PERIOD : Constants.USER_NAME;
        for (int k = 0; k < dataList.size(); k++) {
            // 获取每一项的数据
            JSONObject data = dataList.get(k);
            // 设置每一行的字段标题和数据
            XSSFRow row = sheet.createRow(k + 1);
            // 标题
            row.createCell(0).setCellValue(data.getString(period));
            sheet.getRow(k + 1).getCell(0).setCellStyle(contentStyle);
            row.createCell(1).setCellValue(data.getString(Constants.TOTAL_COUNT));
            sheet.getRow(k + 1).getCell(1).setCellStyle(contentStyle);
            // 处理数字过长转成科学计数法问题
            BigDecimal avgTimeDecimal = new BigDecimal(data.getString(Constants.TOTAL_AVG_TIME));
            row.createCell(2).setCellValue(avgTimeDecimal.toPlainString());
            sheet.getRow(k + 1).getCell(2).setCellStyle(contentStyle);
            // 设置左边字段样式
            for (int j = 0; j < typeList.size(); j++) {
                EventTypeEntity entity = typeList.get(j);
                String eventTYpeData = data.getString(Constants.EVENT_TYPE + entity.getEventType());
                row.createCell(j + 3).setCellValue(eventTYpeData);
                // 设置数据样式
                sheet.getRow(k + 1).getCell(j + 3).setCellStyle(intStyle);
            }
        }

        // 合计
        XSSFRow endRow = sheet.createRow(dataList.size() + 1);
        endRow.createCell(0).setCellValue(Constants.TOTAL);
        endRow.getCell(0).setCellStyle(contentStyle);
        // 事件总数
        endRow.createCell(1).setCellValue(countList.get(countList.size() - 2));
        endRow.getCell(1).setCellStyle(contentStyle);
        // 处理科学计数法问题
        BigDecimal bigDecimal = new BigDecimal(countList.get(countList.size() - 1));
        endRow.createCell(2).setCellValue(bigDecimal.toPlainString());
        endRow.getCell(2).setCellStyle(contentStyle);
        for (int i = 3; i <= countList.size(); i++) {
            endRow.createCell(i).setCellValue(countList.get(i - 3));
            endRow.getCell(i).setCellStyle(contentStyle);
        }
        return result;
    }
  • 工具类
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.PresetColor;
import org.apache.poi.xddf.usermodel.XDDFColor;
import org.apache.poi.xddf.usermodel.XDDFSolidFillProperties;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;

import java.util.List;

public class ExcelUtils {
    /**
     * 创建表头样式
     * @param wb
     * @return
     */
    public static XSSFCellStyle createHeadCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setFillForegroundColor(IndexedColors.BLUE_GREY.getIndex());//背景颜色
        cellStyle.setAlignment(HorizontalAlignment.CENTER); //水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //垂直对齐
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setBottomBorderColor(IndexedColors.BLACK.index);
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        XSSFFont headerFont = wb.createFont(); // 创建字体样式
        headerFont.setBold(true); //字体加粗
        headerFont.setFontName("宋体"); // 设置字体类型
        headerFont.setFontHeightInPoints((short) 12); // 设置字体大小
        cellStyle.setFont(headerFont); // 为标题样式设置字体样式

        return cellStyle;
    }
    /**
     * 创建标题样式
     * @param wb
     * @return
     */
    public static XSSFCellStyle createTitleCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setAlignment(HorizontalAlignment.CENTER);//水平居中
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);//垂直对齐
        cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        cellStyle.setFillForegroundColor(IndexedColors.WHITE1.getIndex());//背景颜色

        XSSFFont headerFont1 = wb.createFont(); // 创建字体样式
        headerFont1.setBold(true); //字体加粗
        headerFont1.setFontName("宋体"); // 设置字体类型
        headerFont1.setFontHeightInPoints((short) 16); // 设置字体大小
        cellStyle.setFont(headerFont1); // 为标题样式设置字体样式

        return cellStyle;
    }
    /**
     * 创建内容样式
     * @param wb
     * @return
     */
    public static XSSFCellStyle createRemarkCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.JUSTIFY);// 两边对齐
        cellStyle.setAlignment(HorizontalAlignment.LEFT);// 居左
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        // 生成12号字体
        XSSFFont font = wb.createFont();
        font.setColor((short)8);
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);

        return cellStyle;
    }
    /**
     * 创建内容样式
     * @param wb
     * @return
     */
    public static XSSFCellStyle createContentCellStyle(XSSFWorkbook wb) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        // 生成12号字体
        XSSFFont font = wb.createFont();
        font.setColor((short)8);
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);

        return cellStyle;
    }
    /**
     * 创建内容样式
     * @param wb
     * @return
     */
    public static XSSFCellStyle createContentNumericalCellStyle(XSSFWorkbook wb,String format) {
        XSSFCellStyle cellStyle = wb.createCellStyle();
        XSSFDataFormat dataFormat = wb.createDataFormat();
        cellStyle.setDataFormat(dataFormat.getFormat(format));
        cellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 垂直居中
        cellStyle.setAlignment(HorizontalAlignment.CENTER);// 水平居中
        cellStyle.setWrapText(true);// 设置自动换行
        cellStyle.setBorderBottom(BorderStyle.THIN); //下边框
        cellStyle.setBorderLeft(BorderStyle.THIN); //左边框
        cellStyle.setBorderRight(BorderStyle.THIN); //右边框
        cellStyle.setBorderTop(BorderStyle.THIN); //上边框

        // 生成12号字体
        XSSFFont font = wb.createFont();
        font.setColor((short)8);
        font.setFontHeightInPoints((short) 12);
        cellStyle.setFont(font);

        return cellStyle;
    }

    /**
     * 折线图
     *
     * @param sheet sheet
     * @param chartTitle 折线图标题
     * @param lineName 折线名称
     * @param xName x轴名称
     * @param yName y轴名称
     * @param firstRow 开始行
     * @param dataEndRow 结束行
     * @param startCol 开始列
     * @param xAxisCol x轴列
     * @param valueCol y轴列
     */
    public static void createSheetLineChark(XSSFSheet sheet, String chartTitle,String lineName,String xName,String yName, int firstRow, int dataEndRow, int startCol, int xAxisCol, int valueCol) {
        //创建一个画布
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        //前四个默认0,[0,4]:从0列4行开始;[7,20]:宽度7个单元格,20向下扩展到20行
        //默认宽度(14-8)*12
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, startCol, dataEndRow + 4, startCol + 9, dataEndRow + 28);
        //创建一个chart对象
        XSSFChart chart = drawing.createChart(anchor);
        //标题
        chart.setTitleText(chartTitle);
        //标题是否覆盖图表
        chart.setTitleOverlay(false);
        //图例位置
//        XDDFChartLegend legend = chart.getOrAddLegend();
//        legend.setPosition(LegendPosition.TOP);
        //分类轴标(X轴),标题位置
        XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        if(StringUtils.isNotBlank(xName))
        bottomAxis.setTitle(xName);
        //值(Y轴)轴,标题位置
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        if(StringUtils.isNotBlank(yName))
        leftAxis.setTitle(yName);
        //CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
        //分类轴标(X轴)数据,单元格范围位置[0, 0]到[0, 6]
        XDDFDataSource<String> xData = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(firstRow, dataEndRow, xAxisCol, xAxisCol));

        //数据1,单元格范围位置[1, 0]到[1, 6]
        XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(firstRow, dataEndRow, valueCol, valueCol));

        //LINE:折线图,
        XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
        //图表加载数据,折线1
        XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xData, values);
        //折线图例标题
        if(StringUtils.isNotBlank(lineName))
            series1.setTitle(lineName, null);
        //直线
        series1.setSmooth(false);
        //设置标记大小
        series1.setMarkerSize((short) 6);

        //设置标记样式 无
        series1.setMarkerStyle(MarkerStyle.CIRCLE);
//        series1.setShowLeaderLines(false);

        //绘制
        chart.plot(data);
    }

    /**
     * 饼图
     *
     * @param sheet sheet
     * @param chartTitle 标题
     * @param firstRow  开始行
     * @param dataEndRow 结束行
     * @param startCol 开始列
     * @param xAxisCol x轴列
     * @param valueCol 结束列
     */
    public static void createSheetPieChark(XSSFSheet sheet,String chartTitle,int firstRow,int dataEndRow,int startCol,int xAxisCol,int valueCol){
        //创建一个画布
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        //前四个默认0,[0,4]:从0列4行开始;[7,20]:宽度7个单元格,20向下扩展到20行
        //默认宽度(14-8)*12
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, startCol, dataEndRow + 4, startCol + 20, dataEndRow + 40);
        //创建一个chart对象
        XSSFChart chart = drawing.createChart(anchor);
        //标题
        chart.setTitleText(chartTitle);
        //标题是否覆盖图表
        chart.setTitleOverlay(false);
        //图例位置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP_RIGHT);
        //CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
        //分类轴标数据,
        XDDFDataSource<String> xData = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(firstRow, dataEndRow, xAxisCol, xAxisCol));
        //数据1,单元格范围位置[1, 0]到[1, 6]
        XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(firstRow, dataEndRow, valueCol, valueCol));
        //XDDFChartData data = chart.createData(ChartTypes.PIE3D, null, null);
        XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
        //设置为可变颜色
        data.setVaryColors(true);
        //图表加载数据
        data.addSeries(xData, values);

        //绘制
        chart.plot(data);

    }

    /**
     * 柱状图
     *
     * @param sheet
     * @param chartTitle
     * @param firstRow
     * @param dataEndRow
     * @param startCol
     * @param xAxisCol
     * @param valueCol
     */
    public static void createSheetBarChark(XSSFSheet sheet,String chartTitle,int firstRow,int dataEndRow,int startCol,int xAxisCol,int valueCol){
        //创建一个画布
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        //前四个默认0,[0,4]:从0列4行开始;[7,20]:宽度7个单元格,20向下扩展到20行
        //默认宽度(14-8)*12
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, startCol, dataEndRow + 4, startCol + 20, dataEndRow + 45);
        //创建一个chart对象
        XSSFChart chart = drawing.createChart(anchor);
        //标题
        chart.setTitleText(chartTitle);
        //标题是否覆盖图表
        chart.setTitleOverlay(false);

        //图例位置
//        XDDFChartLegend legend = chart.getOrAddLegend();
//        legend.setPosition(LegendPosition.TOP);
        //分类轴标(X轴),标题位置
        XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        //值(Y轴)轴,标题位置
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        //CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
        //分类轴标数据,
        XDDFDataSource<String> xData = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(firstRow, dataEndRow, xAxisCol, xAxisCol));

        //数据1,单元格范围位置[1, 0]到[1, 6]
        XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(firstRow, dataEndRow, valueCol, valueCol));
        //bar:条形图,
        XDDFBarChartData bar = (XDDFBarChartData) chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);

        leftAxis.setCrossBetween(AxisCrossBetween.BETWEEN);
        //设置为可变颜色
        bar.setVaryColors(true);
        //条形图方向,纵向/横向:纵向
        bar.setBarDirection(BarDirection.COL);

        //图表加载数据,条形图1
        XDDFBarChartData.Series series1 = (XDDFBarChartData.Series) bar.addSeries(xData, values);
        //条形图例标题

        XDDFSolidFillProperties fill = new XDDFSolidFillProperties(XDDFColor.from(PresetColor.BLUE));
        //条形图,填充颜色
        series1.setFillProperties(fill);
        //绘制
        chart.plot(bar);
    }

    /**
     * 创建画布
     *
     * @param sheet
     * @param chartTitle
     * @param dataEndRow
     * @param startCol
     * @return
     */
    public static XSSFChart createSheetDrawing(XSSFSheet sheet, String chartTitle, int dataEndRow, int startCol) {
        //创建一个画布
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        //前四个默认0,[0,4]:从0列4行开始;[7,20]:宽度7个单元格,20向下扩展到20行
        //默认宽度(14-8)*12
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, startCol, dataEndRow + 4, startCol + 9, dataEndRow + 28);
        //创建一个chart对象
        XSSFChart chart = drawing.createChart(anchor);
        //标题
        chart.setTitleText(chartTitle);
        //标题是否覆盖图表
        chart.setTitleOverlay(false);
        return chart;
    }


    /**
     * 创建折线图
     *
     * @param sheet
     * @param yDataList y轴数据
     * @param title
     * @param firstRow
     * @param endRow
     * @param startCol
     * @param endCol
     */
    public static void createLineChart(XSSFSheet sheet, List<Double> yDataList, String title, int firstRow, int endRow, int startCol, int endCol, int firstRowOffset, int endRowOffset, int startColOffset, int endColOffset) {

        //创建一个画布
        XSSFChart chart = getSheetDrawing(sheet, title, startCol, firstRowOffset, endRowOffset, startColOffset, endColOffset);

        //图例位置
        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);

        // X轴数据
        XDDFCategoryDataSource countries = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(firstRow, endRow, startCol, endCol));
        Double[] doubles = new Double[yDataList.size()];
        for (int i= 0; i< yDataList.size(); i++) {
            doubles[i] = yDataList.get(i);
        }
        // Y轴数据
        XDDFNumericalDataSource<Double> source = XDDFDataSourcesFactory.fromArray(doubles);

        XDDFLineChartData.Series series = (XDDFLineChartData.Series) data.addSeries(countries, source);
        series.setTitle(title, null);
        //直线
        series.setSmooth(false);
        //设置标记大小
        series.setMarkerSize((short) 6);

        //绘制
        chart.plot(data);
    }

    /**
     * 饼图
     *
     * @param sheet sheet
     * @param chartTitle 标题
     * @param firstRow  开始行
     * @param endRow 结束行
     * @param startCol 开始列
     * @param endCol 结束列
     * @param firstRowOffset  饼图开始y坐标偏移量
     * @param endRowOffset    饼图结束y坐标偏移量
     * @param startColOffset  饼图开始x坐标偏移量
     * @param endColOffset    饼图结束x坐标偏移量
     */
    public static void createPieChart(XSSFSheet sheet, List<Double> yDataList, String chartTitle, int firstRow, int endRow, int startCol, int endCol, int firstRowOffset, int endRowOffset, int startColOffset, int endColOffset) {
        //创建一个画布
        XSSFChart chart = getSheetDrawing(sheet, chartTitle, startCol, firstRowOffset, endRowOffset, startColOffset, endColOffset);
        //图例位置
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP_RIGHT);
        //CellRangeAddress(起始行号,终止行号, 起始列号,终止列号)
        //分类轴标数据,
        XDDFDataSource<String> xData = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(firstRow, endRow, startCol, endCol));

        Double[] doubles = new Double[yDataList.size()];
        for (int i= 0; i< yDataList.size(); i++) {
            doubles[i] = yDataList.get(i);
        }
        // Y轴数据
        XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromArray(doubles);
        XDDFChartData data = chart.createData(ChartTypes.PIE, null, null);
        //设置为可变颜色
        data.setVaryColors(true);
        //图表加载数据
        data.addSeries(xData, values);

        //绘制
        chart.plot(data);

    }

    /**
     * 柱状图
     *
     * @param sheet
     * @param yDataList
     * @param chartTitle
     * @param firstRow
     * @param endRow
     * @param startCol
     * @param endCol
     * @param firstRowOffset
     * @param endRowOffset
     * @param startColOffset
     * @param endColOffset
     */
    public static void createBarChart(XSSFSheet sheet, List<Double> yDataList, String chartTitle, int firstRow, int endRow, int startCol, int endCol, int firstRowOffset, int endRowOffset, int startColOffset, int endColOffset) {
        // 获取画布
        XSSFChart chart = getSheetDrawing(sheet, chartTitle, startCol, firstRowOffset, endRowOffset, startColOffset, endColOffset);
        //获取或添加图例
        XDDFChartLegend legend = chart.getOrAddLegend();
        //设置图例的位置
        legend.setPosition(LegendPosition.BOTTOM);
        //创建 类别轴 放置底部
        XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        //创建数据轴 放置左侧
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
//        leftAxis.setTitle(chartTitle);
        //创建数据中心  0,0
        XDDFCategoryDataSource xs = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(firstRow, endRow, startCol, endCol));

        Double[] doubles = new Double[yDataList.size()];
        for (int i= 0; i< yDataList.size(); i++) {
            doubles[i] = yDataList.get(i);
        }
        XDDFNumericalDataSource<Double> xv = XDDFDataSourcesFactory.fromArray(doubles);
        //数据加载
        XDDFChartData data = chart.createData(ChartTypes.BAR, bottomAxis, leftAxis);
        XDDFChartData.Series series = data.addSeries(xs, xv);
        series.setTitle(chartTitle, null);
        XDDFBarChartData bar = (XDDFBarChartData) data;
        bar.setVaryColors(true);
        bar.setBarDirection(BarDirection.COL);
        bar.setBarGrouping(BarGrouping.STACKED);
        chart.plot(data);
    }

    /**
     * 创建画布
     *
     * @param sheet
     * @param chartTitle
     * @param startCol
     * @param firstRowOffset
     * @param endRowOffset
     * @param startColOffset
     * @param endColOffset
     * @return
     */
    private static XSSFChart getSheetDrawing(XSSFSheet sheet, String chartTitle, int startCol, int firstRowOffset, int endRowOffset, int startColOffset, int endColOffset) {
        //创建一个画布
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        //前四个默认0,[0,4]:从0列4行开始;[7,20]:宽度7个单元格,20向下扩展到20行

        //默认宽度(14-8)*12
        int lastRowNum = sheet.getLastRowNum();
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, startCol + startColOffset, lastRowNum + firstRowOffset, startCol + endColOffset, lastRowNum + endRowOffset);
        //创建一个chart对象
        XSSFChart chart = drawing.createChart(anchor);
        //标题
        chart.setTitleText(chartTitle);
        //标题是否覆盖图表
        chart.setTitleOverlay(false);
        return chart;
    }

}

图片
图片
图片
图片
  • 参考链接
https://www.freesion.com/article/3914537989/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容