You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Apache-POI的getNumericCellValue()返回值存入x-y对应矩阵?

解决Apache POI读取Excel成对数据存入矩阵的问题

嘿,我完全懂你卡在这里的感受——折腾了3小时,本来以为按计数器奇偶就能搞定,结果还是没弄对,确实让人头疼。咱们来把这个问题拆解清楚,一步步解决它。

首先,你的核心需求是把Excel里x1 y1 x2 y2 … xn yn格式的数据,按(x,y)对的形式存入一个r行c列的矩阵(或者分开的x、y矩阵),比如第一个(x1,y1)对应data[0][0]。之前用计数器的思路其实没问题,但可能是计数器的起始值或者循环逻辑没处理好,导致出错。我给你一个更直观、不容易出错的方案:

解决方案步骤

  1. 先确定矩阵的维度:
    • 行数r就是Excel中包含数据的总行数(用getPhysicalNumberOfRows()获取)
    • 列数c是每行单元格数的一半(因为每两个单元格是一组(x,y))
  2. 初始化存储矩阵:可以分开创建x和y的二维数组,或者用自定义对象存储每对数据(这里推荐前者,更贴合基本类型的使用场景)
  3. 成对读取单元格数据:不再用奇偶计数器,而是直接每次读取两个单元格——第一个是x,第二个是y,然后存入对应的矩阵位置

修改后的完整代码

import org.apache.poi.ss.usermodel.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

public class ExcelDataReader {
    private File excelFile; // 你的成员变量

    public void getDataFromExcelFile() throws IOException {
        FileInputStream inputStream = new FileInputStream(excelFile);
        Workbook workbook = new XSSFWorkbook(inputStream);
        Sheet firstSheet = workbook.getSheetAt(0);
        
        // 1. 校验并确定矩阵维度
        int rowCount = firstSheet.getPhysicalNumberOfRows();
        if (rowCount == 0) {
            System.out.println("Excel中没有数据行");
            workbook.close();
            inputStream.close();
            return;
        }
        
        Row firstRow = firstSheet.getRow(0);
        int cellCount = firstRow.getPhysicalNumberOfCells();
        if (cellCount % 2 != 0) {
            throw new IOException("第一行单元格数为奇数,不符合x1 y1 x2 y2的格式要求");
        }
        int colCount = cellCount / 2;
        
        // 2. 初始化x、y数据矩阵
        double[][] xData = new double[rowCount][colCount];
        double[][] yData = new double[rowCount][colCount];
        
        // 3. 遍历数据并填充矩阵
        int currentRow = 0;
        Iterator<Row> rowIterator = firstSheet.iterator();
        
        while (rowIterator.hasNext()) {
            Row row = rowIterator.next();
            Iterator<Cell> cellIterator = row.cellIterator();
            int currentPair = 0;
            
            while (cellIterator.hasNext()) {
                // 读取当前(x,y)对的x值
                Cell xCell = cellIterator.next();
                double xValue = getCellNumericValue(xCell);
                
                // 读取对应的y值,确保有下一个单元格
                if (!cellIterator.hasNext()) {
                    throw new IOException("第" + row.getRowNum() + "行单元格数为奇数,数据格式错误");
                }
                Cell yCell = cellIterator.next();
                double yValue = getCellNumericValue(yCell);
                
                // 存入矩阵
                xData[currentRow][currentPair] = xValue;
                yData[currentRow][currentPair] = yValue;
                
                currentPair++;
            }
            currentRow++;
        }
        
        // 测试打印结果(可以根据需求删除)
        System.out.println("X数据矩阵:");
        for (double[] row : xData) {
            for (double val : row) {
                System.out.print(val + "\t");
            }
            System.out.println();
        }
        
        System.out.println("\nY数据矩阵:");
        for (double[] row : yData) {
            for (double val : row) {
                System.out.print(val + "\t");
            }
            System.out.println();
        }
        
        workbook.close();
        inputStream.close();
        
        // 之后就可以直接使用xData和yData矩阵了
    }
    
    // 辅助方法:处理不同类型的单元格,确保获取到数值
    private double getCellNumericValue(Cell cell) throws IOException {
        if (cell.getCellType() == CellType.NUMERIC) {
            return cell.getNumericCellValue();
        } else if (cell.getCellType() == CellType.STRING) {
            try {
                return Double.parseDouble(cell.getStringCellValue().trim());
            } catch (NumberFormatException e) {
                throw new IOException("单元格" + cell.getAddress() + "的内容不是有效的数值:" + cell.getStringCellValue());
            }
        } else {
            throw new IOException("单元格" + cell.getAddress() + "的类型不支持(仅支持数值或文本类型的数值)");
        }
    }
}

关键说明

  • 成对读取逻辑:直接每次取两个单元格,避免了奇偶计数器可能出现的边界错误(比如行尾单元格数为奇数的情况)
  • 类型兼容处理:加入了getCellNumericValue辅助方法,支持读取数值类型和文本类型的数值,让代码更健壮
  • 异常校验:提前检查总行数、每行单元格数是否符合格式,避免后续运行时出错

额外注意事项

  • 如果Excel有表头行,需要跳过第一行:可以在rowIterator遍历的时候,先调用一次rowIterator.next()跳过表头,再开始填充矩阵
  • 如果存在空行,可以在遍历行的时候判断row == null || row.getPhysicalNumberOfCells() == 0,跳过这些空行

内容的提问来源于stack exchange,提问作者John Gunasar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:14:35