Vor Controls2B_EnDisabled Change

This commit is contained in:
Developer01
2026-03-11 16:43:34 +01:00
parent 7629d54fe1
commit 969e07eb17
2 changed files with 119 additions and 39 deletions

View File

@@ -39,46 +39,85 @@ Public Class ClassFormat
Dim normalized As String = pValue.Trim() Dim normalized As String = pValue.Trim()
LOGGER.Debug($"[NormalizeNumericString] Input: [{pValue}]")
' Entferne Währungssymbole und Leerzeichen ' Entferne Währungssymbole und Leerzeichen
normalized = System.Text.RegularExpressions.Regex.Replace(normalized, "[€$£¥\s]", "") normalized = System.Text.RegularExpressions.Regex.Replace(normalized, "[€$£¥\s]", "")
' Prüfe, ob der String sowohl Punkt als auch Komma enthält
Dim hasDot As Boolean = normalized.Contains(".") Dim hasDot As Boolean = normalized.Contains(".")
Dim hasComma As Boolean = normalized.Contains(",") Dim hasComma As Boolean = normalized.Contains(",")
LOGGER.Debug($"[NormalizeNumericString] After cleanup: [{normalized}], HasDot={hasDot}, HasComma={hasComma}")
If hasDot AndAlso hasComma Then If hasDot AndAlso hasComma Then
' Beide vorhanden: Das letzte ist der Dezimaltrenner ' Beide vorhanden: Das letzte ist der Dezimaltrenner
Dim lastDotPos As Integer = normalized.LastIndexOf(".") Dim lastDotPos As Integer = normalized.LastIndexOf(".")
Dim lastCommaPos As Integer = normalized.LastIndexOf(",") Dim lastCommaPos As Integer = normalized.LastIndexOf(",")
LOGGER.Debug($"[NormalizeNumericString] Both separators found: LastDotPos={lastDotPos}, LastCommaPos={lastCommaPos}")
If lastDotPos > lastCommaPos Then If lastDotPos > lastCommaPos Then
' Punkt ist Dezimaltrenner, Komma ist Tausendertrenner
normalized = normalized.Replace(",", "") normalized = normalized.Replace(",", "")
Else Else
' Komma ist Dezimaltrenner, Punkt ist Tausendertrenner
normalized = normalized.Replace(".", "").Replace(",", ".") normalized = normalized.Replace(".", "").Replace(",", ".")
End If End If
ElseIf hasComma Then ElseIf hasComma Then
' Nur Komma: Könnte Dezimal- oder Tausendertrenner sein
' Wenn mehr als ein Komma → Tausendertrenner
' Wenn nur ein Komma und <= 3 Stellen danach → Dezimaltrenner
Dim commaCount As Integer = normalized.Count(Function(c) c = ","c) Dim commaCount As Integer = normalized.Count(Function(c) c = ","c)
LOGGER.Debug($"[NormalizeNumericString] Only comma found: CommaCount={commaCount}")
If commaCount = 1 Then If commaCount = 1 Then
Dim lastCommaPos As Integer = normalized.LastIndexOf(",") Dim lastCommaPos As Integer = normalized.LastIndexOf(",")
Dim digitsAfterComma As Integer = normalized.Length - lastCommaPos - 1 Dim digitsAfterComma As Integer = normalized.Length - lastCommaPos - 1
LOGGER.Debug($"[NormalizeNumericString] Single comma: DigitsAfterComma={digitsAfterComma}")
If digitsAfterComma <= 3 Then If digitsAfterComma <= 3 Then
' Wahrscheinlich Dezimaltrenner
normalized = normalized.Replace(",", ".") normalized = normalized.Replace(",", ".")
Else Else
' Wahrscheinlich Tausendertrenner
normalized = normalized.Replace(",", "") normalized = normalized.Replace(",", "")
End If End If
Else Else
' Mehrere Kommas → Tausendertrenner
normalized = normalized.Replace(",", "") normalized = normalized.Replace(",", "")
End If End If
ElseIf hasDot Then
Dim dotCount As Integer = normalized.Count(Function(c) c = "."c)
LOGGER.Debug($"[NormalizeNumericString] Only dot found: DotCount={dotCount}")
If dotCount = 1 Then
Dim lastDotPos As Integer = normalized.LastIndexOf(".")
Dim digitsAfterDot As Integer = normalized.Length - lastDotPos - 1
LOGGER.Debug($"[NormalizeNumericString] Single dot: DigitsAfterDot={digitsAfterDot}")
' ✅ KRITISCHE ÄNDERUNG: Prüfe auch Stellen VOR dem Punkt
Dim digitsBeforeDot As Integer = lastDotPos
' Heuristik: Wenn <= 3 Stellen nach Punkt UND >= 1 Stelle davor → Dezimaltrenner
' Wenn > 3 Stellen davor UND <= 3 Stellen nach Punkt → unklar, vermutlich Dezimal
' Wenn > 3 Stellen nach Punkt → definitiv KEIN Dezimaltrenner
If digitsAfterDot > 3 Then
LOGGER.Warn($"⚠️ [NormalizeNumericString] Dot with {digitsAfterDot} digits after → treating as THOUSAND separator!")
normalized = normalized.Replace(".", "")
ElseIf digitsAfterDot >= 1 AndAlso digitsAfterDot <= 3 Then
' Wahrscheinlich Dezimaltrenner (z.B. 5464.17 oder 120.5)
LOGGER.Debug($"[NormalizeNumericString] Dot treated as decimal separator ({digitsBeforeDot} digits before, {digitsAfterDot} after)")
Else
' digitsAfterDot = 0 → Punkt am Ende, vermutlich Fehler
LOGGER.Warn($"⚠️ [NormalizeNumericString] Dot at end of string → removing")
normalized = normalized.Replace(".", "")
End If
Else
' Mehrere Punkte → Tausendertrenner
LOGGER.Debug($"[NormalizeNumericString] Multiple dots → removing all")
normalized = normalized.Replace(".", "")
End If
Else
LOGGER.Debug($"[NormalizeNumericString] No separators found → integer or already normalized")
End If End If
' Wenn nur Punkt vorhanden: bereits im richtigen Format
LOGGER.Debug($"[NormalizeNumericString] Output: [{normalized}]")
Return normalized Return normalized
End Function End Function
@@ -96,6 +135,7 @@ Public Class ClassFormat
Select Case pType Select Case pType
Case ClassControlCreator.CONTROL_TYPE_DOUBLE Case ClassControlCreator.CONTROL_TYPE_DOUBLE
Try Try
' ✅ IMMER normalisieren auch für DB-Werte!
Dim normalizedValue As String = NormalizeNumericString(pValue?.ToString()) Dim normalizedValue As String = NormalizeNumericString(pValue?.ToString())
If Double.TryParse(normalizedValue, NumberStyles.Float, CultureInfo.InvariantCulture, oConvertedValue) Then If Double.TryParse(normalizedValue, NumberStyles.Float, CultureInfo.InvariantCulture, oConvertedValue) Then
Return oConvertedValue Return oConvertedValue
@@ -106,12 +146,15 @@ Public Class ClassFormat
Case ClassControlCreator.CONTROL_TYPE_CURRENCY Case ClassControlCreator.CONTROL_TYPE_CURRENCY
Try Try
' ✅ KRITISCH: Normalisierung VOR Konvertierung
Dim normalizedValue As String = NormalizeNumericString(pValue?.ToString()) Dim normalizedValue As String = NormalizeNumericString(pValue?.ToString())
LOGGER.Debug($"GetConvertedValue: Converting {pValue.ToString} (normalized: {normalizedValue}) to Currency ") LOGGER.Debug($"GetConvertedValue CURRENCY: Original=[{pValue}], Normalized=[{normalizedValue}]")
If Double.TryParse(normalizedValue, NumberStyles.Float, CultureInfo.InvariantCulture, oConvertedValue) Then If Double.TryParse(normalizedValue, NumberStyles.Float, CultureInfo.InvariantCulture, oConvertedValue) Then
Return oConvertedValue Return oConvertedValue
End If End If
Catch ex As Exception Catch ex As Exception
LOGGER.Error($"Currency conversion failed for [{pValue}]: {ex.Message}")
LOGGER.Error(ex) LOGGER.Error(ex)
End Try End Try
@@ -124,6 +167,7 @@ Public Class ClassFormat
Catch ex As Exception Catch ex As Exception
LOGGER.Error(ex) LOGGER.Error(ex)
End Try End Try
Case Else Case Else
LOGGER.Debug($"GetConvertedValue - Case ELSE - pType is {pType}") LOGGER.Debug($"GetConvertedValue - Case ELSE - pType is {pType}")
Try Try
@@ -132,7 +176,6 @@ Public Class ClassFormat
LOGGER.Warn($"Error in GetConvertedValue: pType is {pType} - converting value to String") LOGGER.Warn($"Error in GetConvertedValue: pType is {pType} - converting value to String")
oConvertedValue = "" oConvertedValue = ""
End Try End Try
End Select End Select
Return oConvertedValue Return oConvertedValue
@@ -140,26 +183,32 @@ Public Class ClassFormat
''' <summary> ''' <summary>
''' Converts values to their respective data type and then back to string ''' Converts values to their respective data type and then back to string
''' according to the current culture ''' using INVARIANT culture for consistency across systems.
''' </summary> ''' </summary>
''' <param name="pValue"></param> ''' <param name="pValue"></param>
''' <returns></returns> ''' <returns></returns>
Public Shared Function GetStringValue(pValue As Object) As String Public Shared Function GetStringValue(pValue As Object) As String
' ✅ FIX: Immer InvariantCulture verwenden für DB-Speicherung
Select Case pValue.GetType Select Case pValue.GetType
Case GetType(Single) Case GetType(Single)
Return DirectCast(pValue, Single).ToString(CultureInfo.CurrentCulture) ' ✅ NEU: InvariantCulture statt CurrentCulture
Return DirectCast(pValue, Single).ToString(CultureInfo.InvariantCulture)
Case GetType(Double) Case GetType(Double)
Return DirectCast(pValue, Double).ToString(CultureInfo.CurrentCulture) ' ✅ NEU: InvariantCulture statt CurrentCulture
Return DirectCast(pValue, Double).ToString(CultureInfo.InvariantCulture)
Case GetType(Decimal) Case GetType(Decimal)
Return DirectCast(pValue, Decimal).ToString(CultureInfo.CurrentCulture) ' ✅ NEU: InvariantCulture statt CurrentCulture
Return DirectCast(pValue, Decimal).ToString(CultureInfo.InvariantCulture)
Case GetType(Date) Case GetType(Date)
Return DirectCast(pValue, Date).ToString(CultureInfo.CurrentCulture) ' Datum: ISO 8601 Format für Culture-Unabhängigkeit
Return DirectCast(pValue, Date).ToString("yyyy-MM-dd", CultureInfo.InvariantCulture)
Case GetType(DateTime) Case GetType(DateTime)
Return DirectCast(pValue, DateTime).ToString(CultureInfo.CurrentCulture) ' DateTime: ISO 8601 Format
Return DirectCast(pValue, DateTime).ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture)
Case Else Case Else
Return pValue.ToString Return pValue.ToString

View File

@@ -3779,12 +3779,15 @@ Public Class frmValidator
MyValidationLogger.Error(ex) MyValidationLogger.Error(ex)
errormessage = "unexpected error in Load_Next_Document:" & ex.Message errormessage = "unexpected error in Load_Next_Document:" & ex.Message
My.Settings.Save() My.Settings.Save()
MyValidationLogger.Info("unexpected error in Load_Next_Document: " & ex.Message) MyValidationLogger.Info("unexpected error in Load_Next_Document: " & ex.Message)
frmError.ShowDialog() frmError.ShowDialog()
Finally Finally
If layoutSuspended Then If layoutSuspended Then
PanelValidatorControl.ResumeLayout() PanelValidatorControl.ResumeLayout()
End If End If
CloseOverlaySafe()
If LOG_HOTSPOTS Then If LOG_HOTSPOTS Then
' ========== DIAGNOSE ENDE ========== ' ========== DIAGNOSE ENDE ==========
MyValidationLogger.Info($"[INFO] Load_Next_Document ENDE") MyValidationLogger.Info($"[INFO] Load_Next_Document ENDE")
@@ -4533,33 +4536,61 @@ Public Class frmValidator
MyValidationLogger.Debug("Creating new row..") MyValidationLogger.Debug("Creating new row..")
For index = 0 To oDTColumnsPerDevExGrid.Rows.Count - 1 For index = 0 To oDTColumnsPerDevExGrid.Rows.Count - 1
Dim rawValue As String = If(index < oColValuesfromSource.Length, oColValuesfromSource(index), String.Empty)
Dim targetColumn As DataColumn = oDataSource.Columns(index)
Dim colName As String = targetColumn.ColumnName
Dim colType As String = targetColumn.DataType.FullName
MyValidationLogger.Debug("Grid row assign: RowIdx={0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}], IsEmpty={5}",
oDataSource.Rows.Count, index, colName, colType, rawValue, String.IsNullOrWhiteSpace(rawValue))
Try Try
If oColValuesfromSource.Length > index Then ' 1. Basis-Checks
oNewRow.Item(index) = oColValuesfromSource(index) Dim rawValue As String = If(index < oColValuesfromSource.Length, oColValuesfromSource(index), String.Empty)
Else Dim targetColumn As DataColumn = oDataSource.Columns(index)
If colType = "System.Double" Or colType = "System.Int32" Or colType = "System.Int64" Then Dim colType As Type = targetColumn.DataType
oNewRow.Item(index) = 0
' 2. NULL-Handling
If String.IsNullOrWhiteSpace(rawValue) Then
If colType.IsValueType AndAlso Nullable.GetUnderlyingType(colType) Is Nothing Then
' Nicht-Nullable Value-Type → Default-Wert setzen
oNewRow.Item(index) = Activator.CreateInstance(colType)
MyValidationLogger.Debug($"Grid row default: ColIdx={index}, ColType={colType.Name}")
Else Else
oNewRow.Item(index) = String.Empty ' Nullable/Reference-Type → DBNull
oNewRow.Item(index) = DBNull.Value
End If End If
Continue For
End If End If
Catch ex As Exception
MyValidationLogger.Warn("⚠️ Grid row assign FAILED RowIdx = {0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}]", ' 3. Typ-spezifische Konvertierung
oDataSource.Rows.Count, index, colName, colType, rawValue)
MyValidationLogger.Error(ex)
Try Try
MyValidationLogger.Debug("Column.AllowDBNull={0}, Column.MaxLength={1}", targetColumn.AllowDBNull, targetColumn.MaxLength) Select Case Type.GetTypeCode(colType)
Catch Case TypeCode.Int32
oNewRow.Item(index) = Integer.Parse(rawValue.Trim(), CultureInfo.InvariantCulture)
Case TypeCode.Int64
oNewRow.Item(index) = Long.Parse(rawValue.Trim(), CultureInfo.InvariantCulture)
Case TypeCode.Double
oNewRow.Item(index) = Double.Parse(rawValue.Trim().Replace(",", "."), CultureInfo.InvariantCulture)
Case TypeCode.Decimal
oNewRow.Item(index) = Decimal.Parse(rawValue.Trim().Replace(",", "."), CultureInfo.InvariantCulture)
Case TypeCode.Boolean
oNewRow.Item(index) = Boolean.Parse(rawValue.Trim())
Case TypeCode.DateTime
oNewRow.Item(index) = DateTime.Parse(rawValue.Trim(), CultureInfo.CurrentCulture)
Case Else
' String oder Custom-Type → direkt übernehmen
oNewRow.Item(index) = rawValue
End Select
Catch convEx As FormatException
MyValidationLogger.Warn($"⚠️ Grid conversion FAILED: ColIdx={index}, ColType={colType.Name}, RawValue=[{rawValue}] → using default")
' Fallback: Default-Wert statt Crash
If colType.IsValueType Then
oNewRow.Item(index) = Activator.CreateInstance(colType)
Else
oNewRow.Item(index) = DBNull.Value
End If
End Try End Try
Throw
Catch logEx As Exception
' Fallback: Minimales Logging ohne Fehler
MyValidationLogger.Debug($"Grid row assign CRITICAL: ColIdx={index} [error: {logEx.Message}]")
' Leere Zelle → DBNull
oNewRow.Item(index) = DBNull.Value
End Try End Try
Next Next
MyValidationLogger.Debug("Adding row To grid..") MyValidationLogger.Debug("Adding row To grid..")