如何将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]。之前用计数器的思路其实没问题,但可能是计数器的起始值或者循环逻辑没处理好,导致出错。我给你一个更直观、不容易出错的方案:
解决方案步骤
- 先确定矩阵的维度:
- 行数r就是Excel中包含数据的总行数(用
getPhysicalNumberOfRows()获取) - 列数c是每行单元格数的一半(因为每两个单元格是一组
(x,y))
- 行数r就是Excel中包含数据的总行数(用
- 初始化存储矩阵:可以分开创建x和y的二维数组,或者用自定义对象存储每对数据(这里推荐前者,更贴合基本类型的使用场景)
- 成对读取单元格数据:不再用奇偶计数器,而是直接每次读取两个单元格——第一个是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
相关产品推荐
相关产品推荐

