Files
SDL/SDL/ZOLLSYSTEM/DAKOSY/ATLAS/EZA/cATLAS_EZA_IMPORT.vb

2011 lines
104 KiB
VB.net
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Imports System.Data.SqlClient
Imports System.Globalization
Imports DAKOSY_Worker
Imports Microsoft.Office.Interop
Imports VERAG_PROG_ALLGEMEIN
Public Class cATLAS_EZA_IMPORT
Public EZA As DAKOSY_Worker.cDakosyEZA
Dim AVISO As cAviso
Dim SENDUNG As cSendungen
Sub New(AVISO, SENDUNG, EZA)
' Dieser Aufruf ist für den Designer erforderlich.
InitializeComponent()
' Fügen Sie Initialisierungen nach dem InitializeComponent()-Aufruf hinzu.
Me.EZA = EZA
Me.SENDUNG = SENDUNG
Me.AVISO = AVISO
End Sub
Private Sub Button6_Click(sender As Object, e As EventArgs) Handles Button6.Click
Me.Cursor = Cursors.WaitCursor
importExcel_DynamicAutomotive()
Me.Cursor = Cursors.Default
End Sub
Private Function checkExcel_DynamicAutomotive(Blatt As Excel.Worksheet) As Boolean
'Prüfung
Try
If Blatt Is Nothing Then Return False
If Blatt.Range("B23") Is Nothing Then Return False
If Blatt.Range("B23").Value.ToString <> "Code" Then Return False
Catch ex As Exception
MsgBox("Fehler bei der Prüfung!" & ex.Message)
Me.Cursor = Cursors.Default
Return False
End Try
Return True
End Function
Private Function checkExcel_Geze(Blatt As Excel.Worksheet) As Boolean
'Prüfung
Try
If Blatt Is Nothing Then Return False
If Blatt.Range("I1") Is Nothing Then Return False
If Blatt.Range("I1").Value.ToString <> "Codenummer" Then Return False
Catch ex As Exception
MsgBox("Fehler bei der Prüfung!" & ex.Message)
Me.Cursor = Cursors.Default
Return False
End Try
Return True
End Function
Private Function checkExcel_MEYLE(Blatt As Excel.Worksheet) As Boolean
'Prüfung
Try
If Blatt Is Nothing Then Return False
If Blatt.Range("A3") Is Nothing Then Return False
If Blatt.Range("A3").Value.ToString <> "Eingangsrechnung Lieferant:" Then Return False
Catch ex As Exception
MsgBox("Fehler bei der Prüfung!" & ex.Message)
Me.Cursor = Cursors.Default
Return False
End Try
Return True
End Function
Private Function importExcel_DynamicAutomotive() As Boolean
' --- Dateiauswahl wie gehabt ---
Dim f As New frmImportFromAVISOAnhaenge(AVISO, SENDUNG)
f.ShowDialog(Me)
If f.DialogResult <> DialogResult.OK Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count = 0 Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count > 1 Then MsgBox("Nur 1 File auswählen!") : Return False
Dim filepath = f.LIST_FILES(0)
If Not filepath.ToLower.EndsWith(".xls") And Not filepath.ToLower.EndsWith(".xlsx") Then
Me.Cursor = Cursors.Default
Return False
End If
If True Then
Me.Cursor = Cursors.WaitCursor
Dim exclApp As New Excel.Application 'Object 'as Application
Dim Datei As Excel.Workbook ' 'as WorkBook
Dim Blatt As Excel.Worksheet 'Object 'as WorkSheet
With exclApp
Try
.CutCopyMode = False
.DisplayAlerts = False
Datei = .Workbooks.Open(filepath)
Blatt = Datei.Worksheets(1)
Datei.Activate()
Try
Blatt.ShowAllData() 'Falls Filter ausgewählt wurde
Catch ex As Exception
End Try
Dim startFound As Boolean = False
Dim endFound As Boolean = False
If Not checkExcel_DynamicAutomotive(Blatt) Then 'VALIDIERUNG
Me.Cursor = Cursors.Default
Return False
End If
If EZA.eza_WARENPOS.Count > 0 Then
If vbYes = MsgBox("Sollten die aktuellen Einträge gelöscht werden?", vbYesNo) Then
EZA.eza_WARENPOS.Clear() 'Zurücksetzen
End If
End If
Dim startRows As Integer = 24
Dim endRows As Integer = startRows
While endRows < Blatt.UsedRange.Rows.Count
If Not Blatt.Range("B" & endRows) Is Nothing AndAlso Not Blatt.Range("B" & endRows).Value Is Nothing AndAlso Not Blatt.Range("B" & endRows).Value.ToString.Trim = "" Then
endFound = True
Else
Exit While
End If
endRows += 1
End While
endRows -= 1
If Not endFound Then
MsgBox("Keine Daten vorhanden!")
Me.Cursor = Cursors.Default
Return False
End If
'Laden des Bereiches aus dem Excel:
Dim myRange As Excel.Range
myRange = Blatt.Range("B" & startRows & ":I" & endRows & "")
Dim myArray As Object(,) '<-- declared as 2D Array
myArray = myRange.Value 'store the content of each cell
'myArray(i_soll2 - startRows + 1, 4)
Dim cnt = 0
Try
For i As Integer = 1 To endRows - startRows + 1 Step 1
Dim POSITION As New DAKOSY_Worker.cDakosy_EZA_Warenposition
POSITION.ezaWP_WarennummerEZT = myArray(i, 5).ToString()
POSITION.ezaWP_PackstueckAnzahl = myArray(i, 6).ToString()
POSITION.ezaWP_PackstueckArt = "PK"
POSITION.ezaWP_Artikelpreis = CDbl(myArray(i, 8).ToString()).ToString("N2")
POSITION.ezaWP_ArtikelpreisWaehrung = "EUR"
POSITION.ezaWP_Warenbezeichnung = myArray(i, 2).ToString()
Select Case myArray(i, 4).ToString
Case "TURKEY" : POSITION.ezaWP_UrsprungslandCode = "TR"
Case "ITALY" : POSITION.ezaWP_UrsprungslandCode = "IT"
Case "SPAIN" : POSITION.ezaWP_UrsprungslandCode = "ES"
Case "GERMANY" : POSITION.ezaWP_UrsprungslandCode = "DE"
Case "CZECH REPUBLIC" : POSITION.ezaWP_UrsprungslandCode = "CZ"
Case "FRANCE" : POSITION.ezaWP_UrsprungslandCode = "FR"
End Select
EZA.eza_WARENPOS.Add(POSITION)
cnt += 1
Next
Catch ex As Exception
'MsgBox("Fehler beim Einlesen der Excel-Datei!" & vbNewLine & vbNewLine & ex.Message & ex.StackTrace)
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("Fehler beim Einlesen der Excel-Datei!" & vbNewLine & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
Me.Cursor = Cursors.Default
Return False
End Try
.Visible = False
' AddHandler exclApp.WorkbookBeforeClose, AddressOf BeforeBookClose
'Excelobjekte freistellten
' For Each obj In New Object() {exclApp, Datei, Datei, Blatt, Blatt}
' System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
' Next
Datei.Close()
MsgBox(cnt & " Datensätze wurden eingelesen. ")
Me.Cursor = Cursors.Default
Me.DialogResult = DialogResult.OK
Me.Close()
Catch ex As Exception
'
Me.Cursor = Cursors.Default
'MsgBox("FEHLER! Datei im richtigen Format?" & vbNewLine & vbNewLine & ex.Message & ex.StackTrace)
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("FEHLER! Datei im richtigen Format?" & vbNewLine & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
' Return False
End Try
End With
Return True
Else
MsgBox("Keine Datei ausgewählt!")
End If
Me.Cursor = Cursors.Default
Return False
End Function
Private Function importExcel_Geze(OP_addKN8, OP_translate, OP_TNR8to11) As Boolean
' --- Dateiauswahl wie gehabt ---
Dim f As New frmImportFromAVISOAnhaenge(AVISO, SENDUNG)
f.ShowDialog(Me)
If f.DialogResult <> DialogResult.OK Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count = 0 Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count > 1 Then MsgBox("Nur 1 File auswählen!") : Return False
Dim filepath = f.LIST_FILES(0)
If Not filepath.ToLower.EndsWith(".xls") And Not filepath.ToLower.EndsWith(".xlsx") Then
Me.Cursor = Cursors.Default
Return False
End If
If True Then
Me.Cursor = Cursors.WaitCursor
Dim exclApp As New Excel.Application 'Object 'as Application
Dim Datei As Excel.Workbook ' 'as WorkBook
Dim Blatt As Excel.Worksheet 'Object 'as WorkSheet
With exclApp
Try
.CutCopyMode = False
.DisplayAlerts = False
Datei = .Workbooks.Open(filepath)
Blatt = Datei.Worksheets(1)
Datei.Activate()
Try
Blatt.ShowAllData() 'Falls Filter ausgewählt wurde
Catch ex As Exception
End Try
Dim startFound As Boolean = False
Dim endFound As Boolean = False
If Not checkExcel_Geze(Blatt) Then 'VALIDIERUNG
Me.Cursor = Cursors.Default
Return False
End If
If EZA.eza_WARENPOS.Count > 0 Then
If vbYes = MsgBox("Sollten die aktuellen Einträge gelöscht werden?", vbYesNo) Then
EZA.eza_WARENPOS.Clear() 'Zurücksetzen
End If
End If
Dim startRows As Integer = 2
Dim endRows As Integer = startRows
While endRows < Blatt.UsedRange.Rows.Count
If Not Blatt.Range("I" & endRows) Is Nothing AndAlso Not Blatt.Range("I" & endRows).Value Is Nothing AndAlso Not Blatt.Range("I" & endRows).Value.ToString.Trim = "" Then
endFound = True
Else
Exit While
End If
endRows += 1
End While
' endRows -= 1
If Not endFound Then
MsgBox("Keine Daten vorhanden!")
Me.Cursor = Cursors.Default
Return False
End If
'Laden des Bereiches aus dem Excel:
Dim myRange As Excel.Range
myRange = Blatt.Range("A" & startRows & ":I" & endRows & "")
Dim myArray As Object(,) '<-- declared as 2D Array
myArray = myRange.Value 'store the content of each cell
'myArray(i_soll2 - startRows + 1, 4)
'For i As Integer = 1 To myArray.GetLength(0)
' For j As Integer = 1 To myArray.GetLength(1)
' Console.Write(myArray(i, j).ToString() & vbTab)
' Next
' Console.WriteLine()
'Next
Dim cnt = 0
Try
For i As Integer = 1 To endRows - startRows + 1 Step 1
If myArray(i, 1) IsNot Nothing AndAlso myArray(i, 1).ToString() <> "" Then
Dim POSITION As New DAKOSY_Worker.cDakosy_EZA_Warenposition
If cnt = 0 Then
POSITION.ezaWP_PackstueckAnzahl = SENDUNG.tblSnd_Colli
POSITION.ezaWP_PackstueckArt = "PK"
End If
POSITION.ezaWP_WarennummerEZT = myArray(i, 9).ToString()
'POSITION.ezaWP_PackstueckAnzahl = myArray(i, 6).ToString()
POSITION.ezaWP_PackstueckArt = "" '"PK"
POSITION.ezaWP_Artikelpreis = CDbl(myArray(i, 7).ToString()).ToString("N2")
POSITION.ezaWP_ArtikelpreisWaehrung = myArray(i, 8).ToString()
POSITION.ezaWP_Warenbezeichnung = myArray(i, 4).ToString()
'-------------------------------------------------------
If OP_translate Then
cDeeplAPI.deepl_Translate(POSITION.ezaWP_Warenbezeichnung, POSITION.ezaWP_Warenbezeichnung, "DE")
End If
If OP_addKN8 Then
If POSITION.ezaWP_WarennummerEZT.ToString.Length >= 8 Then
Dim Kn8Text = cTariffKN8_Interface.getKN8FromTNR(POSITION.ezaWP_WarennummerEZT.ToString.Substring(0, 8))
POSITION.ezaWP_Warenbezeichnung = Kn8Text & ",hier: " & If(POSITION.ezaWP_Warenbezeichnung, "")
End If
End If
If If(POSITION.ezaWP_Warenbezeichnung, "").Length > 240 Then
POSITION.ezaWP_Warenbezeichnung = POSITION.ezaWP_Warenbezeichnung.Substring(0, 240)
End If
'Wenn EZT Nummer 8-stellig ist, dann auf 11-stellig erweitern
If OP_TNR8to11 Then
If If(POSITION.ezaWP_WarennummerEZT, "") <> "" AndAlso (POSITION.ezaWP_WarennummerEZT.ToString.Length >= 8 And POSITION.ezaWP_WarennummerEZT.ToString.Length < 11) Then
Dim COMM_TARIFF = VERAG_PROG_ALLGEMEIN.cATEZ_Tariff.GetFullTariff_Only1Result(POSITION.ezaWP_WarennummerEZT, "TR", cboTnrDrc_Geze._value, cboTnrTrg_Geze._value)
' MsgBox(COMM_TARIFF)
If COMM_TARIFF <> "" Then
POSITION.ezaWP_WarennummerEZT = COMM_TARIFF
End If
End If
End If
'-------------------------------------------------------
'Select Case myArray(i, 4).ToString
' Case "TURKEY" : POSITION.ezaWP_UrsprungslandCode = "TR"
' Case "ITALY" : POSITION.ezaWP_UrsprungslandCode = "IT"
' Case "SPAIN" : POSITION.ezaWP_UrsprungslandCode = "ES"
' Case "GERMANY" : POSITION.ezaWP_UrsprungslandCode = "DE"
' Case "CZECH REPUBLIC" : POSITION.ezaWP_UrsprungslandCode = "CZ"
' Case "FRANCE" : POSITION.ezaWP_UrsprungslandCode = "FR"
POSITION.ezaWP_PositionsZusatz = "ArtikelNr: " & myArray(i, 1).ToString()
POSITION.ezaWP_Artikelnummer = myArray(i, 1).ToString()
'End Select
POSITION.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = "N380",
.ezaWpUl_Bereich = "4",
.ezaWpUl_VorlageKz = "J",
.ezaWpUl_Nummer = myArray(i, 2).ToString(),
.ezaWpUl_DatumAusstellung = Nothing
})
EZA.eza_WARENPOS.Add(POSITION)
cnt += 1
End If
Next
Catch ex As Exception
'MsgBox("Fehler beim Einlesen der Excel-Datei!" & vbNewLine & vbNewLine & ex.Message & ex.StackTrace)
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("Fehler beim Einlesen der Excel-Datei!" & vbNewLine & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
Me.Cursor = Cursors.Default
Return False
End Try
.Visible = False
' AddHandler exclApp.WorkbookBeforeClose, AddressOf BeforeBookClose
'Excelobjekte freistellten
' For Each obj In New Object() {exclApp, Datei, Datei, Blatt, Blatt}
' System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
' Next
Datei.Close()
Me.Cursor = Cursors.Default
Me.DialogResult = DialogResult.OK
Me.Close()
Catch ex As Exception
'
Me.Cursor = Cursors.Default
'MsgBox("FEHLER! Datei im richtigen Format?" & vbNewLine & vbNewLine & ex.Message & ex.StackTrace)
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("FEHLER! Datei im richtigen Format?" & vbNewLine & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
' Return False
End Try
End With
Return True
Else
MsgBox("Keine Datei ausgewählt!")
End If
Me.Cursor = Cursors.Default
Return False
End Function
Private Function importExcel_MEYLE() As Boolean
' --- Dateiauswahl wie gehabt ---
Dim f As New frmImportFromAVISOAnhaenge(AVISO, SENDUNG)
f.ShowDialog(Me)
If f.DialogResult <> DialogResult.OK Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count = 0 Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count > 1 Then MsgBox("Nur 1 File auswählen!") : Return False
Dim cnt = 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() 'Zurücksetzen
End If
End If
Me.Cursor = Cursors.WaitCursor
For Each filePath As String In f.LIST_FILES
If Not filePath.ToLower.EndsWith(".xls") AndAlso Not filePath.ToLower.EndsWith(".xlsx") Then
' Ungültige Datei – überspringen oder abbrechen
Continue For
End If
Dim exclApp As New Excel.Application 'Object 'as Application
Dim Datei As Excel.Workbook ' 'as WorkBook
Dim Blatt As Excel.Worksheet 'Object 'as WorkSheet
With exclApp
Try
.CutCopyMode = False
.DisplayAlerts = False
Datei = .Workbooks.Open(filePath)
Blatt = Datei.Worksheets(1)
Datei.Activate()
Try
Blatt.ShowAllData() 'Falls Filter ausgewählt wurde
Catch ex As Exception
End Try
Dim startFound As Boolean = False
Dim endFound As Boolean = False
If Not checkExcel_MEYLE(Blatt) Then 'VALIDIERUNG
Me.Cursor = Cursors.Default
Return False
End If
Dim startRows As Integer = 6
Dim endRows As Integer = startRows
While endRows < Blatt.UsedRange.Rows.Count
If Not Blatt.Range("A" & endRows) Is Nothing AndAlso Not Blatt.Range("A" & endRows).Value Is Nothing AndAlso Not Blatt.Range("A" & endRows).Value.ToString.Trim = "" Then
endFound = True
Else
Exit While
End If
endRows += 1
End While
endRows -= 1
If Not endFound Then
MsgBox("Keine Daten vorhanden!")
Me.Cursor = Cursors.Default
Return False
End If
' Neue DataTable erstellen
Dim DATA As New DataTable()
' Spalten anhand der Anzahl im Range anlegen
Dim colCount As Integer = Blatt.Range("A1:M1").Columns.Count
For c As Integer = 1 To colCount
DATA.Columns.Add("Spalte" & c, GetType(String))
Next
' Range direkt durchlaufen
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
DATA.Rows.Add(newRow)
Next
' DataTable durchlaufen und Zeilen löschen, bei denen Spalte 6 "summe" enthält
For i As Integer = DATA.Rows.Count - 1 To 0 Step -1
Dim cellValue As String = DATA.Rows(i)(6).ToString().ToLower() ' Spalte 6 = Index 5
If cellValue.Contains("summe") Then
DATA.Rows.RemoveAt(i)
End If
Next
'--------------------------------------------------------------------------------------------------------------
' Spaltenüberschriften ausgeben
For Each col As DataColumn In DATA.Columns
Console.Write(col.ColumnName & vbTab)
Next
Console.WriteLine()
' Alle Zeilen ausgeben
For Each row As DataRow In DATA.Rows
For Each col As DataColumn In DATA.Columns
Console.Write(row(col).ToString() & vbTab)
Next
Console.WriteLine()
Next
'--------------------------------------------------------------------------------------------------------------
'-------------HIER WERDEN DIE Zeilen kommuliert---------------------------------------------------------
'--------------------------------------------------------------------------------------------------------------
' Neue Tabelle mit gleicher Struktur
Dim resultDATA As DataTable = DATA.Clone()
'0 = Wartentarifnummer
'6 = Wartenbeschreibung
'12 = Währung (immer gleich)?
' Gruppieren nach den Schlüsseln Spalte 0, 6 und 12
Dim groups = From row In DATA.AsEnumerable()
Group row By key1 = row(0), key2 = row(6), key3 = row(12) Into grp = Group
Select key1, key2, key3, grp
' Gruppen durchlaufen und kumulierte Zeilen erstellen
For Each g In groups
Dim newRow As DataRow = resultDATA.NewRow()
' Gruppierungsspalten setzen
newRow(0) = g.key1
newRow(6) = g.key2
newRow(12) = g.key3
' Summen berechnen
newRow(7) = g.grp.Sum(Function(r) ToDoubleSafe(r(7)))
newRow(9) = g.grp.Sum(Function(r) ToDoubleSafe(r(9)))
newRow(11) = g.grp.Sum(Function(r) ToDoubleSafe(r(11)))
' Restliche Spalten Nothing lassen (bleibt automatisch so)
resultDATA.Rows.Add(newRow)
Next
' Falls du das Ergebnis in DATA zurückschreiben willst:
DATA = resultDATA
'--------------------------------------------------------------------------------------------------------------
'--------------------------------------------------------------------------------------------------------------
' Spaltenüberschriften ausgeben
For Each col As DataColumn In DATA.Columns
Console.Write(col.ColumnName & vbTab)
Next
Console.WriteLine()
' Alle Zeilen ausgeben
For Each row As DataRow In DATA.Rows
For Each col As DataColumn In DATA.Columns
Console.Write(row(col).ToString() & vbTab)
Next
Console.WriteLine()
Next
'--------------------------------------------------------------------------------------------------------------
Dim HandlesRgNr = ""
If Blatt.Range("B3") IsNot Nothing AndAlso Blatt.Range("B3").Value IsNot Nothing Then
HandlesRgNr = Blatt.Range("B3").Value.ToString().Trim()
End If
Dim HandlesRgDat = ""
If Blatt.Range("B1") IsNot Nothing AndAlso Blatt.Range("B1").Value IsNot Nothing Then
HandlesRgDat = Blatt.Range("B1").Value.ToString().Trim()
End If
' MsgBox("A" & startRows & ":I" & endRows & "")
Try
For Each row As DataRow In DATA.Rows
' Prüfen, ob Spalte 1 (Index 0) gefüllt ist
If row(0) IsNot Nothing AndAlso row(0).ToString().Trim() <> "" Then
Dim POSITION As New DAKOSY_Worker.cDakosy_EZA_Warenposition
POSITION.ezaWP_WarennummerEZT = row(0).ToString()
POSITION.ezaWP_PackstueckAnzahl = "0" ' row(5).ToString()
POSITION.ezaWP_PackstueckArt = "PK"
' Sicher konvertieren, falls leer oder ungültig
Dim preis As Double
Double.TryParse(row(11).ToString(), preis)
POSITION.ezaWP_Artikelpreis = preis.ToString("N2")
POSITION.ezaWP_ArtikelpreisWaehrung = row(12).ToString()
POSITION.ezaWP_Warenbezeichnung = row(6).ToString()
Dim masse As Double
Double.TryParse(row(9).ToString(), masse)
POSITION.ezaWP_Eigenmasse = masse.ToString("N1")
' Ursprungsland ggf. per Select Case setzen
'Select Case row(3).ToString()
' Case "TURKEY" : POSITION.ezaWP_UrsprungslandCode = "TR"
' Case "ITALY" : POSITION.ezaWP_UrsprungslandCode = "IT"
' ...
'End Select
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
})
EZA.eza_WARENPOS.Add(POSITION)
cnt += 1
End If
Next
Catch ex As Exception
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("Fehler beim Einlesen der Excel-Datei!" & vbNewLine & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
Me.Cursor = Cursors.Default
Return False
End Try
.Visible = False
' AddHandler exclApp.WorkbookBeforeClose, AddressOf BeforeBookClose
'Excelobjekte freistellten
' For Each obj In New Object() {exclApp, Datei, Datei, Blatt, Blatt}
' System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
' Next
Datei.Close()
Catch ex As Exception
'
Me.Cursor = Cursors.Default
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("FEHLER! Datei im richtigen Format?" & vbNewLine & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
' Return False
End Try
End With
' >>> Hier kannst du jede gültige Excel-Datei weiterverarbeiten:
Console.WriteLine("Verarbeite Datei: " & filePath)
' z. B. Excel öffnen, Range lesen etc.
Next
MsgBox(cnt & " Datensätze wurden eingelesen. ")
Me.Cursor = Cursors.Default
Me.DialogResult = DialogResult.OK
Me.Close()
Return True
End Function
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
Me.Cursor = Cursors.WaitCursor
importExcel_Geze(cbxGezeKN8.Checked, cbxGezeTranslate.Checked, cbxGezeTNR8to11.Checked)
Me.Cursor = Cursors.Default
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Me.Cursor = Cursors.WaitCursor
importExcel_MEYLE()
Me.Cursor = Cursors.Default
End Sub
Private Sub Button5_Click(sender As Object, e As EventArgs) Handles Button5.Click
Me.Cursor = Cursors.WaitCursor
importExcel_Fressnapf()
Me.Cursor = Cursors.Default
End Sub
Private Function importExcel_Fressnapf() As Boolean
' --- Dateiauswahl wie gehabt ---
Dim f As New frmImportFromAVISOAnhaenge(AVISO, SENDUNG)
f.ShowDialog(Me)
If f.DialogResult <> DialogResult.OK Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count = 0 Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count > 1 Then MsgBox("Nur 1 File auswählen!") : Return False
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 f.LIST_FILES
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
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("FEHLER beim Einlesen: " & vbCrLf & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
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
MsgBox(cnt & " Datensätze wurden eingelesen.")
Me.Cursor = Cursors.Default
Me.DialogResult = DialogResult.OK
Me.Close()
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
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Cursor = Cursors.WaitCursor
ImportExcel_CustomsTemplate_V1(cbxVERAG_V1_Kn8.Checked, cbxVERAG_V1_translate.Checked, cbxVERAG_V1_TNR8to11.Checked)
Me.Cursor = Cursors.Default
'ImportExcel_CustomsTemplate_V1_1(cbxVERAG_V1_Kn8.Checked, cbxVERAG_V1_translate.Checked, cbxVERAG_V1_TNR8to11.Checked)
End Sub
'================================================================================================================================
'================================================================================================================================
'================================================================================================================================
Public Function ImportExcel_CustomsTemplate_V1(OP_addKN8, OP_translate, OP_TNR8to11) As Boolean
' --- Dateiauswahl wie gehabt ---
Dim f As New frmImportFromAVISOAnhaenge(AVISO, SENDUNG)
f.ShowDialog(Me)
If f.DialogResult <> DialogResult.OK Then Return False
If f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count = 0 Then Return False
' --- ggf. vorhandene Positionen leeren ---
If EZA.eza_WARENPOS.Count > 0 Then
If vbYes = MsgBox("Sollen vorhandene Positionen gelöscht werden?", vbYesNo) Then
EZA.eza_WARENPOS.Clear()
End If
End If
Me.Cursor = Cursors.WaitCursor
Dim cnt As Integer = 0
For Each filePath As String In f.LIST_FILES
If Not (filePath.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase) OrElse filePath.EndsWith(".xls", StringComparison.OrdinalIgnoreCase)) Then
Continue For
End If
Dim xlApp As Excel.Application = Nothing
Dim wb As Excel.Workbook = Nothing
Dim ws As Excel.Worksheet = Nothing
Try
xlApp = New Excel.Application()
xlApp.DisplayAlerts = False
xlApp.CutCopyMode = False
wb = xlApp.Workbooks.Open(filePath)
ws = CType(wb.Worksheets(1), Excel.Worksheet)
wb.Activate()
' Falls Autofilter aktiv: ShowAllData() versuchen (optional)
Try
ws.ShowAllData()
Catch
End Try
' ---------- VERSIONSPRÜFUNG V1 und V1.1 unterstützt ----------
Dim versionTag As String = GetCellStr(ws, 2, 8) ' H2
If Not String.Equals(versionTag, "2025-V1", StringComparison.OrdinalIgnoreCase) Or
Not String.Equals(versionTag, "2025-V1.1", StringComparison.OrdinalIgnoreCase) Then
Throw New ApplicationException("Version nicht unterstützt (gefunden: '" & versionTag & "', erwartet: '2025-V1').")
End If
' ---------- 1) HEADER KEY/VALUE (A/B) ----------
Dim header As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
Dim usedRows As Integer = ws.UsedRange.Rows.Count
Dim r As Integer
For r = 3 To Math.Min(80, usedRows + 5)
Dim k As String = GetCellStr(ws, r, 1)
Dim v As String = GetCellStr(ws, r, 2)
If Not String.IsNullOrWhiteSpace(k) Then header(k) = v
Next
' ein paar Kopfwerte ins EZA (alle optional)
Dim HandelsRgNr As String = ""
Dim HandelsRgDat As String = ""
If header.ContainsKey("Invoice No.") Then HandelsRgNr = header("Invoice No.")
If header.ContainsKey("Invoice Date") Then HandelsRgDat = header("Invoice Date")
If header.ContainsKey("Currency") Then EZA.eza_Rechnungswaehrung = header("Currency")
If header.ContainsKey("Delivery Terms (Incoterms)") Then EZA.eza_LieferbedingungCode = header("Delivery Terms (Incoterms)")
' If header.ContainsKey("Total Gross Weight (kg)") Then EZA.eza_GesamtRohmasse = ToDoubleSafeVERAGTmpl(header("Total Gross Weight (kg)")) -> nur in pos!
If header.ContainsKey("Truck Plate (Tractor)") Then EZA.eza_KennzeichenNameBefoerderungsmittelAnkunft = header("Truck Plate (Tractor)")
' ---------- 2) CONSIGNOR / CONSIGNEE ----------
Dim rowCons As Integer = -1
Dim rowCee As Integer = -1
For r = 3 To Math.Min(80, usedRows + 5)
Dim aVal As String = GetCellStr(ws, r, 1)
If rowCons < 0 AndAlso String.Equals(aVal, "Consignor / Exporter", StringComparison.OrdinalIgnoreCase) Then rowCons = r
If rowCee < 0 AndAlso String.Equals(aVal, "Consignee / Importer", StringComparison.OrdinalIgnoreCase) Then rowCee = r
If rowCons > 0 AndAlso rowCee > 0 Then Exit For
Next
' Kundennummern nur ermitteln, wenn die Blöcke auch existieren
Dim kdnrImp As String = If(rowCee > 0, GetCellStr(ws, rowCee + 1, 6), "")
Dim kdnrCons As String = If(rowCons > 0, GetCellStr(ws, rowCons + 1, 6), "")
If rowCons > 0 Then
'Prüfen, ob Adresse schon vorhanden:
If Not EZA.eza_ADRESSEN.Any(Function(a) a.ezaAd_AdressTyp IsNot Nothing AndAlso a.ezaAd_AdressTyp.ToString().ToUpper() = "CZ") Then
Dim rr As Integer = rowCons + 1
Dim adrC As New cDakosy_EZA_Adressen()
adrC.ezaAd_AdressTyp = "CZ"
If Not String.IsNullOrWhiteSpace(kdnrCons) Then
' --- Daten aus Datenbank (cAdressen) laden ---
Dim AD As New cAdressen(kdnrCons)
Dim KD As New cKunde(kdnrCons)
adrC.ezaAd_NameFirma1 = AD.Name_1
adrC.ezaAd_LandCode = cProgramFunctions.getISO2Land(AD.LandKz)
adrC.ezaAd_PLZ = AD.PLZ
adrC.ezaAd_Ort = AD.Ort
adrC.ezaAd_StrasseHausNr1 = AD.Straße
If Not String.IsNullOrWhiteSpace(KD.EORITIN) Then adrC.ezaAd_TeilnehmerEORI = KD.EORITIN
Else
' --- Excel-Werte (alle optional) ---
Dim consCompany As String = GetCellStr(ws, rr, 1)
Dim consCountry As String = GetCellStr(ws, rr, 2).ToUpperInvariant()
Dim consZIP As String = GetCellStr(ws, rr, 3)
Dim consCity As String = GetCellStr(ws, rr, 4)
Dim consStreet As String = GetCellStr(ws, rr, 5)
If consCompany <> "" Then adrC.ezaAd_NameFirma1 = consCompany
If consCountry <> "" Then adrC.ezaAd_LandCode = consCountry
If consZIP <> "" Then adrC.ezaAd_PLZ = consZIP
If consCity <> "" Then adrC.ezaAd_Ort = consCity
If consStreet <> "" Then adrC.ezaAd_StrasseHausNr1 = consStreet
End If
EZA.eza_ADRESSEN.Add(adrC)
End If
End If
If rowCee > 0 Then
'Prüfen, ob Adresse schon vorhanden:
If Not EZA.eza_ADRESSEN.Any(Function(a) a.ezaAd_AdressTyp IsNot Nothing AndAlso a.ezaAd_AdressTyp.ToString().ToUpper() = "CN") Then
Dim rr As Integer = rowCee + 1
Dim adrE As New cDakosy_EZA_Adressen()
adrE.ezaAd_AdressTyp = "CN"
If Not String.IsNullOrWhiteSpace(kdnrImp) Then
' --- Daten aus Datenbank (cAdressen) laden ---
Dim AD As New cAdressen(kdnrImp)
Dim KD As New cKunde(kdnrImp)
adrE.ezaAd_NameFirma1 = AD.Name_1
adrE.ezaAd_LandCode = cProgramFunctions.getISO2Land(AD.LandKz)
adrE.ezaAd_PLZ = AD.PLZ
adrE.ezaAd_Ort = AD.Ort
adrE.ezaAd_StrasseHausNr1 = AD.Straße
If Not String.IsNullOrWhiteSpace(KD.EORITIN) Then adrE.ezaAd_TeilnehmerEORI = KD.EORITIN
Else
' --- Excel-Werte (alle optional) ---
Dim ceeCompany As String = GetCellStr(ws, rr, 1)
Dim ceeCountry As String = GetCellStr(ws, rr, 2).ToUpperInvariant()
Dim ceeZIP As String = GetCellStr(ws, rr, 3)
Dim ceeCity As String = GetCellStr(ws, rr, 4)
Dim ceeStreet As String = GetCellStr(ws, rr, 5)
If ceeCompany <> "" Then adrE.ezaAd_NameFirma1 = ceeCompany
If ceeCountry <> "" Then adrE.ezaAd_LandCode = ceeCountry
If ceeZIP <> "" Then adrE.ezaAd_PLZ = ceeZIP
If ceeCity <> "" Then adrE.ezaAd_Ort = ceeCity
If ceeStreet <> "" Then adrE.ezaAd_StrasseHausNr1 = ceeStreet
End If
EZA.eza_ADRESSEN.Add(adrE)
End If
End If
' ---------- 3) ITEM-TABELLE (optional) ----------
' Finde Titelzeile "Item Lines (add as many as needed)" in Spalte A
Dim rowItemsTitle As Integer = -1
For r = 10 To Math.Min(200, usedRows + 10)
If String.Equals(GetCellStr(ws, r, 1), "Item Lines (add as many as needed)", StringComparison.OrdinalIgnoreCase) Then
rowItemsTitle = r
Exit For
End If
Next
If rowItemsTitle > 0 Then
Dim rowHdr As Integer = rowItemsTitle + 1
Dim usedCols As Integer = ws.UsedRange.Columns.Count
' Header-Indices (alle optional)
Dim cLine As Integer = -1, cArticle As Integer = -1, cDesc As Integer = -1, cShortDesc As Integer = -1
Dim cHs As Integer = -1, cOrigin As Integer = -1, cPkgs As Integer = -1, cPkgType As Integer = -1
Dim cGross As Integer = -1, cNet As Integer = -1, cUnit As Integer = -1, cTotal As Integer = -1, cCurr As Integer = -1
Dim cPrefCountry = "", cBenefit = "", cCurrProc = "", cPrevProc = "", cprefCode = "", cprefDocNo = "", cYCodes = ""
Dim c As Integer
For c = 1 To usedCols
Dim h As String = GetCellStr(ws, rowHdr, c).ToLowerInvariant().Replace(vbNewLine, "")
h = h.Replace("(optional)", "").Trim()
Select Case h
Case "line no.", "line no" : cLine = c
Case "article no.", "article no" : cArticle = c
Case "goods description" : cDesc = c
Case "short description" : cShortDesc = c
Case "hs code" : cHs = c
Case "origin country" : cOrigin = c
Case "packages" : cPkgs = c
Case "package type" : cPkgType = c
Case "gross weight (kg)" : cGross = c
Case "net weight (kg)" : cNet = c
Case "unit price" : cUnit = c
Case "total value" : cTotal = c
Case "currency" : cCurr = c
'Case "Invoice Line No."
Case "preferential country origin" : cPrefCountry = c
Case "preferential treatment / benefit" : cBenefit = c
Case "requested procedure" : cCurrProc = c
Case "previous procedure" : cPrevProc = c
Case "preference code" : cprefCode = c
Case "preferential document no" : cprefDocNo = c
Case "y-codes" : cYCodes = c
End Select
Next
' Datenzeilen lesen: ab rowHdr+1 bis zur ersten komplett leeren Zeile
Dim rData As Integer = rowHdr + 1
Dim lastRow As Integer = ws.UsedRange.Rows.Count + 5
Dim tariffCache As New Dictionary(Of String, String)
While rData <= lastRow
Dim anyVal As Boolean = False
For c = 1 To usedCols
If GetCellStr(ws, rData, c) <> "" Then
anyVal = True
Exit For
End If
Next
If Not anyVal Then Exit While
' Werte nur holen, wenn es die Spalten gibt
Dim descTxt As String = If(cDesc > 0, GetCellStr(ws, rData, cDesc), "")
Dim hs As String = If(cHs > 0, GetCellStr(ws, rData, cHs), "")
' Wenn gar nichts Sinnvolles da ist, Zeile überspringen
If descTxt = "" AndAlso hs = "" AndAlso (cArticle <= 0 OrElse GetCellStr(ws, rData, cArticle) = "") Then
rData += 1
Continue While
End If
Dim pos As New cDakosy_EZA_Warenposition()
If cLine > 0 Then pos.ezaWP_PositionsNummer = GetCellStr(ws, rData, cLine)
If cArticle > 0 Then pos.ezaWP_Artikelnummer = GetCellStr(ws, rData, cArticle)
Dim shortTxt As String = If(cShortDesc > 0, GetCellStr(ws, rData, cShortDesc), "")
If shortTxt <> "" Then
pos.ezaWP_Warenbezeichnung = shortTxt
ElseIf descTxt <> "" Then
pos.ezaWP_Warenbezeichnung = descTxt
End If
If hs <> "" Then pos.ezaWP_WarennummerEZT = hs
' Optional: Zollartikel-Stammdaten überschreiben, wenn Kundennummer vorhanden
Dim Kdnr As String = If(Not String.IsNullOrWhiteSpace(kdnrImp), kdnrImp, If(Not String.IsNullOrWhiteSpace(kdnrCons), kdnrCons, ""))
If Kdnr <> "" Then
Try
Dim ZAL = cZollArtikel.GetListByKundenNr(Kdnr) ' Annahme: Methode vorhanden
' Artikelnummer als Schlüssel: nur wenn vorhanden
Dim artKey As String = If(cArticle > 0, GetCellStr(ws, rData, cArticle), "")
If Not String.IsNullOrWhiteSpace(artKey) AndAlso ZAL IsNot Nothing Then
Dim Artikel = cZollArtikel.FindZollArtikelByNummer(ZAL, artKey)
If Artikel IsNot Nothing Then
If Artikel.zollArt_Warenbeschreibung IsNot Nothing AndAlso Artikel.zollArt_Warenbeschreibung.ToString() <> "" Then
pos.ezaWP_Warenbezeichnung = Artikel.zollArt_Warenbeschreibung.ToString()
End If
If Artikel.zollArt_Warencodenummer IsNot Nothing AndAlso Artikel.zollArt_Warencodenummer.ToString() <> "" Then
pos.ezaWP_WarennummerEZT = Artikel.zollArt_Warencodenummer.ToString()
End If
End If
End If
Catch
' Stammdaten-Lookup ist optional; Fehler hier nicht fatal
End Try
End If
'------------------------------------------------
If OP_translate Then
cDeeplAPI.deepl_Translate(pos.ezaWP_Warenbezeichnung, pos.ezaWP_Warenbezeichnung, "DE")
End If
If OP_addKN8 Then
If pos.ezaWP_WarennummerEZT.ToString.Length >= 8 Then
Dim Kn8Text = cTariffKN8_Interface.getKN8FromTNR(pos.ezaWP_WarennummerEZT.ToString.Substring(0, 8))
pos.ezaWP_Warenbezeichnung = Kn8Text & ",hier: " & If(pos.ezaWP_Warenbezeichnung, "")
End If
End If
If If(pos.ezaWP_Warenbezeichnung, "").Length > 240 Then
pos.ezaWP_Warenbezeichnung = pos.ezaWP_Warenbezeichnung.Substring(0, 240)
End If
'Wenn EZT Nummer 8-stellig ist, dann auf 11-stellig erweitern
If OP_TNR8to11 Then
If If(pos.ezaWP_WarennummerEZT, "") <> "" AndAlso (pos.ezaWP_WarennummerEZT.ToString.Length >= 8 And pos.ezaWP_WarennummerEZT.ToString.Length < 11) Then
Dim hsTmp = pos.ezaWP_WarennummerEZT.ToString()
Dim COMM_TARIFF As String = ""
' Prüfen ob bereits abgefragt
If tariffCache.ContainsKey(hsTmp) Then
pos.ezaWP_WarennummerEZT = tariffCache(hsTmp)
Else
pos.ezaWP_WarennummerEZT = VERAG_PROG_ALLGEMEIN.cATEZ_Tariff.GetFullTariff_Only1Result(hsTmp, cboTnrSrc_VERAGImp._value, cboTnrTrg_VERAGImp._value)
tariffCache(hsTmp) = pos.ezaWP_WarennummerEZT
End If
End If
End If
'------------------------------------------------
If If(pos.ezaWP_Warenbezeichnung, "").Length > 240 Then
pos.ezaWP_Warenbezeichnung = pos.ezaWP_Warenbezeichnung.Substring(0, 240)
End If
Dim origin As String = If(cOrigin > 0, GetCellStr(ws, rData, cOrigin).ToUpperInvariant(), "")
If origin.Length >= 2 Then pos.ezaWP_UrsprungslandCode = origin.Substring(0, 2)
If cPkgs > 0 Then
Dim pk As String = GetCellStr(ws, rData, cPkgs)
If pk <> "" Then pos.ezaWP_PackstueckAnzahl = pk
End If
If cPkgType > 0 Then
Dim pt As String = GetCellStr(ws, rData, cPkgType)
If pt <> "" Then pos.ezaWP_PackstueckArt = pt
End If
If cGross > 0 Then
Dim g As Double = ToDoubleSafeVERAGTmpl(GetCellStr(ws, rData, cGross))
If g > 0 Then pos.ezaWP_Rohmasse = g
End If
If cNet > 0 Then
Dim n As Double = ToDoubleSafeVERAGTmpl(GetCellStr(ws, rData, cNet))
If n > 0 Then pos.ezaWP_Eigenmasse = n
End If
If cTotal > 0 Then
Dim totalVal As Double = ToDoubleSafeVERAGTmpl(GetCellStr(ws, rData, cTotal))
pos.ezaWP_Artikelpreis = totalVal
End If
Dim curr As String = If(cCurr > 0, GetCellStr(ws, rData, cCurr).ToUpperInvariant(), "")
If curr = "" Then
If header.ContainsKey("Currency") Then
pos.ezaWP_ArtikelpreisWaehrung = header("Currency").ToUpperInvariant()
Else
pos.ezaWP_ArtikelpreisWaehrung = "EUR"
End If
Else
pos.ezaWP_ArtikelpreisWaehrung = curr
End If
If cPrefCountry <> "" Then
If cPrefCountry.Length >= 2 Then pos.ezaWP_UrsprungslandCode = origin.Substring(0, 2)
End If
If cBenefit <> "" Then
pos.ezaWP_BeguenstigungBenatragtCode = cBenefit
End If
If cPrevProc <> "" Then
pos.ezaWP_VerfahrensCodeVorangegangenesVerfahren = cPrevProc
End If
If cCurrProc <> "" Then
pos.ezaWP_AnmeldeVErfahren = cCurrProc
End If
If cYCodes <> "" Then
cYCodes = cYCodes.Replace(";", ",").Replace("/", ",").Replace("+", ",").Replace("-", ",")
If cYCodes.Contains(",") Then
Dim s = cYCodes.Split(",")
For Each ycode In s
If ycode.Trim() <> "" Then
pos.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = ycode.Trim(),
.ezaWpUl_Bereich = "5",
.ezaWpUl_VorlageKz = "J",
.ezaWpUl_Nummer = cprefDocNo,
.ezaWpUl_DatumAusstellung = Nothing
})
End If
Next
Else
pos.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = cYCodes,
.ezaWpUl_Bereich = "5",
.ezaWpUl_VorlageKz = "J",
.ezaWpUl_Nummer = cprefDocNo,
.ezaWpUl_DatumAusstellung = Nothing
})
End If
End If
If cprefCode <> "" And cprefDocNo <> "" Then
Try
Dim Pref_art = ""
Dim Pref_bereich = ""
If cprefCode.Contains("/") Then
Dim s = cprefCode.Split("/")
Pref_art = s(1)
Pref_bereich = s(0)
Else
Pref_art = cprefCode
Select Case cprefCode
Case "N954" : Pref_bereich = "3"
Case "N018" : Pref_bereich = "6"
Case "ATR", "A.TR" : Pref_bereich = "N018" : Pref_art = "6"
Case "EUR1", "EUR.1" : Pref_bereich = "N954" : Pref_art = "3"
End Select
End If
pos.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = Pref_art,
.ezaWpUl_Bereich = Pref_bereich,
.ezaWpUl_VorlageKz = "J",
.ezaWpUl_Nummer = cprefDocNo,
.ezaWpUl_DatumAusstellung = Nothing
})
Catch
End Try
End If
If HandelsRgNr <> "" Then
Try
pos.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = "N380",
.ezaWpUl_Bereich = "4",
.ezaWpUl_VorlageKz = "J",
.ezaWpUl_Nummer = HandelsRgNr,
.ezaWpUl_DatumAusstellung = If(HandelsRgDat <> "" AndAlso IsDate(HandelsRgDat), CDate(HandelsRgDat).ToShortDateString, Nothing)
})
Catch
End Try
End If
EZA.eza_WARENPOS.Add(pos)
cnt += 1
rData += 1
End While
End If ' rowItemsTitle > 0 (wenn nicht gefunden: Items optional – Abschnitt wird einfach übersprungen)
Catch ex As Exception
MsgBox("FEHLER beim Einlesen (" & filePath & "):" & vbCrLf & ex.Message, vbCritical)
Finally
' --- COM sauber freigeben ---
Try
If wb IsNot Nothing Then wb.Close(False)
Catch
End Try
Try
If xlApp IsNot Nothing Then xlApp.Quit()
Catch
End Try
Try
If ws IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(ws)
Catch
End Try
Try
If wb IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(wb)
Catch
End Try
Try
If xlApp IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)
Catch
End Try
ws = Nothing : wb = Nothing : xlApp = Nothing
GC.Collect()
GC.WaitForPendingFinalizers()
End Try
Next
' --- UI Refresh wie gehabt ---
MsgBox(cnt & " Datensätze wurden eingelesen.")
Me.Cursor = Cursors.Default
Me.DialogResult = DialogResult.OK
Me.Close()
Return True
End Function
Private Function GetCellStr(ws As Excel.Worksheet, r As Integer, c As Integer) As String
Try
Dim v = ws.Cells(r, c).Value
Return If(v IsNot Nothing, v.ToString().Trim(), "")
Catch
Return ""
End Try
End Function
Private Function ToDoubleSafeVERAGTmpl(v As Object) As Double
If v Is Nothing Then Return 0
Dim s As String = v.ToString().Trim().Replace(",", ".")
Dim d As Double
If Double.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, d) Then
Return d
End If
Return 0
End Function
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click, Button7.Click
Try
' Zielpfad im Temp-Ordner festlegen
Dim tempFile As String = ""
If sender Is Button7 Then : tempFile = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Customs_Clearance_Template_2025V1.xlsx")
ElseIf sender Is Button4 Then : tempFile = System.IO.Path.Combine(System.IO.Path.GetTempPath(), "Customs_Clearance_Template_V1.1.xlsx")
End If
' Ressource (als Binärdatei eingebunden) schreiben
System.IO.File.WriteAllBytes(tempFile, My.Resources.Customs_Clearance_Template)
' Datei mit dem Standardprogramm öffnen (z. B. Excel)
Process.Start(New ProcessStartInfo(tempFile) With {.UseShellExecute = True})
Catch ex As Exception
MsgBox("Fehler beim Öffnen der Vorlage: " & ex.Message, vbCritical)
End Try
End Sub
' In cATLAS_EZA_IMPORT einfügen; bestehenden Button8_Click ersetzen.
' Benötigt: Imports System.Globalization, Imports Microsoft.Office.Interop
' In cATLAS_EZA_IMPORT einfügen; bestehenden Button8_Click ersetzen.
' Benötigt: Imports System.Globalization, Imports Microsoft.Office.Interop
' In cATLAS_EZA_IMPORT einfügen; bestehenden Button8_Click ersetzen.
' Benötigt: Imports System.Globalization, Imports Microsoft.Office.Interop
Private Sub Button8_Click(sender As Object, e As EventArgs) Handles Button8.Click
Try
Me.Cursor = Cursors.WaitCursor
importExcel_TetraPak(cbxGezeKN8.Checked, cbxGezeTranslate.Checked, cbxGezeTNR8to11.Checked)
Finally
Me.Cursor = Cursors.Default
End Try
End Sub
' In cATLAS_EZA_IMPORT einfügen. Vorhandene Tetra*-Hilfsfunktionen durch diese Version ersetzen.
' Erforderliche Imports: System.Data.SqlClient, System.Globalization, System.Linq,
' System.Text.RegularExpressions, Microsoft.Office.Interop (Excel-Alias wie im Projekt vorhanden).
' Der bestehende Button8_Click kann unverändert importExcel_TetraPak() aufrufen.
Private Function importExcel_TetraPak(OP_addKN8 As Boolean, OP_translate As Boolean, OP_TNR8to11 As Boolean) As Boolean
Dim f As New frmImportFromAVISOAnhaenge(AVISO, SENDUNG)
f.ShowDialog(Me)
If f.DialogResult <> DialogResult.OK OrElse f.LIST_FILES Is Nothing OrElse f.LIST_FILES.Count <> 1 Then Return False
Dim filePath As String = f.LIST_FILES(0)
If Not (filePath.EndsWith(".xlsx", StringComparison.OrdinalIgnoreCase) OrElse filePath.EndsWith(".xls", StringComparison.OrdinalIgnoreCase)) Then Return False
Dim xlApp As Excel.Application = Nothing
Dim wb As Excel.Workbook = Nothing
Dim ws As Excel.Worksheet = Nothing
Dim used As Excel.Range = Nothing
Dim imported As New List(Of DAKOSY_Worker.cDakosy_EZA_Warenposition)
Dim warnings As New List(Of String)
Try
xlApp = New Excel.Application With {.DisplayAlerts = False, .Visible = False}
wb = xlApp.Workbooks.Open(filePath, ReadOnly:=True)
ws = CType(wb.Worksheets(1), Excel.Worksheet)
used = ws.UsedRange
Dim lastRow As Integer = used.Row + used.Rows.Count - 1
Dim lastCol As Integer = used.Column + used.Columns.Count - 1
If lastRow < 2 Then Return False
' Einmaliges Lesen des Datenblocks statt tausender COM-Zugriffe.
Dim values As Object(,) = CType(ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, lastCol)).Value2, Object(,))
Dim head As New Dictionary(Of String, Integer)(StringComparer.OrdinalIgnoreCase)
For c As Integer = 1 To lastCol
Dim h As String = TetraCell(values(1, c))
If h <> "" AndAlso Not head.ContainsKey(h) Then head.Add(h, c)
Next
' Neues Layout zuerst; alte Feldnamen nur dort, wo sie dieselbe Bedeutung haben.
Dim kopf As New Dictionary(Of String, String)(StringComparer.OrdinalIgnoreCase)
Dim kopfFields As String() = {"Country of Destination", "Country of Dispatch", "Shipment Gross Weight (kg)", "Importer EORI Number", "Invoice Reference Number", "MIC Invoice Number", "Invoice Value", "Currency", "Term of Delivery", "Term of Delivery Place", "Seller Name 1", "Seller Name 2", "Seller Street", "Seller City", "Seller Country", "Supplier Name 1", "Supplier Name 2", "Supplier Street", "Supplier City", "Supplier Country", "Freight Costs", "Currency Freight Costs", "Insurance Costs", "Currency Insurance Costs", "Inland Freight Costs", "Currency Inland Freight", "Other Expenses Costs", "Currency Other Expenses", "Package Information", "Invoice Type", "Office of Entry", "Mode of Transport at the Border", "Identity of the means of transport at the border", "Nationality of the means of transport at the border", "Inland Mode of Transport", "Identity of the inland means of transport"}
For r As Integer = 2 To lastRow
For Each k As String In kopfFields
Dim v As String = TetraGet(values, head, r, k)
If v <> "" AndAlso (Not kopf.ContainsKey(k) OrElse kopf(k) = "") Then kopf(k) = v
Next
Next
Dim currency As String = TetraKopf(kopf, "Currency").ToUpperInvariant()
Dim invoiceNo As String = TetraKopf(kopf, "Invoice Reference Number")
If invoiceNo = "" Then invoiceNo = TetraGet(values, head, 2, "Invoice Number")
Dim invoiceType As String = TetraKopf(kopf, "Invoice Type").ToUpperInvariant()
If invoiceType = "" Then invoiceType = "N380"
Dim invoiceValue As Decimal
Dim hasInvoiceValue As Boolean = TetraTryDecimal(TetraKopf(kopf, "Invoice Value"), invoiceValue)
Dim knownOrigins As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
For r As Integer = 2 To lastRow
Dim o As String = TetraGet(values, head, r, "Country of Origin").ToUpperInvariant()
If o <> "" Then knownOrigins.Add(o)
Next
Dim commonOrigin As String = If(knownOrigins.Count = 1, knownOrigins.FirstOrDefault(), "")
For r As Integer = 2 To lastRow
Dim line As String = TetraGet(values, head, r, "Shipment Line")
Dim article As String = TetraGet(values, head, r, "Part Number")
Dim description As String = TetraGet(values, head, r, "Part Description")
Dim tariff As String = TetraGet(values, head, r, "Tariff Number").Replace(" ", "")
Dim origin As String = TetraGet(values, head, r, "Country of Origin").Trim().ToUpperInvariant()
If origin = "" AndAlso commonOrigin <> "" Then origin = commonOrigin
If origin = "RS" Then origin = "XS"
Dim netText As String = TetraGet(values, head, r, "Net Weight (kg)")
Dim grossText As String = TetraGet(values, head, r, "Gross Weight (kg)")
Dim valueText As String = TetraGet(values, head, r, "Line Value")
Dim procedure As String = TetraGet(values, head, r, "Import Customs Procedure").Replace(" ", "")
If line = "" AndAlso article = "" AndAlso description = "" AndAlso tariff = "" AndAlso origin = "" AndAlso netText = "" AndAlso grossText = "" AndAlso valueText = "" AndAlso procedure = "" Then Continue For
Dim pos As New DAKOSY_Worker.cDakosy_EZA_Warenposition
pos.ezaWP_VerfahrensCodeVorangegangenesVerfahren = "00"
If line <> "" Then pos.ezaWP_PositionsNummer = line Else pos.ezaWP_PositionsNummer = (imported.Count + 1).ToString(CultureInfo.InvariantCulture)
If article <> "" Then pos.ezaWP_Artikelnummer = article
If description <> "" Then pos.ezaWP_Warenbezeichnung = description
If tariff <> "" Then pos.ezaWP_WarennummerEZT = tariff
' GEZE-Logik: Übersetzung -> KN8-Text -> Erweiterung auf 11 Stellen.
If OP_translate AndAlso Not String.IsNullOrWhiteSpace(pos.ezaWP_Warenbezeichnung) Then
cDeeplAPI.deepl_Translate(pos.ezaWP_Warenbezeichnung, pos.ezaWP_Warenbezeichnung, "DE")
End If
If OP_addKN8 AndAlso If(pos.ezaWP_WarennummerEZT, "").Length >= 8 Then
Dim kn8Text As String = cTariffKN8_Interface.getKN8FromTNR(pos.ezaWP_WarennummerEZT.Substring(0, 8))
If Not String.IsNullOrWhiteSpace(kn8Text) Then pos.ezaWP_Warenbezeichnung = kn8Text & ",hier: " & If(pos.ezaWP_Warenbezeichnung, "")
End If
If If(pos.ezaWP_Warenbezeichnung, "").Length > 240 Then pos.ezaWP_Warenbezeichnung = pos.ezaWP_Warenbezeichnung.Substring(0, 240)
If OP_TNR8to11 AndAlso If(pos.ezaWP_WarennummerEZT, "").Length >= 8 AndAlso pos.ezaWP_WarennummerEZT.Length < 11 Then
Dim fullTariff As String = VERAG_PROG_ALLGEMEIN.cATEZ_Tariff.GetFullTariff_Only1Result(pos.ezaWP_WarennummerEZT, "TR", cboTnrDrc_Geze._value, cboTnrTrg_Geze._value)
If Not String.IsNullOrWhiteSpace(fullTariff) Then pos.ezaWP_WarennummerEZT = fullTariff
End If
If origin <> "" Then pos.ezaWP_UrsprungslandCode = origin
If currency <> "" Then pos.ezaWP_ArtikelpreisWaehrung = currency
Dim n As Decimal
If TetraTryDecimal(netText, n) Then pos.ezaWP_Eigenmasse = n.ToString("0.###", CultureInfo.CurrentCulture)
If TetraTryDecimal(grossText, n) Then pos.ezaWP_Rohmasse = CDbl(n)
If TetraTryDecimal(valueText, n) Then pos.ezaWP_Artikelpreis = n.ToString("0.00", CultureInfo.CurrentCulture)
If procedure.Length >= 2 Then pos.ezaWP_AnmeldeVErfahren = procedure.Substring(0, 2)
If procedure.Length >= 4 Then pos.ezaWP_VerfahrensCodeVorangegangenesVerfahren = procedure.Substring(2, 2)
Dim pref As String = TetraGet(values, head, r, "Preference Code")
If pref <> "" Then pos.ezaWP_BeguenstigungBenatragtCode = pref
' Alte Datei: explizite Packstückfelder; neue Datei: Gesamt-Packstückinfo in AG (unten verteilt).
Dim pkgCount As Decimal
If TetraTryDecimal(TetraGet(values, head, r, "Number of Packages"), pkgCount) Then pos.ezaWP_PackstueckAnzahl = pkgCount.ToString("0", CultureInfo.InvariantCulture)
Dim pkgType As String = TetraGet(values, head, r, "Package Type")
If pkgType <> "" Then pos.ezaWP_PackstueckArt = pkgType
If invoiceNo <> "" Then
pos.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = invoiceType, .ezaWpUl_Bereich = "4", .ezaWpUl_VorlageKz = "J", .ezaWpUl_Nummer = invoiceNo, .ezaWpUl_DatumAusstellung = Nothing
})
End If
Dim ycodes As String = TetraGet(values, head, r, "Y-Document Codes", "Y-Document Type")
For Each code As String In ycodes.Split(New Char() {","c, ";"c}, StringSplitOptions.RemoveEmptyEntries)
Dim docCode As String = code.Trim().ToUpperInvariant()
If docCode <> "" Then
pos.ezaWP_UNTERLAGEN.Add(New DAKOSY_Worker.cDakosy_EZA_WarenpositionVorgelegteUnterlagen With {
.ezaWpUl_Art = docCode, .ezaWpUl_Bereich = "5", .ezaWpUl_VorlageKz = "J", .ezaWpUl_Nummer = "", .ezaWpUl_DatumAusstellung = Nothing
})
End If
Next
imported.Add(pos)
Next
If imported.Count = 0 Then
MsgBox("Keine Warenpositionen gefunden.")
Return False
End If
' Packstücke: z.B. "4 Pallets 21 Reels 0 Cartons" -> 4 Paletten.
' Nur wenn keine expliziten positionsbezogenen Packstücke im alten Layout existieren.
Dim pkgInfo As String = TetraKopf(kopf, "Package Information")
Dim pallets As Integer = TetraPackageCount(pkgInfo, "pallets?", "paletten?")
Dim reels As Integer = TetraPackageCount(pkgInfo, "reels?", "rollen?")
Dim cartons As Integer = TetraPackageCount(pkgInfo, "cartons?", "kartons?")
Dim totalPackages As Integer = 0
Dim packageCode As String = ""
If pallets > 0 Then
totalPackages = pallets : packageCode = "PX" ' UN/ECE 21: pallet
ElseIf cartons > 0 Then
totalPackages = cartons : packageCode = "CT"
ElseIf reels > 0 Then
totalPackages = reels : packageCode = "RL"
End If
If totalPackages > 0 AndAlso imported.All(Function(p) If(p.ezaWP_PackstueckAnzahl, "").ToString().Trim() = "") Then
' Die Excel enthält nur eine Gesamtanzahl, keine positionsbezogene Zuordnung.
' Für die Erfassung proportional zum Warenwert verteilen (Rest auf letzte Position).
' Die Verteilung ist ein Vorschlag und muss vor Zollversand fachlich geprüft werden.
' Keine unbewiesene proportionale Aufteilung: alle Packstuecke auf erste Position,
' restliche Positionen ohne Anzahl; Zuordnung ist fachlich zu pruefen.
imported(0).ezaWP_PackstueckAnzahl = totalPackages.ToString(CultureInfo.InvariantCulture)
imported(0).ezaWP_PackstueckArt = packageCode
warnings.Add("Packstücke aus '" & pkgInfo & "' abgeleitet: " & totalPackages & " x " & packageCode & ". Vorlaeufig erste Position; positionsbezogene Zuordnung muss geprueft werden.")
ElseIf pkgInfo <> "" AndAlso totalPackages = 0 Then
warnings.Add("Packstückangabe konnte nicht sicher erkannt werden: " & pkgInfo)
End If
Dim replace As Boolean = False
If EZA.eza_WARENPOS.Count > 0 Then
Dim answer = MsgBox("Vorhandene " & EZA.eza_WARENPOS.Count & " Positionen ersetzen?" & vbCrLf & "Ja = ersetzen, Nein = ergänzen, Abbrechen = Import abbrechen.", MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question)
If answer = MsgBoxResult.Cancel Then Return False
replace = (answer = MsgBoxResult.Yes)
End If
' CZ = Versender laut bisheriger AVISO-Vorgabe: Verkäufer/Seller.
Dim sellerName As String = (TetraKopf(kopf, "Seller Name 1") & " " & TetraKopf(kopf, "Seller Name 2")).Trim()
If sellerName <> "" AndAlso Not EZA.eza_ADRESSEN.Any(Function(a) String.Equals(If(a.ezaAd_AdressTyp, "").ToString(), "CZ", StringComparison.OrdinalIgnoreCase)) Then
EZA.eza_ADRESSEN.Add(New DAKOSY_Worker.cDakosy_EZA_Adressen With {
.ezaAd_AdressTyp = "CZ", .ezaAd_NameFirma1 = sellerName,
.ezaAd_StrasseHausNr1 = TetraKopf(kopf, "Seller Street"), .ezaAd_Ort = TetraKopf(kopf, "Seller City"),
.ezaAd_LandCode = TetraKopf(kopf, "Seller Country").ToUpperInvariant()
})
End If
' CN: ausschliesslich Importer EORI; kein Declarant-Fallback.
Dim importerEori As String = TetraKopf(kopf, "Importer EORI Number")
If importerEori <> "" Then
Dim adrCN = EZA.eza_ADRESSEN.FirstOrDefault(Function(a) String.Equals(If(a.ezaAd_AdressTyp, "").ToString(), "CN", StringComparison.OrdinalIgnoreCase))
If adrCN Is Nothing Then
adrCN = New DAKOSY_Worker.cDakosy_EZA_Adressen With {.ezaAd_AdressTyp = "CN"}
EZA.eza_ADRESSEN.Add(adrCN)
End If
adrCN.ezaAd_TeilnehmerEORI = importerEori
TetraSetBestimmungsbundesland(importerEori)
End If
If replace Then EZA.eza_WARENPOS.Clear()
EZA.eza_WARENPOS.AddRange(imported)
If currency <> "" Then EZA.eza_Rechnungswaehrung = currency
If hasInvoiceValue Then EZA.eza_Rechnungspreis = CDbl(invoiceValue)
Dim incoterm As String = TetraKopf(kopf, "Term of Delivery")
If incoterm <> "" Then EZA.eza_LieferbedingungCode = incoterm
Dim incotermPlace As String = TetraKopf(kopf, "Term of Delivery Place")
If incotermPlace <> "" Then EZA.eza_LieferbedingungOrt = incotermPlace
Dim gross As Decimal
If TetraTryDecimal(TetraKopf(kopf, "Shipment Gross Weight (kg)"), gross) Then EZA.eza_GesamtRohmasse = CDbl(gross)
Dim dispatch As String = TetraKopf(kopf, "Country of Dispatch").Trim().ToUpperInvariant()
If dispatch = "RS" Then dispatch = "XS"
If dispatch <> "" Then
EZA.eza_VersendungsLandCode = dispatch
' ATLAS Einfuhr: EU für Vertragsparteien des gemeinsamen Versandverfahrens
Dim ctcCountries As String() = {"AT", "BE", "BG", "HR", "CY", "CZ", "DK", "EE", "FI", "FR", "DE", "GR", "HU", "IE", "IT", "LV", "LT", "LU", "MT", "NL", "PL", "PT", "RO", "SK", "SI", "ES", "SE", "XS", "CH", "NO", "IS", "LI", "TR", "MK", "GB", "UA", "GE", "MD", "ME"}
EZA.eza_ZollrechtlicherStatus = If(ctcCountries.Contains(dispatch), "EU", "IM")
End If
Dim destination As String = TetraKopf(kopf, "Country of Destination").ToUpperInvariant()
If destination <> "" Then EZA.eza_Bestimmungsland = destination
Dim modeBorder As String = TetraKopf(kopf, "Mode of Transport at the Border")
If modeBorder <> "" Then EZA.eza_VerkehrszweigGrenze = modeBorder
Dim modeInland As String = TetraKopf(kopf, "Inland Mode of Transport")
If modeInland <> "" Then EZA.eza_VerkehrszweigInland = modeInland
Dim vehicle As String = TetraKopf(kopf, "Identity of the means of transport at the border")
If vehicle <> "" Then EZA.eza_KennzeichenNameBefoerderungsmittelAnkunft = vehicle
' DV1: Fracht bis EU-Verbringungsort (010), nach EU-Verbringungsort (014).
' Annahme: Freight Costs = Gesamtfracht; Inland Freight Costs = darin enthaltener EU-Anteil.
' Kostenart 014 ist ein Abzug; die Vorzeichenlogik muss in der DAKOSY-Ausgabe geprüft werden.
Dim freight As Decimal, insurance As Decimal, inlandFreight As Decimal, otherExpenses As Decimal
Dim hasFreight As Boolean = TetraTryDecimal(TetraKopf(kopf, "Freight Costs"), freight)
Dim hasInsurance As Boolean = TetraTryDecimal(TetraKopf(kopf, "Insurance Costs"), insurance)
Dim hasInland As Boolean = TetraTryDecimal(TetraKopf(kopf, "Inland Freight Costs"), inlandFreight)
Dim hasOther As Boolean = TetraTryDecimal(TetraKopf(kopf, "Other Expenses Costs"), otherExpenses)
Dim freightCurrency As String = TetraKopf(kopf, "Currency Freight Costs").ToUpperInvariant()
Dim inlandCurrency As String = TetraKopf(kopf, "Currency Inland Freight").ToUpperInvariant()
Dim insuranceCurrency As String = TetraKopf(kopf, "Currency Insurance Costs").ToUpperInvariant()
If freightCurrency = "" Then freightCurrency = currency
If inlandCurrency = "" Then inlandCurrency = freightCurrency
If insuranceCurrency = "" Then insuranceCurrency = currency
Dim incotermCode As String = If(incoterm, "").Trim().ToUpperInvariant()
If incotermCode.Length > 3 Then incotermCode = incotermCode.Substring(0, 3)
Dim dv1Costs As New List(Of DAKOSY_Worker.cDakosy_EZA_DV1Kosten)
' Originalwährungen an DAKOSY übergeben. Umrechnung nur für eine Differenz
' zwischen Gesamtfracht und EU-Inlandsfracht mit verschiedenen Währungen.
Dim freightValid As Boolean = hasFreight AndAlso freight > 0D AndAlso freightCurrency <> ""
Dim inlandValid As Boolean = hasInland AndAlso inlandFreight > 0D AndAlso inlandCurrency <> ""
If hasFreight AndAlso freight < 0D Then warnings.Add("Negative Gesamtfracht: keine automatische DV1-Übernahme.")
If hasInland AndAlso inlandFreight < 0D Then warnings.Add("Negative Inlandsfracht: keine automatische DV1-Übernahme.")
If hasFreight AndAlso freight > 0D AndAlso freightCurrency = "" Then warnings.Add("Gesamtfracht ohne Währung: keine DV1-Übernahme.")
If hasInland AndAlso inlandFreight > 0D AndAlso inlandCurrency = "" Then warnings.Add("Inlandsfracht ohne Währung: keine DV1-Übernahme.")
Dim splitValid As Boolean = freightValid AndAlso (Not hasInland OrElse inlandFreight = 0D OrElse inlandValid)
Dim beforeEU As Decimal = If(freightValid, freight, 0D)
Dim beforeEUCurrency As String = freightCurrency
If splitValid AndAlso inlandValid Then
If freightCurrency = inlandCurrency Then
beforeEU = freight - inlandFreight
Else
Try
' Inland in die Währung der Gesamtfracht umrechnen;
' die DV1-Kostenart 010 bleibt in der ursprünglichen Frachtwährung.
Dim inlandConverted As Decimal = CDec(VERAG_PROG_ALLGEMEIN.cProgramFunctions.fktEuro(CDbl(inlandFreight), inlandCurrency, freightCurrency))
If inlandConverted <= 0D Then Throw New Exception("Ungültiges Umrechnungsergebnis")
beforeEU = freight - inlandConverted
Catch ex As Exception
splitValid = False
warnings.Add("Umrechnung der Inlandsfracht von " & inlandCurrency & " nach " & freightCurrency & " fehlgeschlagen (" & ex.Message & ").")
End Try
End If
If splitValid AndAlso beforeEU < 0D Then
splitValid = False
warnings.Add("EU-Inlandsfracht übersteigt Gesamtfracht nach Währungsabgleich; keine Differenzbildung.")
End If
End If
If hasInland AndAlso inlandFreight > 0D AndAlso Not inlandValid Then splitValid = False
If splitValid Then beforeEU = Math.Round(beforeEU, 2, MidpointRounding.AwayFromZero)
Select Case incotermCode
Case "EXW", "FCA", "FAS", "FOB"
If splitValid AndAlso beforeEU > 0D Then
If MsgBox("Lieferbedingung " & incotermCode & ": " & beforeEU.ToString("N2") & " " & beforeEUCurrency & " als Kostenart 010 hinzurechnen?" & vbCrLf & "Gesamtfracht: " & freight.ToString("N2") & " " & freightCurrency & "; EU-Inlandsfracht: " & inlandFreight.ToString("N2") & " " & inlandCurrency & "." & vbCrLf & "Bitte bestätigen, dass der Betrag nicht bereits im Rechnungspreis enthalten ist und die EU-Abgrenzung stimmt.", MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.Yes Then
dv1Costs.Add(New DAKOSY_Worker.cDakosy_EZA_DV1Kosten With {
.Kostenart = "010", .Kosten = beforeEU.ToString("0.00", CultureInfo.InvariantCulture),
.KostenWaehrung = beforeEUCurrency, .WechselkursArt = "01", .Verteilungsart = "PRICE", .Minimalbetrag = "0.01"
})
End If
End If
If inlandValid Then warnings.Add("EU-Inlandsfracht " & inlandFreight.ToString("N2") & " " & inlandCurrency & " nicht als 014 abgezogen: Einschluss im Rechnungspreis bei " & incotermCode & " nicht nachgewiesen.")
Case "CFR", "CIF", "CPT", "CIP", "DAP", "DPU", "DDP"
If inlandValid Then
If MsgBox("Lieferbedingung " & incotermCode & ": EU-Inlandsfracht " & inlandFreight.ToString("N2") & " " & inlandCurrency & " als Kostenart 014 abziehen?" & vbCrLf & "Nur bestätigen, wenn diese Kosten bereits im Rechnungspreis enthalten und gesondert nachgewiesen sind.", MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.Yes Then
dv1Costs.Add(New DAKOSY_Worker.cDakosy_EZA_DV1Kosten With {
.Kostenart = "014", .Kosten = inlandFreight.ToString("0.00", CultureInfo.InvariantCulture),
.KostenWaehrung = inlandCurrency, .WechselkursArt = "01", .Verteilungsart = "WEIGHT", .Minimalbetrag = "0.01"
})
warnings.Add("Kostenart 014: DAKOSY-Code WEIGHT und Abzugswirkung vor Versand im XML/UI prüfen.")
End If
ElseIf freightValid Then
warnings.Add("Lieferbedingung " & incotermCode & ": Gesamtfracht vorhanden, aber kein verwertbarer EU-Inlandsanteil; kein 014-Abzug.")
End If
If freightValid Then warnings.Add("Lieferbedingung " & incotermCode & ": Gesamtfracht nicht zusätzlich als 010 angesetzt (Doppelzählungsrisiko).")
Case Else
If freightValid OrElse inlandValid Then warnings.Add("Lieferbedingung '" & incotermCode & "' nicht eindeutig: Fracht nicht als 010/014 übernommen.")
End Select
If hasFreight AndAlso freight > 0D AndAlso Not hasInland Then warnings.Add("Inland Freight Costs ist leer: EU-Anteil unbekannt; Kostenaufteilung vor Zollversand prüfen.")
If hasInsurance AndAlso insurance > 0D Then
If insuranceCurrency = "" Then
warnings.Add("Versicherungskosten ohne Währung: nicht übernommen.")
ElseIf MsgBox("Versicherung " & insurance.ToString("N2") & " " & insuranceCurrency & " als Kostenart 012 hinzurechnen?" & vbCrLf & "Nur bestätigen, wenn die Versicherung nicht bereits im Rechnungspreis enthalten ist.", MsgBoxStyle.YesNo Or MsgBoxStyle.Question) = MsgBoxResult.Yes Then
dv1Costs.Add(New DAKOSY_Worker.cDakosy_EZA_DV1Kosten With {
.Kostenart = "012", .Kosten = insurance.ToString("0.00", CultureInfo.InvariantCulture),
.KostenWaehrung = insuranceCurrency, .WechselkursArt = "01", .Verteilungsart = "PRICE", .Minimalbetrag = "0.01"
})
End If
End If
If hasOther AndAlso otherExpenses <> 0D Then warnings.Add("Sonstige Kosten " & otherExpenses.ToString("N2") & " wurden nicht automatisch übernommen; Kostenart und Zollwertrelevanz prüfen.")
' Bei bestehenden DV1-Kosten nur nach expliziter Entscheidung ersetzen oder ergänzen.
If dv1Costs.Count > 0 Then
If EZA.eza_DV1Kostenverteilung Is Nothing Then EZA.eza_DV1Kostenverteilung = New List(Of DAKOSY_Worker.cDakosy_EZA_DV1Kosten)
If EZA.eza_DV1Kostenverteilung.Count > 0 Then
Dim dvAnswer = MsgBox("Vorhandene " & EZA.eza_DV1Kostenverteilung.Count & " DV1-Kosteneinträge ersetzen?" & vbCrLf & "Ja = ersetzen, Nein = ergänzen, Abbrechen = neue Kosten nicht übernehmen.", MsgBoxStyle.YesNoCancel Or MsgBoxStyle.Question)
If dvAnswer = MsgBoxResult.Cancel Then dv1Costs.Clear()
If dvAnswer = MsgBoxResult.Yes Then EZA.eza_DV1Kostenverteilung.Clear()
End If
For Each cost As DAKOSY_Worker.cDakosy_EZA_DV1Kosten In dv1Costs
If Not EZA.eza_DV1Kostenverteilung.Any(Function(k) k.Kostenart = cost.Kostenart AndAlso k.Kosten = cost.Kosten AndAlso k.KostenWaehrung = cost.KostenWaehrung) Then EZA.eza_DV1Kostenverteilung.Add(cost)
Next
End If
Debug.WriteLine("TetraPak DV1-Kosten nach Import: " & If(EZA.eza_DV1Kostenverteilung Is Nothing, 0, EZA.eza_DV1Kostenverteilung.Count))
If knownOrigins.Count > 1 Then warnings.Add("Mehrere Ursprungslaender vorhanden: leere Positionen nicht automatisch ergaenzt.")
If invoiceNo <> "" Then warnings.Add("Rechnung " & invoiceNo & ": Rechnungsdatum ist im Excel nicht enthalten; Unterlage ohne Datum übernommen.")
If Not OP_addKN8 Then warnings.Add("KN8-Langtext wurde nicht ergänzt (Option deaktiviert).")
Dim msg As String = imported.Count & " Tetra-Pak-Positionen eingelesen."
If warnings.Count > 0 Then msg &= vbCrLf & vbCrLf & "Prüfhinweise:" & vbCrLf & "- " & String.Join(vbCrLf & "- ", warnings)
MsgBox(msg, MsgBoxStyle.Information, "Tetra Pak Excel-Import")
Me.DialogResult = DialogResult.OK
Me.Close()
Return True
Catch ex As Exception
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR("Tetra Pak Excel-Import: " & ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod.Name)
Return False
Finally
Try
If wb IsNot Nothing Then wb.Close(False)
Catch
End Try
Try
If xlApp IsNot Nothing Then xlApp.Quit()
Catch
End Try
For Each obj As Object In New Object() {used, ws, wb, xlApp}
Try
If obj IsNot Nothing Then System.Runtime.InteropServices.Marshal.FinalReleaseComObject(obj)
Catch
End Try
Next
End Try
End Function
Private Function TetraCell(value As Object) As String
If value Is Nothing Then Return ""
Return Convert.ToString(value, CultureInfo.InvariantCulture).Trim()
End Function
Private Function TetraGet(values As Object(,), header As Dictionary(Of String, Integer), row As Integer, ParamArray names As String()) As String
For Each name As String In names
Dim col As Integer
If header.TryGetValue(name, col) Then
Dim v As String = TetraCell(values(row, col))
If v <> "" Then Return v
End If
Next
Return ""
End Function
Private Function TetraKopf(kopf As Dictionary(Of String, String), name As String) As String
Dim value As String = Nothing
If kopf.TryGetValue(name, value) Then Return If(value, "")
Return ""
End Function
Private Function TetraTryDecimal(value As String, ByRef number As Decimal) As Boolean
number = 0D
If String.IsNullOrWhiteSpace(value) Then Return False
Dim culture As CultureInfo = If(value.Contains(",") AndAlso Not value.Contains("."), CultureInfo.GetCultureInfo("de-DE"), CultureInfo.InvariantCulture)
If Decimal.TryParse(value, NumberStyles.Number, culture, number) Then Return True
Return Decimal.TryParse(value, NumberStyles.Number, If(culture.Name = "de-DE", CultureInfo.InvariantCulture, CultureInfo.GetCultureInfo("de-DE")), number)
End Function
Private Function TetraPackageCount(value As String, ParamArray patterns As String()) As Integer
For Each p As String In patterns
Dim m = System.Text.RegularExpressions.Regex.Match(value, "(?i)(\d+)\s*" & p & "\b")
If m.Success Then
Dim n As Integer
If Integer.TryParse(m.Groups(1).Value, n) Then Return n
End If
Next
Return 0
End Function
Private Sub TetraSetBestimmungsbundesland(importerEORI As String)
If String.IsNullOrWhiteSpace(importerEORI) Then Exit Sub
Dim SQL As New VERAG_PROG_ALLGEMEIN.SQL
Try
Using conn As SqlConnection = SQL.GetNewOpenConnectionFMZOLL()
Dim sqlText As String = "SELECT TOP 1 A.[LandKz], A.[PLZ] FROM [VERAG].[dbo].[Kunden] K INNER JOIN [VERAG].[dbo].[Adressen] A ON A.[AdressenNr] = K.[KundenNr] WHERE LTRIM(RTRIM(K.[EORITIN])) = @EORI"
Using cmd As New SqlCommand(sqlText, conn)
cmd.Parameters.Add("@EORI", SqlDbType.VarChar, 50).Value = importerEORI.Trim()
Using dr As SqlDataReader = cmd.ExecuteReader()
If dr.Read() Then
Dim land As String = If(dr.IsDBNull(0), "", dr.GetValue(0).ToString().Trim().ToUpperInvariant())
Dim plz As String = If(dr.IsDBNull(1), "", dr.GetValue(1).ToString().Trim())
If (land = "DE" OrElse land = "D") AndAlso plz <> "" Then
EZA.eza_Bestimmungsbundesland = VERAG_PROG_ALLGEMEIN.cDEBundeslaenderPLZ.LOADBundeslandCode_ByPLZ(plz)
ElseIf land <> "" AndAlso land <> "DE" AndAlso land <> "D" Then
EZA.eza_Bestimmungsbundesland = 25
End If
End If
End Using
End Using
End Using
Catch ex As Exception
VERAG_PROG_ALLGEMEIN.cErrorHandler.ERR(ex.Message, ex.StackTrace, System.Reflection.MethodInfo.GetCurrentMethod().Name)
End Try
End Sub
Private Sub cbxGezeTranslate_CheckedChanged(sender As Object, e As EventArgs) Handles cbxGezeTranslate.CheckedChanged
End Sub
'================================================================================================================================
'================================================================================================================================
'================================================================================================================================
End Class