Java POI Excel 折线图创建教程:使用 Apache POI 生成带日期坐标轴的折线图

本教程将指导您使用 Apache POI 库在 Java 中创建 Excel 折线图。它涵盖了如何设置日期坐标轴、添加多个数据系列、自定义图表样式等步骤,并提供示例代码供您参考。

步骤 1:添加依赖

首先,您需要在项目中添加 Apache POI 库的依赖。您可以使用 Maven 或 Gradle 等构建工具来添加依赖。以下是一个 Maven 依赖示例:

<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>5.2.3</version>
</dependency>

步骤 2:创建工作簿和工作表

创建一个新的 XSSFWorkbook 对象,它代表一个 Excel 文件。然后,使用 createSheet() 方法创建新的工作表。

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExcelChartExample04 {

    public static void main(String[] args) {
        try {
            // 读取Excel文件
            FileInputStream fileIn = new FileInputStream('input-1.xlsx');
            XSSFWorkbook workbook = new XSSFWorkbook(fileIn);
            XSSFSheet sheet1 = workbook.getSheet('P1');

            // 创建折线图
            XSSFDrawing drawing = sheet1.createDrawingPatriarch();
            XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 129, 10, 149);
            XDDFChart chart = drawing.createChart(anchor);
            chart.setTitleText('数据折线图');
            chart.setTitleOverlay(false);

            // 设置图例位置
            XDDFChartLegend legend = chart.getOrAddLegend();
            legend.setPosition(LegendPosition.BOTTOM);

            // 设置横坐标轴为日期坐标轴
            XDDFDataSource<?> dateSource = XDDFDataSourcesFactory.fromArray(new String[]{'A2:A128'});
            XDDFDateAxis bottomAxis = chart.createDateAxis(AxisPosition.BOTTOM);
            bottomAxis.setCrosses(AxisCrosses.AUTO_ZERO);
            bottomAxis.setTitle('时间');
            bottomAxis.setTickLabelPosition(AxisTickLabelPosition.NEXT_TO);

            // 设置时间格式
            SimpleDateFormat dateFormat = new SimpleDateFormat('yyyy/MM/dd');
            for (int i = 0; i < dateSource.getPointCount(); i++) {
                XSSFRow row = sheet1.getRow(i + 1);
                if (row != null) {
                    Cell cell = row.getCell(0);
                    if (cell != null && cell.getCellType() == CellType.NUMERIC) {
                        Date date = cell.getDateCellValue();
                        String formattedDate = dateFormat.format(date);
                        bottomAxis.setTickLabelPosition(AxisTickLabelPosition.NEXT_TO);
                    }
                }
            }

            // 设置左侧坐标轴为温度坐标轴
            XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
            leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
            leftAxis.setTitle('温度');

            // 设置右侧坐标轴为数值坐标轴
            XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
            rightAxis.setCrosses(AxisCrosses.MAX);
            rightAxis.setTitle('数据值');

            // 设置数据源
            XDDFNumericalDataSource<Double> xs1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 0, 0));
            XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 1, 1));
            XDDFNumericalDataSource<Double> xs2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 0, 0));
            XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 2, 2));

            // 添加数据系列
            XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
            XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs1, ys1);
            series1.setTitle('折线图1', null);

            // 添加第二个数据系列
            XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs2, ys2);
            series2.setTitle('折线图2', null);
            series2.setSmooth(false); // 取消平滑曲线

            // 将第二个数据系列关联到右侧坐标轴
            chart.plot(data);
            chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(1).getIdx().setVal(1);

            // 将图表显示在Excel文件中
            XSSFChart xssfChart = (XSSFChart) chart;
            CTChart ctChart = xssfChart.getCTChart();
            CTPlotArea ctPlotArea = ctChart.getPlotArea();
            ctPlotArea.getLineChartArray(0).addNewVaryColors().setVal(true);
            ctPlotArea.getLineChartArray(0).addNewVaryColors().setVal(true);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(0).addNewMarker().addNewSymbol().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle.NONE);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(1).addNewMarker().addNewSymbol().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle.NONE);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(0).addNewSmooth().setVal(false);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(1).addNewSmooth().setVal(false);
            CTBoolean ctBoolean = ctChart.getPlotArea().getLineChartArray(0).addNewVaryColors();
            ctBoolean.setVal(true);
            ctBoolean = ctChart.getPlotArea().getLineChartArray(0).addNewVaryColors();
            ctBoolean.setVal(true);

            XSSFChart xssfChart = (XSSFChart) chart;
            CTChart ctChart = xssfChart.getCTChart();
            CTPlotArea ctPlotArea = ctChart.getPlotArea();
            CTLineChart[] lineCharts = ctPlotArea.getLineChartArray();
            CTLineChart lineChart = lineCharts[0];
            lineChart.addNewMarker().addNewSymbol().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle.NONE);
            lineChart.addNewSmooth().setVal(false);

            // 保存Excel文件
            FileOutputStream fileOut = new FileOutputStream('input-1.xlsx');
            workbook.write(fileOut);
            fileOut.close();

            System.out.println('折线图已创建并保存到Excel文件中。');

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

步骤 3:创建图表

使用 XSSFSheet 的 createDrawingPatriarch() 方法获取绘图对象,并使用 createChart() 方法创建图表。设置图表标题和图例位置。

步骤 4:设置坐标轴

创建一个 XDDFDateAxis 对象作为横坐标轴,并设置它为日期坐标轴。使用 setCrosses() 方法设置坐标轴与另一坐标轴的交点,使用 setTitle() 方法设置坐标轴标题,使用 setTickLabelPosition() 方法设置刻度标签的位置。

创建一个 XDDFValueAxis 对象作为纵坐标轴,并设置它为数值坐标轴。同样地,可以使用 setCrosses()、setTitle() 和 setTickLabelPosition() 方法设置坐标轴属性。

步骤 5:设置数据源

使用 XDDFDataSourcesFactory 的 fromNumericCellRange() 方法从 Excel 工作表中获取数据。这个方法接受两个参数:工作表和 CellRangeAddress 对象,表示数据所在的单元格区域。

步骤 6:添加数据系列

使用 chart.createData() 方法创建图表数据。第一个参数是图表类型,第二个参数是横坐标轴,第三个参数是纵坐标轴。然后,使用 addSeries() 方法添加数据系列。

步骤 7:设置图表样式

您可以通过设置每个数据系列的标题和设置是否平滑曲线等方法来自定义图表样式。

步骤 8:关联数据系列到坐标轴

使用 chart.plot() 方法将图表数据关联到图表。对于第二个数据系列,可以使用 getCTChart() 方法获取图表对象的 CTChart 对象,并使用 getPlotArea() 方法获取图表区域对象的 CTPlotArea 对象。最后,使用 getLineChartArray() 和 getSerArray() 方法获取数据系列对象,并使用 setIdx() 方法将第二个数据系列关联到右侧坐标轴。

步骤 9:保存 Excel 文件

使用 FileOutputStream 打开输出流,并使用 workbook.write() 方法将工作簿保存到 Excel 文件。

完整的代码示例

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xddf.usermodel.chart.*;
import org.apache.poi.xssf.usermodel.*;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class ExcelChartExample04 {

    public static void main(String[] args) {
        try {
            // 读取Excel文件
            FileInputStream fileIn = new FileInputStream('input-1.xlsx');
            XSSFWorkbook workbook = new XSSFWorkbook(fileIn);
            XSSFSheet sheet1 = workbook.getSheet('P1');

            // 创建折线图
            XSSFDrawing drawing = sheet1.createDrawingPatriarch();
            XSSFClientAnchor anchor = drawing.createAnchor(0, 0, 0, 0, 0, 129, 10, 149);
            XDDFChart chart = drawing.createChart(anchor);
            chart.setTitleText('数据折线图');
            chart.setTitleOverlay(false);

            // 设置图例位置
            XDDFChartLegend legend = chart.getOrAddLegend();
            legend.setPosition(LegendPosition.BOTTOM);

            // 设置横坐标轴为日期坐标轴
            XDDFDataSource<?> dateSource = XDDFDataSourcesFactory.fromArray(new String[]{'A2:A128'});
            XDDFDateAxis bottomAxis = chart.createDateAxis(AxisPosition.BOTTOM);
            bottomAxis.setCrosses(AxisCrosses.AUTO_ZERO);
            bottomAxis.setTitle('时间');
            bottomAxis.setTickLabelPosition(AxisTickLabelPosition.NEXT_TO);

            // 设置时间格式
            SimpleDateFormat dateFormat = new SimpleDateFormat('yyyy/MM/dd');
            for (int i = 0; i < dateSource.getPointCount(); i++) {
                XSSFRow row = sheet1.getRow(i + 1);
                if (row != null) {
                    Cell cell = row.getCell(0);
                    if (cell != null && cell.getCellType() == CellType.NUMERIC) {
                        Date date = cell.getDateCellValue();
                        String formattedDate = dateFormat.format(date);
                        bottomAxis.setTickLabelPosition(AxisTickLabelPosition.NEXT_TO);
                    }
                }
            }

            // 设置左侧坐标轴为温度坐标轴
            XDDFValueAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
            leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
            leftAxis.setTitle('温度');

            // 设置右侧坐标轴为数值坐标轴
            XDDFValueAxis rightAxis = chart.createValueAxis(AxisPosition.RIGHT);
            rightAxis.setCrosses(AxisCrosses.MAX);
            rightAxis.setTitle('数据值');

            // 设置数据源
            XDDFNumericalDataSource<Double> xs1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 0, 0));
            XDDFNumericalDataSource<Double> ys1 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 1, 1));
            XDDFNumericalDataSource<Double> xs2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 0, 0));
            XDDFNumericalDataSource<Double> ys2 = XDDFDataSourcesFactory.fromNumericCellRange(sheet1, new CellRangeAddress(1, 127, 2, 2));

            // 添加数据系列
            XDDFLineChartData data = (XDDFLineChartData) chart.createData(ChartTypes.LINE, bottomAxis, leftAxis);
            XDDFLineChartData.Series series1 = (XDDFLineChartData.Series) data.addSeries(xs1, ys1);
            series1.setTitle('折线图1', null);

            // 添加第二个数据系列
            XDDFLineChartData.Series series2 = (XDDFLineChartData.Series) data.addSeries(xs2, ys2);
            series2.setTitle('折线图2', null);
            series2.setSmooth(false); // 取消平滑曲线

            // 将第二个数据系列关联到右侧坐标轴
            chart.plot(data);
            chart.getCTChart().getPlotArea().getLineChartArray(0).getSerArray(1).getIdx().setVal(1);

            // 将图表显示在Excel文件中
            XSSFChart xssfChart = (XSSFChart) chart;
            CTChart ctChart = xssfChart.getCTChart();
            CTPlotArea ctPlotArea = ctChart.getPlotArea();
            ctPlotArea.getLineChartArray(0).addNewVaryColors().setVal(true);
            ctPlotArea.getLineChartArray(0).addNewVaryColors().setVal(true);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(0).addNewMarker().addNewSymbol().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle.NONE);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(1).addNewMarker().addNewSymbol().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle.NONE);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(0).addNewSmooth().setVal(false);
            ctChart.getPlotArea().getLineChartArray(0).getSerArray(1).addNewSmooth().setVal(false);
            CTBoolean ctBoolean = ctChart.getPlotArea().getLineChartArray(0).addNewVaryColors();
            ctBoolean.setVal(true);
            ctBoolean = ctChart.getPlotArea().getLineChartArray(0).addNewVaryColors();
            ctBoolean.setVal(true);

            XSSFChart xssfChart = (XSSFChart) chart;
            CTChart ctChart = xssfChart.getCTChart();
            CTPlotArea ctPlotArea = ctChart.getPlotArea();
            CTLineChart[] lineCharts = ctPlotArea.getLineChartArray();
            CTLineChart lineChart = lineCharts[0];
            lineChart.addNewMarker().addNewSymbol().setVal(org.openxmlformats.schemas.drawingml.x2006.chart.STMarkerStyle.NONE);
            lineChart.addNewSmooth().setVal(false);

            // 保存Excel文件
            FileOutputStream fileOut = new FileOutputStream('input-1.xlsx');
            workbook.write(fileOut);
            fileOut.close();

            System.out.println('折线图已创建并保存到Excel文件中。');

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

总结

本教程展示了如何使用 Apache POI 库在 Java 中创建 Excel 折线图。您可以根据需要修改代码,以创建具有不同数据、样式和功能的图表。希望本教程能帮助您轻松地将图表添加到您的 Excel 文件中。

Java POI Excel 折线图创建教程:使用 Apache POI 生成带日期坐标轴的折线图

原文地址: https://www.cveoy.top/t/topic/fSyc 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录