// Copyright (c) 2022- schick Informatik // Description: Compares excel files and highlights changes // using System; using System.IO; using System.Drawing; using Microsoft.Office.Interop.Excel; namespace ENI2.Excel { /// /// Diese Klasse beinhaltet den von Anmeldungen unabhängigen Vergleich von Excel Sheets. Damit /// können dann Updates von "außen" einfacher abgearbeitet werden. Zellen und sheets werden bei /// Aktualisierung bunt eingefärbt /// public static class ExcelComparer { private static readonly int diffColor = ColorTranslator.ToOle(Color.FromArgb(150, 150, 255)); // blue private static bool GetSheetRange(Worksheet sheet, out int lastUsedRow, out int lastUsedColumn) { try { // sheet.Columns.ClearFormats(); // sheet.Rows.ClearFormats(); Range usedRange = sheet.UsedRange; lastUsedRow = usedRange.Rows.Count; lastUsedColumn = usedRange.Columns.Count; /* Range last = sheet.Cells.SpecialCells(XlCellType.xlCellTypeLastCell, Type.Missing); Range range = sheet.get_Range("A1", last); lastUsedRow = last.Row; lastUsedColumn = last.Column; */ return true; } catch(Exception) { lastUsedColumn = 0; lastUsedRow = 0; return false; } } private static string GetExcelColumnName(int columnNumber) { string columnName = ""; while (columnNumber > 0) { int modulo = (columnNumber - 1) % 26; columnName = Convert.ToChar('A' + modulo) + columnName; columnNumber = (columnNumber - modulo) / 26; } return columnName; } public static string Compare(string sourcePath, string targetPath, string comparisonFileName, out string errorMessage) { errorMessage = ""; int counter = 0; try { File.Copy(targetPath, comparisonFileName); ExcelReader source = new ExcelReader(sourcePath, true, false); ExcelReader comparison = new ExcelReader(comparisonFileName, false, false); /* erste Variante Vergleich über Namen der Zellen // loop through named cells foreach (string name in comparison.NameDict.Keys) { if (!source.NameDict.ContainsKey(name)) continue; string sourceText = source.ReadText(name); string targetText = comparison.ReadText(name); if (sourceText == null) { if (targetText != null) { comparison.Colorize(name, diffColor); counter++; } } else if (targetText == null) { if (sourceText != null) { comparison.Colorize(name, diffColor); counter++; } } else if ((sourceText != null) && (targetText != null)) { if (!sourceText.Equals(targetText)) { // turn cell blue comparison.Colorize(name, diffColor); counter++; } } } */ // Zweite Version durch alle Sheets werden Zellen der "used range" miteinander verglichen foreach(Worksheet sourceSheet in source.Worksheets) { Worksheet targetSheet = null; foreach(Worksheet sheet in comparison.Worksheets) { if (sourceSheet.Name.Equals(sheet.Name)) { targetSheet = sheet; break; } } if (targetSheet == null) continue; System.Diagnostics.Trace.WriteLine(string.Format("Processing sheet {0}", targetSheet.Name)); if(GetSheetRange(sourceSheet, out int sourceRows, out int sourceCols) && GetSheetRange(targetSheet, out int targetRows, out int targetCols)) { // read source into 2 dim array string rangeString = string.Format("A1:{0}{1}", GetExcelColumnName(Math.Max(sourceCols, targetCols)), Math.Max(sourceRows, targetRows)); object[,] sourceArray = sourceSheet.get_Range(rangeString).Value; // read target into 2 dim array object[,] targetArray = targetSheet.get_Range(rangeString).Value; for (int rowidx = 1; rowidx <= Math.Max(sourceRows, targetRows); rowidx++) { for( int colidx = 1; colidx <= Math.Max(sourceCols, targetCols); colidx++) { string sourceText = null; if(sourceArray[rowidx,colidx] != null) sourceText = sourceArray[rowidx,colidx].ToString(); string targetText = null; if(targetArray[rowidx,colidx] != null) targetText = targetArray[rowidx, colidx].ToString(); if (sourceText == null) { if (targetText != null) { string targetRangeName = string.Format("{0}{1}", GetExcelColumnName(colidx), rowidx); comparison.Colorize(targetSheet.Range[targetRangeName], diffColor); counter++; } } else if (targetText == null) { if (sourceText != null) { string targetRangeName = string.Format("{0}{1}", GetExcelColumnName(colidx), rowidx); comparison.Colorize(targetSheet.Range[targetRangeName], diffColor); counter++; } } else if ((sourceText != null) && (targetText != null)) { if (!sourceText.Equals(targetText)) { string targetRangeName = string.Format("{0}{1}", GetExcelColumnName(colidx), rowidx); // turn cell blue comparison.Colorize(targetSheet.Range[targetRangeName], diffColor); counter++; } } } } } else { errorMessage = "failed to get sheet ranges"; } } comparison.Save(comparisonFileName); source.Dispose(); comparison.Dispose(); errorMessage = string.Format("{0} differences found", counter); } catch (Exception ex) { errorMessage = ex.Message; } return comparisonFileName; } } }