【POI】Java+poi生成Excel(.xlsx)折线图

5 篇文章 1 订阅

仅通过POI的话,只能实现折线图和散点图
但POI还支持Open Xml,通过这种方式可以实现很多类型的chart
https://blog.csdn.net/u011279583/article/details/105196805

效果参考:
折线图
POI版本

	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi</artifactId>
		<version>3.17</version>
	</dependency>
	<dependency>
		<groupId>org.apache.poi</groupId>
		<artifactId>poi-ooxml</artifactId>
		<version>3.17</version>
	</dependency>
	<dependency>
	  <groupId>org.apache.poi</groupId>
	  <artifactId>poi-scratchpad</artifactId>
	  <version>3.17</version>
	</dependency>
       <dependency>
	  <groupId>org.apache.poi</groupId>
	  <artifactId>poi-ooxml-schemas</artifactId>
	  <version>3.17</version>
	</dependency>
	<dependency>
	  <groupId>org.apache.poi</groupId>
	  <artifactId>ooxml-schemas</artifactId>
	  <version>1.3</version>
	</dependency>

代码

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.charts.AxisCrosses;
import org.apache.poi.ss.usermodel.charts.AxisPosition;
import org.apache.poi.ss.usermodel.charts.ChartDataSource;
import org.apache.poi.ss.usermodel.charts.DataSources;
import org.apache.poi.ss.usermodel.charts.LegendPosition;
import org.apache.poi.ss.usermodel.charts.LineChartSeries;
import org.apache.poi.ss.util.CellRangeAddress;
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.apache.poi.xssf.usermodel.charts.XSSFChartAxis;
import org.apache.poi.xssf.usermodel.charts.XSSFChartLegend;
import org.apache.poi.xssf.usermodel.charts.XSSFLineChartData;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTBoolean;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTDispBlanksAs;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineChart;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTLineSer;
import org.openxmlformats.schemas.drawingml.x2006.chart.CTPlotArea;
import org.openxmlformats.schemas.drawingml.x2006.chart.STDispBlanksAs;

public class XSSFUtils {

    public static void test(XSSFSheet sheet) {
        Map<String, Object> params = new HashMap<String, Object> ();

        // 图表位置(B36左上角:AA53左上角)
        int[] position = new int[] {getColumnIndexByAddress("B"), 35, getColumnIndexByAddress("AA"), 52};

        // x轴坐标区域(B60:B90)
        int[] xAxisRange = new int[] {59, 89, getColumnIndexByAddress("B"), getColumnIndexByAddress("B")};

        // 每个系列的数据(D60:D90、J60:J90、P60:P90)
        // 每个系列的标题(D59、J59、P59)
        List<Integer[]> seriesDataRangeList = new ArrayList<Integer[]>();
        seriesDataRangeList .add(new Integer[] {59, 89, getColumnIndexByAddress("D"), getColumnIndexByAddress("D"),
                58, getColumnIndexByAddress("D")});
        seriesDataRangeList .add(new Integer[] {59, 89, getColumnIndexByAddress("J"), getColumnIndexByAddress("J"),
                58, getColumnIndexByAddress("J")});
        seriesDataRangeList .add(new Integer[] {59, 89, getColumnIndexByAddress("P"), getColumnIndexByAddress("P"),
                58, getColumnIndexByAddress("P")});

        params.put("chartPosition", position);
        params.put("xAxisRange", xAxisRange);
        params.put("seriesDataRangeList ", seriesDataRangeList );

        createLineChart(sheet, params);
    }

    /**
     * create line chart
     * @param sheet
     * @param params
     *             chartPosition            int[]{startRow, endRow, startCol, endCol}
     *             xAxisRange               int[]{startRow, endRow, startCol, endCol}
     *             seriesDataRangeList      List<Integer[]>{startRow, endRow, startCol, endCol, titleRow, titleCol}
     */
    private static void createLineChart(XSSFSheet sheet, Map<String, Object> params) {

        int[] position = (int[]) params.get("chartPosition");
        int[] xAxisRange = (int[]) params.get("xAxisRange");
        List<Integer[]> seriesDataRangeList = (List<Integer[]>) params.get("seriesDataRangeList ");

        XSSFDrawing drawing = sheet.createDrawingPatriarch();
        XSSFClientAnchor anchor =
                drawing.createAnchor(0, 0, 0, 0, position[0], position[1], position[2], position[3]);

        XSSFChart chart = drawing.createChart(anchor);
        XSSFChartLegend legned = chart.getOrCreateLegend();
        legned.setPosition(LegendPosition.TOP);

        // set blank values as gaps
        CTDispBlanksAs disp = CTDispBlanksAs.Factory.newInstance();
        disp.setVal(STDispBlanksAs.GAP);
        chart.getCTChart().setDispBlanksAs(disp);

        XSSFLineChartData chartData = chart.getChartDataFactory().createLineChartData();
        XSSFChartAxis bottomAxis = chart.createCategoryAxis(AxisPosition.BOTTOM);
        XSSFChartAxis leftAxis = chart.createValueAxis(AxisPosition.LEFT);
        bottomAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        bottomAxis.setNumberFormat("yyyy/m/d");
        leftAxis.setCrosses(AxisCrosses.AUTO_ZERO);
        leftAxis.setMinimum(0);

        // 设置x轴坐标区域(B60:B90)
        ChartDataSource<String> xAxisData =
                DataSources.fromStringCellRange(sheet,
                        new CellRangeAddress(xAxisRange[0], xAxisRange[1], xAxisRange[2], xAxisRange[3]));

        // 设置数据区域,即每个系列的数据(D60:D90、J60:J90、P60:P90)
        for (Integer[] seriesDataRange : seriesDataRangeList ) {
            ChartDataSource<Number> yAxisData =
                    DataSources.fromNumericCellRange(sheet,
                            new CellRangeAddress(seriesDataRange[0], seriesDataRange[1], seriesDataRange[2], seriesDataRange[3]));
            LineChartSeries series = chartData.addSeries(xAxisData, yAxisData);

            // 设置每个系列的标题(D59、J59、P59)
            series.setTitle(sheet.getRow(seriesDataRange[4]).getCell(seriesDataRange[5]).getStringCellValue());
        }

        chart.plot(chartData, bottomAxis, leftAxis);

        // unsmooth series(好像必须写在polt方法之后)
        CTPlotArea plotArea = chart.getCTChart().getPlotArea();
        for (CTLineChart ch : plotArea.getLineChartList()) {
            for (CTLineSer ser : ch.getSerList()) {
                CTBoolean ctBool = CTBoolean.Factory.newInstance();
                ctBool.setVal(false);
                ser.setSmooth(ctBool);
            }
        }
    }

    /**
     * get column index by column address
     */
    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;
    }
}
使用Apache POI库可以轻松地读取Excel文件。下面是一个使用XSSFWorkbook类读取.xlsx文件的示例代码: ```java import java.io.File; import java.io.FileInputStream; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.xssf.usermodel.XSSFWorkbook; public class ReadExcel { public static void main(String[] args) { try { // 读取文件 File file = new File("data.xlsx"); FileInputStream inputStream = new FileInputStream(file); // 创建工作簿对象 XSSFWorkbook workbook = new XSSFWorkbook(inputStream); // 获取第一个工作表 org.apache.poi.ss.usermodel.Sheet sheet = workbook.getSheetAt(0); // 循环读取每一行数据 for (Row row : sheet) { // 循环读取每一个单元格数据 for (Cell cell : row) { // 输出单元格内容 System.out.print(cell.toString() + "\t"); } System.out.println(); } // 关闭输入流 inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } ``` 这个程序将打开名为“data.xlsx”的文件,并将其读取到XSSFWorkbook对象。然后,它获取工作表的第一个工作表,并使用循环遍历每一行和每一个单元格,输出单元格的内容。最后,它关闭输入流。 请注意,此示例代码需要添加Apache POI库的依赖项。您可以在Maven添加以下依赖项: ```xml <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.2</version> </dependency> ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值