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

Java实现.xlsx与.csv文件单元格值对比的技术求助

XLSX与CSV单元格逐位对比的实现方案

核心思路

把XLSX和CSV的行、单元格遍历整合到同一个双层循环中,同时处理两者行/列数不一致的边界情况,统一将单元格值转为字符串后再对比,避免类型差异导致的误判。

关键实现代码

确保项目已引入Apache POI和OpenCSV依赖,先导入必要包:

import org.apache.poi.ss.usermodel.*;
import com.opencsv.CSVReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.util.List;

1. XLSX单元格值统一转换工具方法

处理XLSX中不同类型的单元格(字符串、数字、日期、公式等),统一转为字符串格式:

private static String getCellValue(Cell cell) {
    if (cell == null) {
        return "";
    }
    switch (cell.getCellType()) {
        case STRING:
            return cell.getStringCellValue().trim();
        case NUMERIC:
            if (DateUtil.isCellDateFormatted(cell)) {
                // 可根据需求调整日期格式化规则
                return cell.getDateCellValue().toString();
            } else {
                // 避免数字转为科学计数法,直接转字符串
                return String.valueOf(cell.getNumericCellValue()).trim();
            }
        case BOOLEAN:
            return String.valueOf(cell.getBooleanCellValue()).trim();
        case FORMULA:
            // 计算公式结果并递归获取值
            FormulaEvaluator evaluator = cell.getSheet().getWorkbook().getCreationHelper().createFormulaEvaluator();
            return getCellValue(evaluator.evaluateInCell(cell));
        default:
            return "";
    }
}

2. 主对比逻辑

将行遍历和单元格对比整合,覆盖所有行/列的对比场景:

public void compareXlsxAndCsv(String xlsxFilePath, String csvFilePath) {
    try (Workbook workbook = WorkbookFactory.create(new FileInputStream(xlsxFilePath));
         CSVReader csvReader = new CSVReader(new FileReader(csvFilePath))) {

        Sheet xlsxSheet = workbook.getSheetAt(0); // 读取XLSX第一个工作表
        List<String[]> csvRows = csvReader.readAll(); // 读取所有CSV行

        // 取两者最大行数,确保遍历完所有行(包括其中一个文件行数更多的情况)
        int totalRows = Math.max(xlsxSheet.getLastRowNum() + 1, csvRows.size());

        for (int rowIdx = 0; rowIdx < totalRows; rowIdx++) {
            Row xlsxRow = xlsxSheet.getRow(rowIdx);
            String[] csvRow = rowIdx < csvRows.size() ? csvRows.get(rowIdx) : new String[0];

            // 取当前行的最大列数,处理列数不一致的情况
            int totalCols = 0;
            if (xlsxRow != null) {
                totalCols = Math.max(totalCols, xlsxRow.getLastCellNum());
            }
            totalCols = Math.max(totalCols, csvRow.length);

            // 逐单元格对比
            for (int colIdx = 0; colIdx < totalCols; colIdx++) {
                // 获取XLSX单元格值
                String xlsxVal = "";
                if (xlsxRow != null) {
                    Cell cell = xlsxRow.getCell(colIdx);
                    xlsxVal = getCellValue(cell);
                }

                // 获取CSV单元格值
                String csvVal = colIdx < csvRow.length ? csvRow[colIdx].trim() : "";

                // 对比并输出差异
                if (!xlsxVal.equals(csvVal)) {
                    System.out.printf("差异位置:行%d,列%d%nXLSX值:%s%nCSV值:%s%n---%n", rowIdx + 1, colIdx + 1, xlsxVal, csvVal);
                }
            }
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
}

注意事项

  • 使用try-with-resources自动关闭流,避免资源泄漏
  • 对比前对所有值做trim()处理,避免因首尾空格导致的误判
  • 处理XLSX公式单元格时,默认取计算结果,若需对比公式可修改工具方法
  • 若XLSX包含多个工作表,可在外层增加工作表遍历循环

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 00:11:00