diff --git a/.classpath b/.classpath index 5efa12f1e..72367da8d 100644 --- a/.classpath +++ b/.classpath @@ -10,6 +10,7 @@ + diff --git a/src/contrib/src/org/apache/poi/ss/ExcelComparator.java b/src/contrib/src/org/apache/poi/ss/ExcelComparator.java new file mode 100644 index 000000000..f1e658734 --- /dev/null +++ b/src/contrib/src/org/apache/poi/ss/ExcelComparator.java @@ -0,0 +1,1348 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ +package org.apache.poi.ss; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.DateUtil; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.util.CellReference; +import org.apache.poi.xssf.usermodel.XSSFCellStyle; +import org.apache.poi.xssf.usermodel.XSSFColor; + +/** + * Utility to compare Excel File Contents cell by cell for all sheets. + * + *

This utility will be used to compare Excel File Contents cell by cell for all sheets programmatically.

+ * + *

Below are the list of Attribute comparison supported in this version.

+ * + *
    + *
  • Cell Alignment
  • + *
  • Cell Border Attributes
  • + *
  • Cell Data
  • + *
  • Cell Data-Type
  • + *
  • Cell Fill Color
  • + *
  • Cell Fill pattern
  • + *
  • Cell Font Attributes
  • + *
  • Cell Font Family
  • + *
  • Cell Font Size
  • + *
  • Cell Protection
  • + *
  • Name of the sheets
  • + *
  • Number of Columns
  • + *
  • Number of Rows
  • + *
  • Number of Sheet
  • + *
+ * + *

(Some of the above attribute comparison only work for *.xlsx format currently. In future it can be enhanced.)

+ * + *

Usage:

+ * + *
+ * {@code
+ *  Workbook wb1 = WorkbookFactory.create(new File("workBook1.xls"));
+ *  Workbook wb2 = WorkbookFactory.create(new File("workBook2.xls"));
+ *  ExcelFileDifference excelFileDifference = ExcelComparator.compare(wb1, wb2);
+ *  for (String differences : excelFileDifference.listOfDifferences)
+ *      System.out.println(differences);
+ *  System.out.println("DifferenceFound = "+ excelFileDifference.isDifferenceFound);
+ *  }
+ * 
+ */ +public class ExcelComparator { + + private static final String BOLD = "BOLD"; + private static final String BOTTOM_BORDER = "BOTTOM BORDER"; + private static final String BRACKET_END = "]"; + private static final String BRACKET_START = " ["; + private static final String CELL_ALIGNMENT_DOES_NOT_MATCH = "Cell Alignment does not Match ::"; + private static final String CELL_BORDER_ATTRIBUTES_DOES_NOT_MATCH = "Cell Border Attributes does not Match ::"; + private static final String CELL_DATA_DOES_NOT_MATCH = "Cell Data does not Match ::"; + private static final String CELL_DATA_TYPE_DOES_NOT_MATCH = "Cell Data-Type does not Match in :: "; + private static final String CELL_FILL_COLOR_DOES_NOT_MATCH = "Cell Fill Color does not Match ::"; + private static final String CELL_FILL_PATTERN_DOES_NOT_MATCH = "Cell Fill pattern does not Match ::"; + private static final String CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH = "Cell Font Attributes does not Match ::"; + private static final String CELL_FONT_FAMILY_DOES_NOT_MATCH = "Cell Font Family does not Match ::"; + private static final String CELL_FONT_SIZE_DOES_NOT_MATCH = "Cell Font Size does not Match ::"; + private static final String CELL_PROTECTION_DOES_NOT_MATCH = "Cell Protection does not Match ::"; + private static final String ITALICS = "ITALICS"; + private static final String LEFT_BORDER = "LEFT BORDER"; + private static final String LINE_SEPARATOR = "line.separator"; + private static final String NAME_OF_THE_SHEETS_DO_NOT_MATCH = "Name of the sheets do not match :: "; + private static final String NEXT_STR = " -> "; + private static final String NO_BOTTOM_BORDER = "NO BOTTOM BORDER"; + private static final String NO_COLOR = "NO COLOR"; + private static final String NO_LEFT_BORDER = "NO LEFT BORDER"; + private static final String NO_RIGHT_BORDER = "NO RIGHT BORDER"; + private static final String NO_TOP_BORDER = "NO TOP BORDER"; + private static final String NOT_BOLD = "NOT BOLD"; + private static final String NOT_EQUALS = " != "; + private static final String NOT_ITALICS = "NOT ITALICS"; + private static final String NOT_UNDERLINE = "NOT UNDERLINE"; + private static final String NUMBER_OF_COLUMNS_DOES_NOT_MATCH = "Number Of Columns does not Match :: "; + private static final String NUMBER_OF_ROWS_DOES_NOT_MATCH = "Number Of Rows does not Match :: "; + private static final String NUMBER_OF_SHEETS_DO_NOT_MATCH = "Number of Sheets do not match :: "; + private static final String RIGHT_BORDER = "RIGHT BORDER"; + private static final String TOP_BORDER = "TOP BORDER"; + private static final String UNDERLINE = "UNDERLINE"; + private static final String WORKBOOK1 = "workbook1"; + private static final String WORKBOOK2 = "workbook2"; + + /** + * Utility to compare Excel File Contents cell by cell for all sheets. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @return the Excel file difference containing a flag and a list of + * differences + * @throws ExcelCompareException + * the excel compare exception + */ + public static ExcelFileDifference compare(Workbook workbook1, + Workbook workbook2) { + List listOfDifferences = compareWorkBookContents(workbook1, + workbook2); + return populateListOfDifferences(listOfDifferences); + } + + /** + * Compare work book contents. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @return the list + */ + private static List compareWorkBookContents(Workbook workbook1, + Workbook workbook2) { + ExcelComparator excelComparator = new ExcelComparator(); + List listOfDifferences = new ArrayList(); + excelComparator.compareNumberOfSheets(workbook1, workbook2, + listOfDifferences); + excelComparator.compareSheetNames(workbook1, workbook2, + listOfDifferences); + excelComparator.compareSheetData(workbook1, workbook2, + listOfDifferences); + return listOfDifferences; + } + + /** + * Populate list of differences. + * + * @param listOfDifferences + * the list of differences + * @return the excel file difference + */ + private static ExcelFileDifference populateListOfDifferences( + List listOfDifferences) { + ExcelFileDifference excelFileDifference = new ExcelFileDifference(); + excelFileDifference.isDifferenceFound = listOfDifferences.size() > 0; + excelFileDifference.listOfDifferences = listOfDifferences; + return excelFileDifference; + } + + /** + * Compare data in all sheets. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * the list of differences + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareDataInAllSheets(Workbook workbook1, Workbook workbook2, + List listOfDifferences) { + for (int i = 0; i < workbook1.getNumberOfSheets(); i++) { + Sheet sheetWorkBook1 = workbook1.getSheetAt(i); + Sheet sheetWorkBook2; + if (workbook2.getNumberOfSheets() > i) { + sheetWorkBook2 = workbook2.getSheetAt(i); + } else { + sheetWorkBook2 = null; + } + + for (int j = 0; j < sheetWorkBook1.getPhysicalNumberOfRows(); j++) { + Row rowWorkBook1 = sheetWorkBook1.getRow(j); + Row rowWorkBook2; + if (sheetWorkBook2 != null) { + rowWorkBook2 = sheetWorkBook2.getRow(j); + } else { + rowWorkBook2 = null; + } + + if ((rowWorkBook1 == null) || (rowWorkBook2 == null)) { + continue; + } + for (int k = 0; k < rowWorkBook1.getLastCellNum(); k++) { + Cell cellWorkBook1 = rowWorkBook1.getCell(k); + Cell cellWorkBook2 = rowWorkBook2.getCell(k); + + if (!((null == cellWorkBook1) || (null == cellWorkBook2))) { + if (isCellTypeMatches(cellWorkBook1, cellWorkBook2)) { + + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_DATA_TYPE_DOES_NOT_MATCH, + cellWorkBook1.getCellType() + "", + cellWorkBook2.getCellType() + "")); + } + + if (isCellContentTypeBlank(cellWorkBook1)) { + if (isCellContentMatches(cellWorkBook1, + cellWorkBook2)) { + + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, + cellWorkBook1.getRichStringCellValue() + + "", + cellWorkBook2.getRichStringCellValue() + + "")); + + } + + } else if (isCellContentTypeBoolean(cellWorkBook1)) { + if (isCellContentMatchesForBoolean(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, + cellWorkBook1.getBooleanCellValue() + + "", + cellWorkBook2.getBooleanCellValue() + + "")); + + } + + } else if (isCellContentInError(cellWorkBook1)) { + if (isCellContentMatches(cellWorkBook1, + cellWorkBook2)) { + + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, + cellWorkBook1.getRichStringCellValue() + + "", + cellWorkBook2.getRichStringCellValue() + + "")); + + } + } else if (isCellContentFormula(cellWorkBook1)) { + if (isCellContentMatchesForFormula(cellWorkBook1, + cellWorkBook2)) { + + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, + cellWorkBook1.getCellFormula() + "", + cellWorkBook2.getCellFormula() + "")); + + } + + } else if (isCellContentTypeNumeric(cellWorkBook1)) { + if (DateUtil.isCellDateFormatted(cellWorkBook1)) { + if (isCellContentMatchesForDate(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, + cellWorkBook1.getDateCellValue() + + "", + cellWorkBook2.getDateCellValue() + + "")); + + } + } else { + if (isCellContentMatchesForNumeric( + cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, + cellWorkBook1.getNumericCellValue() + + "", + cellWorkBook2.getNumericCellValue() + + "")); + + } + } + + } else if (isCellContentTypeString(cellWorkBook1)) { + if (isCellContentMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, + cellWorkBook2, + CELL_DATA_DOES_NOT_MATCH, cellWorkBook1 + .getRichStringCellValue() + .getString(), cellWorkBook2 + .getRichStringCellValue() + .getString())); + } + } + + if (isCellFillPatternMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_FILL_PATTERN_DOES_NOT_MATCH, + cellWorkBook1.getCellStyle() + .getFillPattern() + "", + cellWorkBook2.getCellStyle() + .getFillPattern() + "")); + + } + + if (isCellAlignmentMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_ALIGNMENT_DOES_NOT_MATCH, + cellWorkBook1.getRichStringCellValue() + .getString(), cellWorkBook2 + .getRichStringCellValue() + .getString())); + + } + + if (isCellHiddenMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences + .add(getMessage(workbook1, workbook2, i, + cellWorkBook1, cellWorkBook2, + CELL_PROTECTION_DOES_NOT_MATCH, + cellWorkBook1.getCellStyle() + .getHidden() ? "HIDDEN" + : "NOT HIDDEN", + cellWorkBook2.getCellStyle() + .getHidden() ? "HIDDEN" + : "NOT HIDDEN")); + + } + + if (isCellLockedMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences + .add(getMessage(workbook1, workbook2, i, + cellWorkBook1, cellWorkBook2, + CELL_PROTECTION_DOES_NOT_MATCH, + cellWorkBook1.getCellStyle() + .getLocked() ? "LOCKED" + : "NOT LOCKED", + cellWorkBook2.getCellStyle() + .getLocked() ? "LOCKED" + : "NOT LOCKED")); + + } + + if (isCellFontFamilyMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_FONT_FAMILY_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()).getFont() + .getFontName(), + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont() + .getFontName())); + + } + + if (isCellFontSizeMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_FONT_SIZE_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()).getFont() + .getFontHeightInPoints() + + "", + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont() + .getFontHeightInPoints() + + "")); + + } + + if (isCellFontBoldMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()).getFont() + .getBold() ? BOLD : NOT_BOLD, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont() + .getBold() ? BOLD : NOT_BOLD)); + + } + + if (isCellUnderLineMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()).getFont() + .getUnderline() == 1 ? UNDERLINE + : NOT_UNDERLINE, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont() + .getUnderline() == 1 ? UNDERLINE + : NOT_UNDERLINE)); + + } + + if (isCellFontItalicsMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage(workbook1, + workbook2, i, cellWorkBook1, cellWorkBook2, + CELL_FONT_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()).getFont() + .getItalic() ? ITALICS + : NOT_ITALICS, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont() + .getItalic() ? ITALICS + : NOT_ITALICS)); + + } + + if (isCellBorderBottomMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences + .add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_BORDER_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()) + .getBorderBottom() == 1 ? BOTTOM_BORDER + : NO_BOTTOM_BORDER, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()) + .getBorderBottom() == 1 ? BOTTOM_BORDER + : NO_BOTTOM_BORDER)); + + } + + if (isCellBorderLeftMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences + .add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_BORDER_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()) + .getBorderLeft() == 1 ? LEFT_BORDER + : NO_LEFT_BORDER, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()) + .getBorderLeft() == 1 ? LEFT_BORDER + : NO_LEFT_BORDER)); + + } + + if (isCellBorderRightMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences + .add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_BORDER_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()) + .getBorderRight() == 1 ? RIGHT_BORDER + : NO_RIGHT_BORDER, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()) + .getBorderRight() == 1 ? RIGHT_BORDER + : NO_RIGHT_BORDER)); + + } + + if (isCellBorderTopMatches(cellWorkBook1, cellWorkBook2)) { + listOfDifferences + .add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_BORDER_ATTRIBUTES_DOES_NOT_MATCH, + ((XSSFCellStyle) cellWorkBook1 + .getCellStyle()) + .getBorderTop() == 1 ? TOP_BORDER + : NO_TOP_BORDER, + ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()) + .getBorderTop() == 1 ? TOP_BORDER + : NO_TOP_BORDER)); + + } + + if (isCellBackGroundFillMatchesAndEmpty(cellWorkBook1, + cellWorkBook2)) { + continue; + } else if (isCellFillBackGroundMatchesAndEitherEmpty( + cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_FILL_COLOR_DOES_NOT_MATCH, + NO_COLOR, + ((XSSFColor) cellWorkBook2.getCellStyle() + .getFillForegroundColorColor()) + .getARGBHex() + + "")); + + } else if (isCellFillBackGroundMatchesAndSecondEmpty( + cellWorkBook1, cellWorkBook2)) { + listOfDifferences.add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_FILL_COLOR_DOES_NOT_MATCH, + ((XSSFColor) cellWorkBook1.getCellStyle() + .getFillForegroundColorColor()) + .getARGBHex() + + "", NO_COLOR)); + + } else { + if (isCellFileBackGroundMatches(cellWorkBook1, + cellWorkBook2)) { + listOfDifferences.add(getMessage( + workbook1, + workbook2, + i, + cellWorkBook1, + cellWorkBook2, + CELL_FILL_COLOR_DOES_NOT_MATCH, + ((XSSFColor) cellWorkBook1 + .getCellStyle() + .getFillForegroundColorColor()) + .getARGBHex() + + "", + ((XSSFColor) cellWorkBook2 + .getCellStyle() + .getFillForegroundColorColor()) + .getARGBHex() + + "")); + + } + } + + } + } + } + } + } + + /** + * Compare number of columns in sheets. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * the list of differences + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareNumberOfColumnsInSheets(Workbook workbook1, + Workbook workbook2, List listOfDifferences) { + for (int i = 0; i < workbook1.getNumberOfSheets(); i++) { + Sheet sheetWorkBook1 = workbook1.getSheetAt(i); + Sheet sheetWorkBook2; + if (workbook2.getNumberOfSheets() > i) { + sheetWorkBook2 = workbook2.getSheetAt(i); + } else { + sheetWorkBook2 = null; + } + if (isWorkBookEmpty(sheetWorkBook1, sheetWorkBook2)) { + if (isNumberOfColumnsMatches(sheetWorkBook1, sheetWorkBook2)) { + String noOfCols; + String sheetName; + if (sheetWorkBook2 != null) { + noOfCols = sheetWorkBook2.getRow(0).getLastCellNum() + + ""; + sheetName = workbook2.getSheetName(i); + } else { + noOfCols = ""; + sheetName = ""; + } + short lastCellNumForWbk1 = sheetWorkBook1.getRow(0) != null ? sheetWorkBook1 + .getRow(0).getLastCellNum() : 0; + listOfDifferences.add(NUMBER_OF_COLUMNS_DOES_NOT_MATCH + + System.getProperty(LINE_SEPARATOR) + WORKBOOK1 + + NEXT_STR + workbook1.getSheetName(i) + NEXT_STR + + lastCellNumForWbk1 + NOT_EQUALS + WORKBOOK2 + + NEXT_STR + sheetName + NEXT_STR + noOfCols); + } + } + } + } + + /** + * Compare number of rows in sheets. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * the list of differences + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareNumberOfRowsInSheets(Workbook workbook1, + Workbook workbook2, List listOfDifferences) { + for (int i = 0; i < workbook1.getNumberOfSheets(); i++) { + Sheet sheetWorkBook1 = workbook1.getSheetAt(i); + Sheet sheetWorkBook2; + if (workbook2.getNumberOfSheets() > i) { + sheetWorkBook2 = workbook2.getSheetAt(i); + } else { + sheetWorkBook2 = null; + } + if (isNumberOfRowsMatches(sheetWorkBook1, sheetWorkBook2)) { + String noOfRows; + String sheetName; + if (sheetWorkBook2 != null) { + noOfRows = sheetWorkBook2.getPhysicalNumberOfRows() + ""; + sheetName = workbook2.getSheetName(i); + } else { + noOfRows = ""; + sheetName = ""; + } + listOfDifferences.add(NUMBER_OF_ROWS_DOES_NOT_MATCH + + System.getProperty(LINE_SEPARATOR) + WORKBOOK1 + + NEXT_STR + workbook1.getSheetName(i) + NEXT_STR + + sheetWorkBook1.getPhysicalNumberOfRows() + NOT_EQUALS + + WORKBOOK2 + NEXT_STR + sheetName + NEXT_STR + + noOfRows); + } + } + + } + + /** + * Compare number of sheets. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareNumberOfSheets(Workbook workbook1, Workbook workbook2, + List listOfDifferences) { + if (isNumberOfSheetsMatches(workbook1, workbook2)) { + listOfDifferences.add(NUMBER_OF_SHEETS_DO_NOT_MATCH + + System.getProperty(LINE_SEPARATOR) + WORKBOOK1 + NEXT_STR + + workbook1.getNumberOfSheets() + NOT_EQUALS + WORKBOOK2 + + NEXT_STR + workbook2.getNumberOfSheets()); + } + } + + /** + * Compare sheet data. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareSheetData(Workbook workbook1, Workbook workbook2, + List listOfDifferences) { + compareNumberOfRowsInSheets(workbook1, workbook2, listOfDifferences); + compareNumberOfColumnsInSheets(workbook1, workbook2, listOfDifferences); + compareDataInAllSheets(workbook1, workbook2, listOfDifferences); + + } + + /** + * Compare sheet names. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param listOfDifferences + * + * @throws ExcelCompareException + * the excel compare exception + */ + private void compareSheetNames(Workbook workbook1, Workbook workbook2, + List listOfDifferences) { + for (int i = 0; i < workbook1.getNumberOfSheets(); i++) { + if (isNameOfSheetMatches(workbook1, workbook2, i)) { + String sheetname = workbook2.getNumberOfSheets() > i ? workbook2 + .getSheetName(i) : ""; + listOfDifferences.add(NAME_OF_THE_SHEETS_DO_NOT_MATCH + + System.getProperty(LINE_SEPARATOR) + WORKBOOK1 + + NEXT_STR + workbook1.getSheetName(i) + BRACKET_START + + (i + 1) + BRACKET_END + NOT_EQUALS + WORKBOOK2 + + NEXT_STR + sheetname + BRACKET_START + (i + 1) + + BRACKET_END); + } + } + } + + /** + * Gets the message. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param i + * the i + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @param messageStart + * the message start + * @param workBook1Value + * the work book1 value + * @param workBook2Value + * the work book2 value + * @return the message + */ + private String getMessage(Workbook workbook1, Workbook workbook2, int i, + Cell cellWorkBook1, Cell cellWorkBook2, String messageStart, + String workBook1Value, String workBook2Value) { + StringBuilder sb = new StringBuilder(); + return sb + .append(messageStart) + .append(System.getProperty(LINE_SEPARATOR)) + .append(WORKBOOK1) + .append(NEXT_STR) + .append(workbook1.getSheetName(i)) + .append(NEXT_STR) + .append(new CellReference(cellWorkBook1.getRowIndex(), + cellWorkBook1.getColumnIndex()).formatAsString()) + .append(BRACKET_START) + .append(workBook1Value) + .append(BRACKET_END) + .append(NOT_EQUALS) + .append(WORKBOOK2) + .append(NEXT_STR) + .append(workbook2.getSheetName(i)) + .append(NEXT_STR) + .append(new CellReference(cellWorkBook2.getRowIndex(), + cellWorkBook2.getColumnIndex()).formatAsString()) + .append(BRACKET_START).append(workBook2Value) + .append(BRACKET_END).toString(); + } + + /** + * Checks if cell alignment matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell alignment matches + */ + private boolean isCellAlignmentMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + return cellWorkBook1.getCellStyle().getAlignment() != cellWorkBook2 + .getCellStyle().getAlignment(); + } + + /** + * Checks if cell back ground fill matches and empty. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell back ground fill matches and empty + */ + private boolean isCellBackGroundFillMatchesAndEmpty(Cell cellWorkBook1, + Cell cellWorkBook2) { + return (cellWorkBook1.getCellStyle().getFillForegroundColorColor() == null) + && (cellWorkBook2.getCellStyle().getFillForegroundColorColor() == null); + } + + /** + * Checks if cell border bottom matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell border bottom matches + */ + private boolean isCellBorderBottomMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()) + .getBorderBottom() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getBorderBottom(); + } else { + return false; + } + + } + + /** + * Checks if cell border left matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell border left matches + */ + private boolean isCellBorderLeftMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()) + .getBorderLeft() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getBorderLeft(); + } else { + return false; + } + + } + + /** + * Checks if cell border right matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell border right matches + */ + private boolean isCellBorderRightMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()) + .getBorderRight() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getBorderRight(); + } else { + return false; + } + + } + + /** + * Checks if cell border top matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell border top matches + */ + private boolean isCellBorderTopMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()) + .getBorderTop() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getBorderTop(); + } else { + return false; + } + + } + + /** + * Checks if cell content formula. + * + * @param cellWorkBook1 + * the cell work book1 + * @return true, if cell content formula + */ + private boolean isCellContentFormula(Cell cellWorkBook1) { + return cellWorkBook1.getCellType() == Cell.CELL_TYPE_FORMULA; + } + + /** + * Checks if cell content in error. + * + * @param cellWorkBook1 + * the cell work book1 + * @return true, if cell content in error + */ + private boolean isCellContentInError(Cell cellWorkBook1) { + return cellWorkBook1.getCellType() == Cell.CELL_TYPE_ERROR; + } + + /** + * Checks if cell content matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell content matches + */ + private boolean isCellContentMatches(Cell cellWorkBook1, Cell cellWorkBook2) { + return !(cellWorkBook1.getRichStringCellValue().getString() + .equals(cellWorkBook2.getRichStringCellValue().getString())); + } + + /** + * Checks if cell content matches for boolean. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell content matches for boolean + */ + private boolean isCellContentMatchesForBoolean(Cell cellWorkBook1, + Cell cellWorkBook2) { + return !(cellWorkBook1.getBooleanCellValue() == cellWorkBook2 + .getBooleanCellValue()); + } + + /** + * Checks if cell content matches for date. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell content matches for date + */ + private boolean isCellContentMatchesForDate(Cell cellWorkBook1, + Cell cellWorkBook2) { + return !(cellWorkBook1.getDateCellValue().equals(cellWorkBook2 + .getDateCellValue())); + } + + /** + * Checks if cell content matches for formula. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell content matches for formula + */ + private boolean isCellContentMatchesForFormula(Cell cellWorkBook1, + Cell cellWorkBook2) { + return !(cellWorkBook1.getCellFormula().equals(cellWorkBook2 + .getCellFormula())); + } + + /** + * Checks if cell content matches for numeric. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell content matches for numeric + */ + private boolean isCellContentMatchesForNumeric(Cell cellWorkBook1, + Cell cellWorkBook2) { + return !(cellWorkBook1.getNumericCellValue() == cellWorkBook2 + .getNumericCellValue()); + } + + /** + * Checks if cell content type blank. + * + * @param cellWorkBook1 + * the cell work book1 + * @return true, if cell content type blank + */ + private boolean isCellContentTypeBlank(Cell cellWorkBook1) { + return cellWorkBook1.getCellType() == Cell.CELL_TYPE_BLANK; + } + + /** + * Checks if cell content type boolean. + * + * @param cellWorkBook1 + * the cell work book1 + * @return true, if cell content type boolean + */ + private boolean isCellContentTypeBoolean(Cell cellWorkBook1) { + return cellWorkBook1.getCellType() == Cell.CELL_TYPE_BOOLEAN; + } + + /** + * Checks if cell content type numeric. + * + * @param cellWorkBook1 + * the cell work book1 + * @return true, if cell content type numeric + */ + private boolean isCellContentTypeNumeric(Cell cellWorkBook1) { + return cellWorkBook1.getCellType() == Cell.CELL_TYPE_NUMERIC; + } + + /** + * Checks if cell content type string. + * + * @param cellWorkBook1 + * the cell work book1 + * @return true, if cell content type string + */ + private boolean isCellContentTypeString(Cell cellWorkBook1) { + return cellWorkBook1.getCellType() == Cell.CELL_TYPE_STRING; + } + + /** + * Checks if cell file back ground matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell file back ground matches + */ + private boolean isCellFileBackGroundMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return !((XSSFColor) cellWorkBook1.getCellStyle() + .getFillForegroundColorColor()).getARGBHex().equals( + ((XSSFColor) cellWorkBook2.getCellStyle() + .getFillForegroundColorColor()).getARGBHex()); + } else { + return false; + } + + } + + /** + * Checks if cell fill back ground matches and either empty. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell fill back ground matches and either empty + */ + private boolean isCellFillBackGroundMatchesAndEitherEmpty( + Cell cellWorkBook1, Cell cellWorkBook2) { + return (cellWorkBook1.getCellStyle().getFillForegroundColorColor() == null) + && (cellWorkBook2.getCellStyle().getFillForegroundColorColor() != null); + } + + /** + * Checks if cell fill back ground matches and second empty. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell fill back ground matches and second empty + */ + private boolean isCellFillBackGroundMatchesAndSecondEmpty( + Cell cellWorkBook1, Cell cellWorkBook2) { + return (cellWorkBook1.getCellStyle().getFillForegroundColorColor() != null) + && (cellWorkBook2.getCellStyle().getFillForegroundColorColor() == null); + } + + /** + * Checks if cell fill pattern matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell fill pattern matches + */ + private boolean isCellFillPatternMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + return cellWorkBook1.getCellStyle().getFillPattern() != cellWorkBook2 + .getCellStyle().getFillPattern(); + } + + /** + * Checks if cell font bold matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell font bold matches + */ + private boolean isCellFontBoldMatches(Cell cellWorkBook1, Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()).getFont() + .getBold() != ((XSSFCellStyle) cellWorkBook2.getCellStyle()) + .getFont().getBold(); + } else { + return false; + } + + } + + /** + * Checks if cell font family matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell font family matches + */ + private boolean isCellFontFamilyMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return !(((XSSFCellStyle) cellWorkBook1.getCellStyle()).getFont() + .getFontName().equals(((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont().getFontName())); + } else { + return false; + } + } + + /** + * Checks if cell font italics matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell font italics matches + */ + private boolean isCellFontItalicsMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()).getFont() + .getItalic() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont().getItalic(); + } else { + return false; + } + + } + + /** + * Checks if cell font size matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell font size matches + */ + private boolean isCellFontSizeMatches(Cell cellWorkBook1, Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()).getFont() + .getFontHeightInPoints() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont().getFontHeightInPoints(); + } else { + return false; + } + + } + + /** + * Checks if cell hidden matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell hidden matches + */ + private boolean isCellHiddenMatches(Cell cellWorkBook1, Cell cellWorkBook2) { + return cellWorkBook1.getCellStyle().getHidden() != cellWorkBook2 + .getCellStyle().getHidden(); + } + + /** + * Checks if cell locked matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell locked matches + */ + private boolean isCellLockedMatches(Cell cellWorkBook1, Cell cellWorkBook2) { + return cellWorkBook1.getCellStyle().getLocked() != cellWorkBook2 + .getCellStyle().getLocked(); + } + + /** + * Checks if cell type matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell type matches + */ + private boolean isCellTypeMatches(Cell cellWorkBook1, Cell cellWorkBook2) { + return !(cellWorkBook1.getCellType() == cellWorkBook2.getCellType()); + } + + /** + * Checks if cell under line matches. + * + * @param cellWorkBook1 + * the cell work book1 + * @param cellWorkBook2 + * the cell work book2 + * @return true, if cell under line matches + */ + private boolean isCellUnderLineMatches(Cell cellWorkBook1, + Cell cellWorkBook2) { + if (cellWorkBook1.getCellStyle() instanceof XSSFCellStyle) { + return ((XSSFCellStyle) cellWorkBook1.getCellStyle()).getFont() + .getUnderline() != ((XSSFCellStyle) cellWorkBook2 + .getCellStyle()).getFont().getUnderline(); + } else { + return false; + } + + } + + /** + * Checks if name of sheet matches. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @param i + * the i + * @return true, if name of sheet matches + */ + private boolean isNameOfSheetMatches(Workbook workbook1, + Workbook workbook2, int i) { + if (workbook2.getNumberOfSheets() > i) { + return !(workbook1.getSheetName(i) + .equals(workbook2.getSheetName(i))); + } else { + return true; + } + + } + + /** + * Checks if number of columns matches. + * + * @param sheetWorkBook1 + * the sheet work book1 + * @param sheetWorkBook2 + * the sheet work book2 + * @return true, if number of columns matches + */ + private boolean isNumberOfColumnsMatches(Sheet sheetWorkBook1, + Sheet sheetWorkBook2) { + if (sheetWorkBook2 != null) { + return !(sheetWorkBook1.getRow(0).getLastCellNum() == sheetWorkBook2 + .getRow(0).getLastCellNum()); + } else { + return true; + } + + } + + /** + * Checks if number of rows matches. + * + * @param sheetWorkBook1 + * the sheet work book1 + * @param sheetWorkBook2 + * the sheet work book2 + * @return true, if number of rows matches + */ + private boolean isNumberOfRowsMatches(Sheet sheetWorkBook1, + Sheet sheetWorkBook2) { + if (sheetWorkBook2 != null) { + return !(sheetWorkBook1.getPhysicalNumberOfRows() == sheetWorkBook2 + .getPhysicalNumberOfRows()); + } else { + return true; + } + + } + + /** + * Checks if number of sheets matches. + * + * @param workbook1 + * the workbook1 + * @param workbook2 + * the workbook2 + * @return true, if number of sheets matches + */ + private boolean isNumberOfSheetsMatches(Workbook workbook1, + Workbook workbook2) { + return !(workbook1.getNumberOfSheets() == workbook2.getNumberOfSheets()); + } + + private boolean isWorkBookEmpty(Sheet sheetWorkBook1, Sheet sheetWorkBook2) { + if (sheetWorkBook2 != null) { + return !((null == sheetWorkBook1.getRow(0)) || (null == sheetWorkBook2 + .getRow(0))); + } else { + return true; + } + + } + +} + +class ExcelFileDifference { + boolean isDifferenceFound; + List listOfDifferences; +}