2

我需要将两个工作表与 Apache POI 进行比较。有没有一种简单的方法可以做到这一点,例如工作表比较功能,还是我必须比较每个单元格?

4

3 回答 3

5

由于这是 Google 上出现的关于比较 POI 工作簿的第一个问题,我想分享一个适用于单元测试的解决方案。我找到了一个很好的 Hamcrest 匹配器来解决这个问题:

http://baddotrobot.com/blog/2012/09/14/diff-excel-with-java-and-hamcrest/

基本上,通过 Maven 导入库(在 Github README 中有详细说明)。一旦你有两个 POI 工作簿,你就可以编写一个类似于下面的断言:

MatcherAssert.assertThat("Workbooks to be identical", actualWorkbook,
    WorkbookMatcher.sameWorkbook(expectedWorkbook));

注意:我在这里使用 MatcherAssert 来检索更详细的比较注释,但 JUnit Assert 也可以使用。这在作者的网站上有说明。

它可以在GitHub 上以及通过作者的个人 Maven 存储库获得。

于 2015-05-01T20:30:11.437 回答
1
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.junit.Assert;


public class CompareExcel {

    public static void assertWorkbooksEqual(final XSSFWorkbook workbookA, final XSSFWorkbook workbookB) {
        for (int i = 0; i < workbookA.getNumberOfSheets(); i++) {
            final XSSFSheet sheetA = workbookA.getSheetAt(i);
            final XSSFSheet sheetB = workbookB.getSheetAt(i);

            compareTwoSheets(sheetA, sheetB);
        }
    }

    private static void compareTwoSheets(final XSSFSheet sheetA, final XSSFSheet sheetB) {
        final int firstRowA = sheetA.getFirstRowNum();
        final int lastRowB = sheetA.getLastRowNum();


        final String sheetName = sheetA.getSheetName();
        Assert.assertEquals(sheetName, sheetB.getSheetName());

        Assert.assertEquals("In sheet: " + sheetName, firstRowA, sheetB.getFirstRowNum());
        Assert.assertEquals("In sheet: " + sheetName, lastRowB, sheetB.getLastRowNum());

        for(int i=firstRowA; i <= lastRowB; i++) {

            final XSSFRow rowA = sheetA.getRow(i);
            final XSSFRow rowB = sheetB.getRow(i);

            compareTwoRows(sheetName, rowA, rowB);
        }
    }

    private static void compareTwoRows(final String sheetName, final XSSFRow rowA, final XSSFRow rowB) {
        if((rowA == null) && (rowB == null)) {
            return;
        }
        Assert.assertNotNull("In sheet: " + sheetName, rowA);
        Assert.assertNotNull("In sheet: " + sheetName, rowB);

        final int firstCellA = rowA.getFirstCellNum();
        final int lastCellA = rowA.getLastCellNum();

        Assert.assertEquals("In sheet: " + sheetName, firstCellA, rowB.getFirstCellNum());
        Assert.assertEquals("In sheet: " + sheetName, lastCellA, rowB.getLastCellNum());

        for(int i=firstCellA; i <= lastCellA; i++) {
            final XSSFCell cellA = rowA.getCell(i);
            final XSSFCell cellB = rowB.getCell(i);
            compareTwoCells(sheetName, cellA, cellB);
        }
    }

    private static void compareTwoCells(final String sheetName, final XSSFCell cellA, final XSSFCell cellB) {
        if((cellA == null) && (cellB == null)) {
            return;
        }
        Assert.assertNotNull(cellA);
        Assert.assertNotNull(cellB);

        String valueA = null;
        String valueB = null;

        Assert.assertEquals(cellA.getCellTypeEnum(), cellB.getCellTypeEnum());

        switch(cellA.getCellTypeEnum()) {
            case NUMERIC:
                valueA = String.valueOf(cellA.getNumericCellValue());
                valueB = String.valueOf(cellB.getNumericCellValue());
                break;
            case STRING:
                valueA = cellA.getStringCellValue();
                valueB = cellB.getStringCellValue();
                break;
            default:
                Assert.fail(
                        String.format(
                                "Unexpected cell type '%s' in sheet: '%s' row: '%s' column: '%s'",
                                cellA.getCellTypeEnum().name(),
                                sheetName,
                                cellA.getRowIndex(),
                                cellA.getColumnIndex()
                        ));
        }

        Assert.assertEquals(
                String.format(
                        "Cell values do not match in sheet: '%s' row: '%s' column: '%s'",
                        sheetName,
                        cellA.getRowIndex(),
                        cellA.getColumnIndex()
                ),
                valueA, valueB);
    }
}
于 2021-01-15T16:36:06.223 回答
-1

尝试遍历所有单元格并计算正在运行的哈希或类似的东西。您运行它两次,每个工作表一次,如果哈希相同 - 工作表是相同的。AFAIK,没有开箱即用的方法可以做到这一点。

我相信这是一种比逐个单元进行比较更好的方法,因为您一次只能打开一个工作表(而不是逐个单元方法中的两个工作表)。

于 2012-10-22T09:42:34.510 回答