Vor Controls2B_EnDisabled Change
This commit is contained in:
@@ -39,46 +39,85 @@ Public Class ClassFormat
|
||||
|
||||
Dim normalized As String = pValue.Trim()
|
||||
|
||||
LOGGER.Debug($"[NormalizeNumericString] Input: [{pValue}]")
|
||||
|
||||
' Entferne Währungssymbole und Leerzeichen
|
||||
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 hasComma As Boolean = normalized.Contains(",")
|
||||
|
||||
LOGGER.Debug($"[NormalizeNumericString] After cleanup: [{normalized}], HasDot={hasDot}, HasComma={hasComma}")
|
||||
|
||||
If hasDot AndAlso hasComma Then
|
||||
' Beide vorhanden: Das letzte ist der Dezimaltrenner
|
||||
Dim lastDotPos As Integer = normalized.LastIndexOf(".")
|
||||
Dim lastCommaPos As Integer = normalized.LastIndexOf(",")
|
||||
|
||||
LOGGER.Debug($"[NormalizeNumericString] Both separators found: LastDotPos={lastDotPos}, LastCommaPos={lastCommaPos}")
|
||||
|
||||
If lastDotPos > lastCommaPos Then
|
||||
' Punkt ist Dezimaltrenner, Komma ist Tausendertrenner
|
||||
normalized = normalized.Replace(",", "")
|
||||
Else
|
||||
' Komma ist Dezimaltrenner, Punkt ist Tausendertrenner
|
||||
normalized = normalized.Replace(".", "").Replace(",", ".")
|
||||
End If
|
||||
|
||||
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)
|
||||
LOGGER.Debug($"[NormalizeNumericString] Only comma found: CommaCount={commaCount}")
|
||||
|
||||
If commaCount = 1 Then
|
||||
Dim lastCommaPos As Integer = normalized.LastIndexOf(",")
|
||||
Dim digitsAfterComma As Integer = normalized.Length - lastCommaPos - 1
|
||||
LOGGER.Debug($"[NormalizeNumericString] Single comma: DigitsAfterComma={digitsAfterComma}")
|
||||
|
||||
If digitsAfterComma <= 3 Then
|
||||
' Wahrscheinlich Dezimaltrenner
|
||||
normalized = normalized.Replace(",", ".")
|
||||
Else
|
||||
' Wahrscheinlich Tausendertrenner
|
||||
normalized = normalized.Replace(",", "")
|
||||
End If
|
||||
Else
|
||||
' Mehrere Kommas → Tausendertrenner
|
||||
normalized = normalized.Replace(",", "")
|
||||
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
|
||||
' Wenn nur Punkt vorhanden: bereits im richtigen Format
|
||||
|
||||
LOGGER.Debug($"[NormalizeNumericString] Output: [{normalized}]")
|
||||
|
||||
Return normalized
|
||||
End Function
|
||||
@@ -96,6 +135,7 @@ Public Class ClassFormat
|
||||
Select Case pType
|
||||
Case ClassControlCreator.CONTROL_TYPE_DOUBLE
|
||||
Try
|
||||
' ✅ IMMER normalisieren – auch für DB-Werte!
|
||||
Dim normalizedValue As String = NormalizeNumericString(pValue?.ToString())
|
||||
If Double.TryParse(normalizedValue, NumberStyles.Float, CultureInfo.InvariantCulture, oConvertedValue) Then
|
||||
Return oConvertedValue
|
||||
@@ -106,12 +146,15 @@ Public Class ClassFormat
|
||||
|
||||
Case ClassControlCreator.CONTROL_TYPE_CURRENCY
|
||||
Try
|
||||
' ✅ KRITISCH: Normalisierung VOR Konvertierung
|
||||
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
|
||||
Return oConvertedValue
|
||||
End If
|
||||
Catch ex As Exception
|
||||
LOGGER.Error($"Currency conversion failed for [{pValue}]: {ex.Message}")
|
||||
LOGGER.Error(ex)
|
||||
End Try
|
||||
|
||||
@@ -124,6 +167,7 @@ Public Class ClassFormat
|
||||
Catch ex As Exception
|
||||
LOGGER.Error(ex)
|
||||
End Try
|
||||
|
||||
Case Else
|
||||
LOGGER.Debug($"GetConvertedValue - Case ELSE - pType is {pType}")
|
||||
Try
|
||||
@@ -132,7 +176,6 @@ Public Class ClassFormat
|
||||
LOGGER.Warn($"Error in GetConvertedValue: pType is {pType} - converting value to String")
|
||||
oConvertedValue = ""
|
||||
End Try
|
||||
|
||||
End Select
|
||||
|
||||
Return oConvertedValue
|
||||
@@ -140,26 +183,32 @@ Public Class ClassFormat
|
||||
|
||||
''' <summary>
|
||||
''' 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>
|
||||
''' <param name="pValue"></param>
|
||||
''' <returns></returns>
|
||||
Public Shared Function GetStringValue(pValue As Object) As String
|
||||
' ✅ FIX: Immer InvariantCulture verwenden für DB-Speicherung
|
||||
Select Case pValue.GetType
|
||||
Case GetType(Single)
|
||||
Return DirectCast(pValue, Single).ToString(CultureInfo.CurrentCulture)
|
||||
' ✅ NEU: InvariantCulture statt CurrentCulture
|
||||
Return DirectCast(pValue, Single).ToString(CultureInfo.InvariantCulture)
|
||||
|
||||
Case GetType(Double)
|
||||
Return DirectCast(pValue, Double).ToString(CultureInfo.CurrentCulture)
|
||||
' ✅ NEU: InvariantCulture statt CurrentCulture
|
||||
Return DirectCast(pValue, Double).ToString(CultureInfo.InvariantCulture)
|
||||
|
||||
Case GetType(Decimal)
|
||||
Return DirectCast(pValue, Decimal).ToString(CultureInfo.CurrentCulture)
|
||||
' ✅ NEU: InvariantCulture statt CurrentCulture
|
||||
Return DirectCast(pValue, Decimal).ToString(CultureInfo.InvariantCulture)
|
||||
|
||||
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)
|
||||
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
|
||||
Return pValue.ToString
|
||||
|
||||
@@ -3779,12 +3779,15 @@ Public Class frmValidator
|
||||
MyValidationLogger.Error(ex)
|
||||
errormessage = "unexpected error in Load_Next_Document:" & ex.Message
|
||||
My.Settings.Save()
|
||||
|
||||
MyValidationLogger.Info("unexpected error in Load_Next_Document: " & ex.Message)
|
||||
|
||||
frmError.ShowDialog()
|
||||
Finally
|
||||
If layoutSuspended Then
|
||||
PanelValidatorControl.ResumeLayout()
|
||||
End If
|
||||
CloseOverlaySafe()
|
||||
If LOG_HOTSPOTS Then
|
||||
' ========== DIAGNOSE ENDE ==========
|
||||
MyValidationLogger.Info($"[INFO] Load_Next_Document ENDE")
|
||||
@@ -4533,33 +4536,61 @@ Public Class frmValidator
|
||||
MyValidationLogger.Debug("Creating new row..")
|
||||
|
||||
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
|
||||
If oColValuesfromSource.Length > index Then
|
||||
oNewRow.Item(index) = oColValuesfromSource(index)
|
||||
Else
|
||||
If colType = "System.Double" Or colType = "System.Int32" Or colType = "System.Int64" Then
|
||||
oNewRow.Item(index) = 0
|
||||
' 1. Basis-Checks
|
||||
Dim rawValue As String = If(index < oColValuesfromSource.Length, oColValuesfromSource(index), String.Empty)
|
||||
Dim targetColumn As DataColumn = oDataSource.Columns(index)
|
||||
Dim colType As Type = targetColumn.DataType
|
||||
|
||||
' 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
|
||||
oNewRow.Item(index) = String.Empty
|
||||
' Nullable/Reference-Type → DBNull
|
||||
oNewRow.Item(index) = DBNull.Value
|
||||
End If
|
||||
Continue For
|
||||
End If
|
||||
Catch ex As Exception
|
||||
MyValidationLogger.Warn("⚠️ Grid row assign FAILED RowIdx = {0}, ColIdx={1}, ColName={2}, ColType={3}, RawValue=[{4}]",
|
||||
oDataSource.Rows.Count, index, colName, colType, rawValue)
|
||||
MyValidationLogger.Error(ex)
|
||||
|
||||
' 3. Typ-spezifische Konvertierung
|
||||
Try
|
||||
MyValidationLogger.Debug("Column.AllowDBNull={0}, Column.MaxLength={1}", targetColumn.AllowDBNull, targetColumn.MaxLength)
|
||||
Catch
|
||||
Select Case Type.GetTypeCode(colType)
|
||||
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
|
||||
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
|
||||
Next
|
||||
MyValidationLogger.Debug("Adding row To grid..")
|
||||
|
||||
Reference in New Issue
Block a user