陈昶聿
2026-04-28 2dc0e508dacff4acd61bec58c3549db0e673bcbe
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -38,14 +38,9 @@
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
import org.apache.poi.xssf.usermodel.XSSFDataValidation;
import org.apache.poi.xssf.usermodel.XSSFDrawing;
import org.apache.poi.xssf.usermodel.XSSFPicture;
import org.apache.poi.xssf.usermodel.XSSFShape;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -1472,4 +1467,144 @@
            log.error("{}设置导出Excel文件名称异常,{}", fileName, e.getMessage());
        }
    }
//    public static void main(String[] args) {
//        // 1. 创建工作簿
//        try (XSSFWorkbook workbook = new XSSFWorkbook()) {
//            // 2. 生成柱状图 Sheet
//            createBarChartSheet(workbook);
//            // 3. 生成折线图 Sheet
//            createLineChartSheet(workbook);
//            // 4. 生成饼状图 Sheet
//            createPieChartSheet(workbook);
//
//            // 5. 导出到本地文件
//            try (FileOutputStream fos = new FileOutputStream("D:/图表导出.xlsx")) {
//                workbook.write(fos);
//                System.out.println("Excel 图表导出成功!路径:D:/图表导出.xlsx");
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
    // ==================== 1. 创建柱状图 Sheet ====================
    private static void createBarChartSheet(XSSFWorkbook workbook) {
        XSSFSheet sheet = workbook.createSheet("柱状图");
        writeChartData(sheet);
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 3, 1, 12, 15);
        XSSFChart chart = drawing.createChart(anchor);
        chart.setTitleText("产品销量-柱状图");
        chart.setTitleOverlay(false);
        // 坐标轴
        XDDFCategoryAxis xAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        XDDFValueAxis yAxis = chart.createValueAxis(AxisPosition.LEFT);
        yAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        // 数据范围:分类A2:A6,数值B2:B6
        XDDFDataSource<String> cat = XDDFDataSourcesFactory.fromStringCellRange(sheet,
                new CellRangeAddress(1, 5, 0, 0));
        XDDFNumericalDataSource<Double> val = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
                new CellRangeAddress(1, 5, 1, 1));
        // 柱状图数据
        XDDFBarChartData barChart = (XDDFBarChartData) chart.createData(ChartTypes.BAR, xAxis, yAxis);
        XDDFBarChartData.Series series = (XDDFBarChartData.Series) barChart.addSeries(cat, val);
        series.setTitle("销量", null);
        barChart.setBarDirection(BarDirection.COL);
        // 绘制(关键:缺失就不显示图表)
        chart.plot(barChart);
    }
    // ==================== 2. 创建折线图 Sheet ====================
    private static void createLineChartSheet(XSSFWorkbook workbook) {
        XSSFSheet sheet = workbook.createSheet("折线图");
        // 写入表头 + 数据
        writeChartData(sheet);
        // 绘图区域
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 5, 10, 20);
        XSSFChart chart = drawing.createChart(anchor);
        // 图表标题
        chart.setTitleText("月度销售额折线图");
        chart.setTitleOverlay(false);
        // 图例
        XDDFChartLegend legend = chart.getOrAddLegend();
        legend.setPosition(LegendPosition.TOP_RIGHT);
        // X轴、Y轴
        XDDFCategoryAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        bottomAxis.setTitle("月份");
        XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        leftAxis.setTitle("销售额(万元)");
        // 数据范围
        XDDFDataSource<String> months = XDDFDataSourcesFactory.fromStringCellRange(sheet, new CellRangeAddress(0, 5, 0, 0));
        XDDFNumericalDataSource<Double> values = XDDFDataSourcesFactory.fromNumericCellRange(sheet, new CellRangeAddress(0, 5, 1, 1));
        // 创建折线图
        XDDFLineChartData lineData = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
        XDDFLineChartData.Series series = (XDDFLineChartData.Series) lineData.addSeries(months, values);
        series.setTitle("销售额", null);
        series.setMarkerStyle(MarkerStyle.CIRCLE); // 显示圆点
        chart.plot(lineData);
    }
    // ========== 新增:饼状图 ==========
    private static void createPieChartSheet(XSSFWorkbook workbook) {
        XSSFSheet sheet = workbook.createSheet("饼状图");
        writeChartData(sheet);
        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 3, 1, 12, 15);
        XSSFChart chart = drawing.createChart(anchor);
        chart.setTitleText("产品占比-饼状图");
        chart.setTitleOverlay(false);
        // 饼图不需要XY轴
        XDDFDataSource<String> cat = XDDFDataSourcesFactory.fromStringCellRange(sheet,
                new CellRangeAddress(1, 5, 0, 0));
        XDDFNumericalDataSource<Double> val = XDDFDataSourcesFactory.fromNumericCellRange(sheet,
                new CellRangeAddress(1, 5, 1, 1));
        // 饼图数据
        XDDFPieChartData pieChart = (XDDFPieChartData) chart.createData(ChartTypes.PIE, null, null);
        pieChart.addSeries(cat, val);
        chart.plot(pieChart);
    }
    // ==================== 公共方法:写入图表数据 ====================
    private static void writeChartData(XSSFSheet sheet) {
        Object[][] data = {
                {"分类", "数值"},
                {"产品A", 35},
                {"产品B", 28},
                {"产品C", 42},
                {"产品D", 19},
                {"产品E", 26}
        };
        int rowIdx = 0;
        for (Object[] rows : data) {
            Row row = sheet.createRow(rowIdx++);
            int cellIdx = 0;
            for (Object val : rows) {
                if (val instanceof String) {
                    row.createCell(cellIdx++).setCellValue((String) val);
                } else if (val instanceof Number) {
                    row.createCell(cellIdx++).setCellValue(((Number) val).doubleValue());
                }
            }
        }
        sheet.autoSizeColumn(0);
        sheet.autoSizeColumn(1);
    }
}