From f596a53a38267bdf296f8c8fdc0635d331275016 Mon Sep 17 00:00:00 2001 From: Daniel Schick Date: Tue, 28 Jun 2022 14:46:39 +0200 Subject: [PATCH] =?UTF-8?q?Excel=20Vergleich=20funktioniert=20jetzt=20mit?= =?UTF-8?q?=20Ranges=20statt=20benannten=20Feldern.=20Es=20l=C3=A4uft=20au?= =?UTF-8?q?ch=20wesentlich=20schneller,=20weil=20der=20Zugriff=20auf=20die?= =?UTF-8?q?=20Ranges=20=C3=BCber=20einen=20Array=20und=20nicht=20mehr=20ei?= =?UTF-8?q?nzeln=20erfolgt.=20Diese=20Funktion=20kann=20jetzt=20auf=20beli?= =?UTF-8?q?ebige=20Excel=20auch=20au=C3=9Ferhalb=20vom=20NSW=20angewandt?= =?UTF-8?q?=20werden.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ENI2/Excel/ExcelBase.cs | 18 +++++--- ENI2/Excel/ExcelComparer.cs | 92 +++++++++++++++++++++++++++++++++++-- ENI2/Excel/ExcelReader.cs | 25 ++++++++-- 3 files changed, 123 insertions(+), 12 deletions(-) diff --git a/ENI2/Excel/ExcelBase.cs b/ENI2/Excel/ExcelBase.cs index 71f55158..31eb1cd5 100644 --- a/ENI2/Excel/ExcelBase.cs +++ b/ENI2/Excel/ExcelBase.cs @@ -25,7 +25,7 @@ namespace ENI2.Excel protected Dictionary _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 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 diff --git a/ENI2/Excel/ExcelComparer.cs b/ENI2/Excel/ExcelComparer.cs index 4d9b36e9..99eea7e0 100644 --- a/ENI2/Excel/ExcelComparer.cs +++ b/ENI2/Excel/ExcelComparer.cs @@ -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); diff --git a/ENI2/Excel/ExcelReader.cs b/ENI2/Excel/ExcelReader.cs index 2c1af6ce..cb9444d2 100644 --- a/ENI2/Excel/ExcelReader.cs +++ b/ENI2/Excel/ExcelReader.cs @@ -33,13 +33,15 @@ namespace ENI2.Excel internal Dictionary ImportValues { get; } = new Dictionary(); - 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) {