如何使用Java提取Excel第0列重复值对应记录并写入新文件
实现Excel重复值记录筛选与导出
没问题,我来帮你改造代码,实现提取第0列存在重复值的对应记录并写入新文件的需求。核心思路是先统计第0列每个值的出现频率,再筛选出值重复的整行记录,最后把这些记录导出到新Excel里。
完整代码实现
import org.apache.poi.ss.usermodel.*; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import java.io.FileInputStream; import java.io.FileOutputStream; import java.util.*; public class ExcelDuplicateExtractor { public static void main(String[] args) { try { String sourceFilePath = "你的源文件路径.xlsx"; String targetFilePath = "导出的重复记录文件.xlsx"; // 读取源Excel文件 FileInputStream fis = new FileInputStream(sourceFilePath); XSSFWorkbook sourceWorkbook = new XSSFWorkbook(fis); Sheet sourceSheet = sourceWorkbook.getSheetAt(0); // 第一步:统计第0列每个值的出现次数 Map<String, Integer> valueCountMap = new HashMap<>(); for (int rowIndex = 0; rowIndex <= sourceSheet.getLastRowNum(); rowIndex++) { Row row = sourceSheet.getRow(rowIndex); if (row == null) continue; Cell cell = row.getCell(0); String cellValue = getCellStringValue(cell); if (cellValue == null || cellValue.trim().isEmpty()) continue; // 更新计数 valueCountMap.put(cellValue, valueCountMap.getOrDefault(cellValue, 0) + 1); } // 第二步:筛选出第0列值重复的整行记录 List<Row> duplicateRows = new ArrayList<>(); for (int rowIndex = 0; rowIndex <= sourceSheet.getLastRowNum(); rowIndex++) { Row row = sourceSheet.getRow(rowIndex); if (row == null) continue; Cell cell = row.getCell(0); String cellValue = getCellStringValue(cell); if (cellValue == null || cellValue.trim().isEmpty()) continue; // 如果该值出现次数大于1,说明是重复记录 if (valueCountMap.get(cellValue) > 1) { duplicateRows.add(row); } } // 第三步:将筛选后的记录写入新Excel文件 XSSFWorkbook targetWorkbook = new XSSFWorkbook(); Sheet targetSheet = targetWorkbook.createSheet("重复记录"); // 复制表头(如果有)和重复行 for (int i = 0; i < duplicateRows.size(); i++) { Row sourceRow = duplicateRows.get(i); Row targetRow = targetSheet.createRow(i); // 复制每一个单元格的值和样式 for (int colIndex = 0; colIndex < sourceRow.getLastCellNum(); colIndex++) { Cell sourceCell = sourceRow.getCell(colIndex); if (sourceCell == null) continue; Cell targetCell = targetRow.createCell(colIndex); copyCellValueAndStyle(sourceCell, targetCell); } } // 自动调整列宽 for (int colIndex = 0; colIndex < sourceSheet.getLastCellNum(); colIndex++) { targetSheet.autoSizeColumn(colIndex); } // 写入文件 FileOutputStream fos = new FileOutputStream(targetFilePath); targetWorkbook.write(fos); // 关闭资源 fos.close(); targetWorkbook.close(); sourceWorkbook.close(); fis.close(); System.out.println("重复记录已成功导出到:" + targetFilePath); } catch (Exception e) { e.printStackTrace(); } } // 工具方法:安全获取单元格的字符串值,兼容不同单元格类型 private static String getCellStringValue(Cell cell) { if (cell == null) return null; switch (cell.getCellType()) { case STRING: return cell.getStringCellValue(); case NUMERIC: // 处理数字和日期类型 if (DateUtil.isCellDateFormatted(cell)) { return cell.getDateCellValue().toString(); } else { return String.valueOf(cell.getNumericCellValue()); } case BOOLEAN: return String.valueOf(cell.getBooleanCellValue()); case FORMULA: // 如果是公式,计算后获取值 try { return String.valueOf(cell.getNumericCellValue()); } catch (Exception e) { return cell.getStringCellValue(); } default: return null; } } // 工具方法:复制单元格的值和样式 private static void copyCellValueAndStyle(Cell sourceCell, Cell targetCell) { // 复制样式 targetCell.setCellStyle(sourceCell.getCellStyle()); // 复制值 switch (sourceCell.getCellType()) { case STRING: targetCell.setCellValue(sourceCell.getStringCellValue()); break; case NUMERIC: if (DateUtil.isCellDateFormatted(sourceCell)) { targetCell.setCellValue(sourceCell.getDateCellValue()); } else { targetCell.setCellValue(sourceCell.getNumericCellValue()); } break; case BOOLEAN: targetCell.setCellValue(sourceCell.getBooleanCellValue()); break; case FORMULA: targetCell.setCellFormula(sourceCell.getCellFormula()); break; default: targetCell.setCellValue(""); } } }
关键说明
- 统计频率:用
HashMap记录第0列每个值的出现次数,这样后续判断是否重复就很高效。 - 单元格类型兼容:原代码直接用
getStringCellValue容易报错,新增的getCellStringValue方法能处理数字、日期、布尔值等多种类型,避免类型转换异常。 - 完整行复制:不仅复制单元格的值,还复制样式,保证导出的文件和原表格格式一致。
- 资源关闭:最后记得关闭所有流和Workbook对象,避免资源泄漏。
内容的提问来源于stack exchange,提问作者Dolly
相关产品推荐
相关产品推荐

