ADMIN UsrParam, DHF Import

This commit is contained in:
2025-08-20 21:32:47 +02:00
parent a97eb51344
commit 0100b3ed89
5 changed files with 1211 additions and 186 deletions

View File

@@ -1428,24 +1428,7 @@ Public Class usrCntlATLAS_EZA
End Function
Private Function ToDoubleSafe(o As Object) As Double
If o Is Nothing OrElse IsDBNull(o) Then Return 0
' Direkte Numerik
If TypeOf o Is Double Then Return DirectCast(o, Double)
If TypeOf o Is Decimal Then Return Convert.ToDouble(o)
If TypeOf o Is Integer OrElse TypeOf o Is Int64 OrElse TypeOf o Is Int16 Then Return Convert.ToDouble(o)
' String-Fälle (leer, deutsch, englisch)
Dim s = o.ToString().Trim()
If s = "" Then Return 0
Dim v As Double
If Double.TryParse(s, NumberStyles.Any, CultureInfo.CurrentCulture, v) Then Return v
If Double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, v) Then Return v
Return 0 ' Notfalls 0
End Function
Private Sub pnl_Paint_1(sender As Object, e As PaintEventArgs) Handles pnl.Paint
@@ -1497,5 +1480,309 @@ Public Class usrCntlATLAS_EZA
Private Sub MEYLEXLSXToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles MEYLEXLSXToolStripMenuItem.Click
importExcel_MEYLE()
End Sub
Private Sub FressnapToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles FressnapToolStripMenuItem.Click
importExcel_Fressnapf()
End Sub
Private Function importExcel_Fressnapf() As Boolean
Dim fd As New OpenFileDialog With {
.Filter = "Excel Dateien|*.xls;*.xlsx",
.Multiselect = True,
.Title = "Bitte eine oder mehrere Excel-Dateien auswählen"
}
If fd.ShowDialog() <> DialogResult.OK Then
Me.Cursor = Cursors.Default
MsgBox("Keine Datei ausgewählt!")
Return False
End If
Dim cnt As Integer = 0
If EZA.eza_WARENPOS.Count > 0 Then
If vbYes = MsgBox("Sollten die aktuellen Einträge gelöscht werden?", vbYesNo) Then
EZA.eza_WARENPOS.Clear()
End If
End If
Me.Cursor = Cursors.WaitCursor
For Each filePath As String In fd.FileNames
If Not (filePath.ToLower().EndsWith(".xls") OrElse filePath.ToLower().EndsWith(".xlsx")) Then
Continue For
End If
Dim exclApp As Excel.Application = Nothing
Dim Datei As Excel.Workbook = Nothing
Dim Blatt As Excel.Worksheet = Nothing
Try
exclApp = New Excel.Application With {
.CutCopyMode = False,
.DisplayAlerts = False
}
Datei = exclApp.Workbooks.Open(filePath)
Blatt = CType(Datei.Worksheets(1), Excel.Worksheet)
Datei.Activate()
Try : Blatt.ShowAllData() : Catch : End Try
' --- Prüfe, ob Kopfzeile in Zeile 17 existiert
If Not checkExcelHeader_Fressnapf(Blatt) Then
Throw New ApplicationException("Excel-Struktur entspricht nicht dem erwarteten Layout (Header-Zeile 17).")
End If
' --- Spalten dynamisch per Header ermitteln (Zeile 17)
Dim colDesc = FindHeaderColumn(Blatt, 17, {"warenbeschreibung"})
Dim colImpCode = FindHeaderColumn(Blatt, 17, {"importcodenummer", "warentarifnummer", "eztnummer", "ezt-nummer"})
Dim colOrigin = FindHeaderColumn(Blatt, 17, {"ursprungsland", "ursprungslandcode"})
Dim colCurrency = FindHeaderColumn(Blatt, 17, {"währung", "waehrung", "currency"})
Dim colNetMass = FindHeaderColumn(Blatt, 17, {"nettomasse", "nettomas­se", "nettomasse kg", "eigenmasse"})
Dim colQty = FindHeaderColumn(Blatt, 17, {"menge", "quantity", "qty"})
Dim colValue = FindHeaderColumn(Blatt, 17, {"warenwert", "invoice value", "value"})
' Minimal erforderliche Spalten prüfen
If colDesc = -1 OrElse colImpCode = -1 OrElse colOrigin = -1 OrElse colCurrency = -1 OrElse colValue = -1 Then
Throw New ApplicationException("Nicht alle erforderlichen Spaltenköpfe gefunden (Beschreibung/Warentarifnummer/Ursprungsland/Währung/Warenwert).")
End If
' --- Datenbereich bestimmen: ab Zeile 18 bis erste Leerzeile in Spalte A (Pos.)
Dim startRows As Integer = 18
Dim endRows As Integer = startRows
Dim usedRows As Integer = Blatt.UsedRange.Rows.Count
Do While endRows <= usedRows
Dim val = Blatt.Range("A" & endRows).Value
If val Is Nothing OrElse val.ToString().Trim() = "" Then Exit Do
endRows += 1
Loop
endRows -= 1
If endRows < startRows Then
Throw New ApplicationException("Keine Positionsdaten im Excel gefunden.")
End If
' --- Spaltenanzahl mindestens so groß wie letzte genutzte Spalte
Dim colCount As Integer = Math.Max(Blatt.UsedRange.Columns.Count, Math.Max(Math.Max(Math.Max(colDesc, colImpCode), Math.Max(colOrigin, colCurrency)), Math.Max(colValue, If(colNetMass < 0, 0, colNetMass))) + 1)
If colCount < 19 Then colCount = 19 ' typischerweise A..S
' --- Rohdaten in DataTable übernehmen
Dim DATA As New DataTable()
For c As Integer = 1 To colCount
DATA.Columns.Add("Spalte" & c, GetType(String))
Next
For r As Integer = startRows To endRows
Dim newRow As DataRow = DATA.NewRow()
For c As Integer = 1 To colCount
Dim value = Blatt.Cells(r, c).Value
newRow(c - 1) = If(value IsNot Nothing, value.ToString(), "")
Next
' Normalisierung für Gruppierung
If colCurrency >= 0 Then newRow(colCurrency) = newRow(colCurrency).ToString().Trim().ToUpper()
If colOrigin >= 0 Then newRow(colOrigin) = newRow(colOrigin).ToString().Trim().ToUpper()
DATA.Rows.Add(newRow)
Next
' --- Nur numerische Pos.-Zeilen behalten (Spalte A / Index 0)
For i As Integer = DATA.Rows.Count - 1 To 0 Step -1
Dim posTxt As String = DATA.Rows(i)(0).ToString().Trim()
Dim posNum As Integer
If Not Integer.TryParse(posTxt, posNum) Then
DATA.Rows.RemoveAt(i)
End If
Next
' --- Gruppieren nach: Beschreibung, Warentarifnummer, Ursprungsland, Währung
Dim resultDATA As DataTable = DATA.Clone()
Dim groups = From row In DATA.AsEnumerable()
Group row By
keyDesc = row(colDesc),
keyTariff = row(colImpCode),
keyOrigin = row(colOrigin),
keyCurr = row(colCurrency)
Into grp = Group
Select keyDesc, keyTariff, keyOrigin, keyCurr, grp
For Each g In groups
Dim newRow As DataRow = resultDATA.NewRow()
newRow(colDesc) = g.keyDesc
newRow(colImpCode) = g.keyTariff
newRow(colOrigin) = g.keyOrigin
newRow(colCurrency) = g.keyCurr
' Summenfelder (nur wenn vorhanden)
If colQty >= 0 Then newRow(colQty) = g.grp.Sum(Function(r) ToDoubleSafe(r(colQty))).ToString()
If colNetMass >= 0 Then newRow(colNetMass) = g.grp.Sum(Function(r) ToDoubleSafe(r(colNetMass))).ToString()
newRow(colValue) = g.grp.Sum(Function(r) ToDoubleSafe(r(colValue))).ToString()
resultDATA.Rows.Add(newRow)
Next
' --- Kopfwerte optional (z. B. Belegnummer)
Dim HandlesRgNr As String = ""
Try
If Blatt.Range("A8") IsNot Nothing AndAlso Blatt.Range("A8").Value IsNot Nothing Then
HandlesRgNr = Blatt.Range("A8").Value.ToString().Trim()
End If
Catch
End Try
' --- Ergebniszeilen in EZA schreiben
For Each row As DataRow In resultDATA.Rows
Dim tariff As String = row(colImpCode).ToString().Trim()
Dim desc As String = row(colDesc).ToString().Trim()
If tariff = "" AndAlso desc = "" Then Continue For
Dim POSITION As New DAKOSY_Worker.cDakosy_EZA_Warenposition
' *** WAREN­TARIFNUMMER ***
POSITION.ezaWP_WarennummerEZT = tariff
' Packstücke (nicht aus Excel, Standardwerte)
POSITION.ezaWP_PackstueckAnzahl = "0"
POSITION.ezaWP_PackstueckArt = "PK"
' *** ARTIKELPREIS (Warenwert) ***
Dim warenwert As Double = ToDoubleSafe(row(colValue))
POSITION.ezaWP_Artikelpreis = warenwert.ToString("N2")
' *** WÄHRUNG ***
POSITION.ezaWP_ArtikelpreisWaehrung = row(colCurrency).ToString()
' *** BESCHREIBUNG ***
POSITION.ezaWP_Warenbezeichnung = desc
' *** EIGENMASSE (aus Nettomasse, wenn vorhanden) ***
If colNetMass >= 0 Then
Dim netto As Double = ToDoubleSafe(row(colNetMass))
POSITION.ezaWP_Eigenmasse = netto.ToString("N1")
Else
POSITION.ezaWP_Eigenmasse = "0.0"
End If
' *** URSPRUNGS­LAND (2-stellig) ***
Dim ursprung As String = row(colOrigin).ToString().Trim().ToUpper()
If ursprung.Length >= 2 Then POSITION.ezaWP_UrsprungslandCode = ursprung.Substring(0, 2)
' Unterlagen (optional)
If Not String.IsNullOrWhiteSpace(HandlesRgNr) Then
POSITION.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = "N380",
.ezaWpUl_Bereich = "4",
.ezaWpUl_VorlageKz = "J",
.ezaWpUl_Nummer = HandlesRgNr,
.ezaWpUl_DatumAusstellung = Nothing
})
End If
EZA.eza_WARENPOS.Add(POSITION)
cnt += 1
Next
Catch ex As Exception
Me.Cursor = Cursors.Default
MsgBox("FEHLER beim Einlesen: " & vbCrLf & ex.Message)
Finally
' Ressourcen sauber freigeben
Try
If Datei IsNot Nothing Then Datei.Close(False)
Catch
End Try
Try
If exclApp IsNot Nothing Then exclApp.Quit()
Catch
End Try
Try
If Blatt IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Blatt)
Catch
End Try
Try
If Datei IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(Datei)
Catch
End Try
Try
If exclApp IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(exclApp)
Catch
End Try
Blatt = Nothing : Datei = Nothing : exclApp = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
Console.WriteLine("Verarbeite Datei: " & filePath)
Next
Me.FindForm.SuspendLayout()
POSITIONEN.setValues(EZA, True)
btnPositionen.PerformClick()
Me.FindForm.ResumeLayout()
MsgBox(cnt & " Datensätze wurden eingelesen.")
Me.Cursor = Cursors.Default
Return True
End Function
' Liefert die 0-basierte Spaltennummer (DataTable-Index) anhand eines Header-Texts in rowIdx.
' Gibt -1 zurück, wenn keine der gesuchten Varianten gefunden wird.
Private Function FindHeaderColumn(ws As Excel.Worksheet, rowIdx As Integer, headerVariants As IEnumerable(Of String)) As Integer
Dim maxScanCols As Integer = 35 ' etwas Puffer
For c As Integer = 1 To maxScanCols
Dim cell = ws.Cells(rowIdx, c).Value
If cell Is Nothing Then Continue For
Dim norm = cell.ToString().Trim().ToLower()
For Each hv In headerVariants
If norm.Contains(hv.ToLower()) Then
Return c - 1 ' DataTable ist 0-basiert
End If
Next
Next
Return -1
End Function
Private Function ToDoubleSafe(obj As Object) As Double
If obj Is Nothing Then Return 0
Dim s As String = obj.ToString().Trim()
If s = "" Then Return 0
' Komma/Punkt robust behandeln, kulturinvariant parsen
Dim d As Double
' Erst alle Tausenderpunkte/Kommas vereinheitlichen
s = s.Replace(" ", "")
' Häufigster Fall: deutsches Komma
If s.Contains(",") AndAlso Not s.Contains(".") Then
s = s.Replace(".", "")
s = s.Replace(",", ".")
ElseIf s.Contains(".") AndAlso s.Contains(",") Then
' Entferne Tausender-Trenner, behalte Dezimaltrennzeichen als Punkt
s = s.Replace(".", "")
s = s.Replace(",", ".")
End If
If Double.TryParse(s, Globalization.NumberStyles.Any, Globalization.CultureInfo.InvariantCulture, d) Then
Return d
End If
Return 0
End Function
' Prüft Kopfzeile in Zeile 17:
' A17="Pos.", D17 beginnt mit "Warenbeschreibung",
' P17 beginnt mit "Importcodenummer", R17 beginnt mit "Ursprungsland"
Private Function checkExcelHeader_Fressnapf(ws As Excel.Worksheet) As Boolean
Try
Dim a = CStr(ws.Range("A17").Value)
Dim d = CStr(ws.Range("D17").Value)
If a Is Nothing OrElse d Is Nothing Then Return False
Return a.Trim().ToLower() = "pos." AndAlso
d.Trim().ToLower().StartsWith("warenbeschreibung")
Catch
Return False
End Try
End Function
End Class