Java读取Excel数字字段为字符串时显示科学计数法的问题
解决POI读取Excel手机号显示为科学计数法的问题
这个问题很常见,原因是Excel会把超过一定长度的数值自动转换成科学计数法存储,而你直接用toString()读取单元格内容时,就会拿到这个格式化后的字符串。下面给你两种可行的解决方案:
方案1:提前设置Excel单元格为文本格式(最简单)
如果可以修改源Excel文件,直接把存储手机号/邮箱的列设置为文本格式:
- 选中目标列,右键选择「设置单元格格式」
- 在弹出的窗口里选择「文本」类型,点击确定
之后再输入手机号,Excel就会把它当作文本存储,读取时直接用getStringCellValue()就能拿到完整的手机号字符串,不会出现科学计数法。
方案2:在代码中处理数值型单元格(无需修改Excel)
如果不能修改源文件,就需要在读取时判断单元格类型,对数值型单元格做特殊处理:
修改后的核心代码片段:
Workbook workbook = WorkbookFactory.create(new File("./TXN_Log_Mar_18_input.xlsx")); Sheet sheet = workbook.getSheetAt(0); Iterator<Row> rowIterator = sheet.rowIterator(); while (rowIterator.hasNext() && cnt < maxRows) { System.out.println("\n\nNew row " + cnt + " "); Row row = rowIterator.next(); // 安全获取第11列的单元格内容 Cell debitCell = row.getCell(11); String debitUser = ""; if (debitCell != null) { switch (debitCell.getCellType()) { case STRING: debitUser = debitCell.getStringCellValue(); break; case NUMERIC: // 将数值转换为长整型,避免科学计数法 long mobileNum = (long) debitCell.getNumericCellValue(); debitUser = String.valueOf(mobileNum); break; case FORMULA: // 处理公式型单元格,先获取计算结果类型 CellType resultType = debitCell.getCachedFormulaResultType(); if (resultType == CellType.NUMERIC) { mobileNum = (long) debitCell.getNumericCellValue(); debitUser = String.valueOf(mobileNum); } else if (resultType == CellType.STRING) { debitUser = debitCell.getStringCellValue(); } else { debitUser = debitCell.toString(); } break; default: debitUser = debitCell.toString(); break; } } // 同理处理第12列(这里省略重复逻辑,你可以参考上面的代码实现) Cell creditCell = row.getCell(12); String creditUser = ""; // ... 复制上面的单元格类型判断逻辑 ... // 修正空值判断(原代码的 != "" 有问题,应该用isEmpty()) if (!debitUser.isEmpty() || !creditUser.isEmpty()) { System.out.println("input mobile? " + debitUser); if (emailFormat(debitUser) || mobileFormat(debitUser)) { response = umCall(debitUser); } } cnt++; // 别忘了增加计数器,否则会无限循环! }
关键说明:
- 避免空指针异常:先判断
debitCell != null,再处理单元格内容 - 数值转字符串的正确方式:把数值型单元格转成
long(10位手机号在long的范围内),再转成字符串,这样就能得到完整的数字,不会出现科学计数法 - 处理公式单元格:如果单元格是公式,需要先获取计算结果的类型,再做对应处理
- 修正空值判断:原代码的
row.getCell(11).toString() !=""不能正确判断空单元格,改用!debitUser.isEmpty()更可靠
额外提醒:
如果手机号存在前导零(比如0123456789),那么必须用方案1(设置为文本格式),因为数值类型会自动丢弃前导零,代码处理也无法恢复。
内容的提问来源于stack exchange,提问作者Sandeepan Nath




