Excel Vergleich funktioniert jetzt mit Ranges statt benannten Feldern. Es läuft auch wesentlich schneller, weil der Zugriff auf die Ranges über einen Array und nicht mehr einzeln erfolgt. Diese Funktion kann jetzt auf beliebige Excel auch außerhalb vom NSW angewandt werden.

This commit is contained in:
Daniel Schick 2022-06-28 14:46:39 +02:00
parent e8a4fcb227
commit f596a53a38
3 changed files with 123 additions and 12 deletions

View File

@ -25,7 +25,7 @@ namespace ENI2.Excel
protected Dictionary<string, Name> _nameDict;
protected ILog _log;
#endregion
#endregion Fields
#region Construction
@ -39,7 +39,7 @@ namespace ENI2.Excel
this._excelWorkbooks = _excelApp.Workbooks;
}
#endregion
#endregion Construction
#region Properties
@ -47,6 +47,8 @@ namespace ENI2.Excel
internal Dictionary<string, Name> NameDict { get { return _nameDict; } }
internal Sheets Worksheets { get { return _workBook.Worksheets; } }
#endregion
#region protected methods
@ -143,10 +145,14 @@ namespace ENI2.Excel
if(_nameDict.ContainsKey(lookup))
{
var range = _nameDict[lookup].RefersToRange;
range.Interior.Color = color;
// range.Worksheet.Tab.ColorIndex = XlColorIndex.xlColorIndexAutomatic;
range.Worksheet.Tab.Color = color;
}
Colorize(range, color);
}
}
internal void Colorize(Range range, int color)
{
range.Interior.Color = color;
range.Worksheet.Tab.Color = color;
}
#endregion

View File

@ -42,6 +42,20 @@ namespace ENI2.Excel
}
}
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, out string errorMessage)
{
string fileName = Path.GetTempPath() + Guid.NewGuid().ToString() + ".xlsx";
@ -51,10 +65,11 @@ namespace ENI2.Excel
try
{
File.Copy(targetPath, fileName);
ExcelReader source = new ExcelReader(sourcePath);
ExcelReader comparison = new ExcelReader(fileName, false);
ExcelReader source = new ExcelReader(sourcePath, true, false);
ExcelReader comparison = new ExcelReader(fileName, false, false);
/*
/* erste Variante Vergleich über Namen der Zellen
// loop through named cells
foreach (string name in comparison.NameDict.Keys)
{
@ -90,6 +105,77 @@ namespace ENI2.Excel
}
*/
// 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(fileName);
errorMessage = string.Format("{0} differences found", counter);

View File

@ -33,13 +33,15 @@ namespace ENI2.Excel
internal Dictionary<string, string> ImportValues { get; } = new Dictionary<string, string>();
public ExcelReader(string filePath, bool openReadonly = true)
public ExcelReader(string filePath, bool openReadonly = true, bool createNameFields = true)
{
this._workBook = _excelWorkbooks.Open(filePath, 0, openReadonly, 5, "", "", false, XlPlatform.xlWindows, "", false, false, 0, false, false, false);
this.InitNameFields();
if(createNameFields)
this.InitNameFields();
// Determine if this is a Dakosy or BSMD Sheet
_sheetType = (_nameDict.Count > 10) ? SheetTypeEnum.BSMD : SheetTypeEnum.DAKOSY;
if(createNameFields)
_sheetType = (_nameDict.Count > 10) ? SheetTypeEnum.BSMD : SheetTypeEnum.DAKOSY;
}
public SheetTypeEnum SheetType { get { return _sheetType; } }
@ -584,6 +586,23 @@ namespace ENI2.Excel
return null;
}
internal string ReadCellAsText(string sheetName, int row, int col)
{
try
{
Worksheet workSheet = (Worksheet)_workBook.Worksheets[sheetName];
string result = workSheet.Range[row, col].Text.ToString();
if (!result.IsNullOrEmpty())
result = result.Trim().Clean();
return result;
}
catch (Exception e)
{
_log.Warn(e.Message);
}
return null;
}
// TODO THIS IS NOT WORKING
internal string ReadTextFromDropdown(string sheetName, string range)
{