procedures

This commit is contained in:
2025-11-26 09:03:21 +01:00
parent 7918b0d0b8
commit 99bb7d39de
6 changed files with 489 additions and 26 deletions

301
UID/cTRCustStat.vb Normal file
View File

@@ -0,0 +1,301 @@

Imports System.Data
Imports System.Data.SqlClient
Imports System.Globalization
Imports ClosedXML.Excel
Public Class cTRCustStat
Private ReadOnly _connectionString As String
Private ReadOnly _de As CultureInfo = CultureInfo.GetCultureInfo("de-DE")
Public Sub New(connectionString As String)
_connectionString = connectionString
End Sub
' Mehrere Dateien importieren
Public Sub ImportFiles(filePaths As IEnumerable(Of String))
For Each p In filePaths
ImportSingleFile(p)
Next
End Sub
Private Sub ImportSingleFile(filePath As String)
Using wb As New XLWorkbook(filePath)
Dim ws = wb.Worksheets.First()
' Header (Zeile 1) normalisieren
Dim lastCol = ws.Row(1).LastCellUsed().Address.ColumnNumber
Dim headers As New List(Of String)
For c = 1 To lastCol
headers.Add(NormalizeHeader(ws.Cell(1, c).GetString()))
Next
Dim layout = DetectLayout(headers)
Select Case layout
Case LayoutType.Exports
Dim dt = CreateExportsDataTable() ' Spaltennamen = SQL-Spalten EN
FillDataTable(ws, headers, dt, isExport:=True, sourceFile:=filePath)
BulkInsert(dt, "dbo.Customs_Exports")
Case LayoutType.Imports
Dim dt = CreateImportsDataTable()
FillDataTable(ws, headers, dt, isExport:=False, sourceFile:=filePath)
BulkInsert(dt, "dbo.Customs_Imports")
Case Else
Throw New InvalidOperationException($"Unknown layout in file: {filePath}")
End Select
End Using
End Sub
Private Enum LayoutType
Unknown = 0
Exports = 1
[Imports] = 2
End Enum
Private Function DetectLayout(headers As List(Of String)) As LayoutType
' Export: hat "tcgb statü açıklaması" ODER "gümrük istatistik tarihi"
If headers.Any(Function(h) h.Contains("tcgb statu aciklamasi") OrElse h.Contains("gumruk istatistik tarihi")) Then
Return LayoutType.Exports
End If
' Import: hat "gümrük idaresi kodu" und "tcgb kapanış tarihi"
If headers.Any(Function(h) h.Contains("gumruk idaresi kodu")) AndAlso
headers.Any(Function(h) h.Contains("tcgb kapanis tarihi")) Then
Return LayoutType.Imports
End If
Return LayoutType.Unknown
End Function
Private Function NormalizeHeader(raw As String) As String
If raw Is Nothing Then Return ""
Dim s = raw.Trim().ToLowerInvariant()
s = s.Replace("ı", "i").Replace("ş", "s").Replace("ğ", "g").Replace("ü", "u").Replace("ö", "o").Replace("ç", "c")
s = System.Text.RegularExpressions.Regex.Replace(s, "\s+", " ")
Return s
End Function
' --- DataTables: Spaltennamen = EN-Tabellenschema ---
Private Function CreateExportsDataTable() As DataTable
Dim dt As New DataTable("Customs_Exports")
dt.Columns.Add("CustomsOfficeName", GetType(String))
dt.Columns.Add("RegistrationNo", GetType(String))
dt.Columns.Add("RegistrationDate", GetType(Date))
dt.Columns.Add("StatisticsDate", GetType(Date))
dt.Columns.Add("ConsignorConsigneeTaxNo", GetType(String))
dt.Columns.Add("ConsignorConsigneeName", GetType(String))
dt.Columns.Add("ConsigneeName", GetType(String))
dt.Columns.Add("DestinationCountryCode", GetType(String))
dt.Columns.Add("DestinationCountryName", GetType(String))
dt.Columns.Add("OriginCountryCode", GetType(String))
dt.Columns.Add("OriginCountryName", GetType(String))
dt.Columns.Add("IncotermCode", GetType(String))
dt.Columns.Add("LineNo", GetType(Integer))
dt.Columns.Add("RegimeCode", GetType(String))
dt.Columns.Add("RegimeDescription", GetType(String))
dt.Columns.Add("HSCode", GetType(String))
dt.Columns.Add("HSDescription", GetType(String))
dt.Columns.Add("CommercialDescription", GetType(String))
dt.Columns.Add("DeclarationStatus", GetType(String))
dt.Columns.Add("InvoiceAmount", GetType(Decimal))
dt.Columns.Add("InvoiceCurrencyCode", GetType(String))
dt.Columns.Add("Quantity", GetType(Decimal))
dt.Columns.Add("QuantityUnit", GetType(String))
dt.Columns.Add("NetWeightKg", GetType(Decimal))
dt.Columns.Add("CalculatedLineValueUSD", GetType(Decimal))
dt.Columns.Add("StatisticalValueUSD", GetType(Decimal))
dt.Columns.Add("SourceFile", GetType(String))
dt.Columns.Add("ImportedAtUtc", GetType(DateTime))
Return dt
End Function
Private Function CreateImportsDataTable() As DataTable
Dim dt As New DataTable("Customs_Imports")
dt.Columns.Add("CustomsOfficeCode", GetType(String))
dt.Columns.Add("CustomsOfficeName", GetType(String))
dt.Columns.Add("RegistrationNo", GetType(String))
dt.Columns.Add("RegistrationDate", GetType(Date))
dt.Columns.Add("ClosingDate", GetType(Date))
dt.Columns.Add("ConsignorConsigneeTaxNo", GetType(String))
dt.Columns.Add("ConsignorConsigneeName", GetType(String))
dt.Columns.Add("SenderName", GetType(String))
dt.Columns.Add("DispatchCountryCode", GetType(String))
dt.Columns.Add("DispatchCountryName", GetType(String))
dt.Columns.Add("OriginCountryCode", GetType(String))
dt.Columns.Add("OriginCountryName", GetType(String))
dt.Columns.Add("IncotermCode", GetType(String))
dt.Columns.Add("LineNo", GetType(Integer))
dt.Columns.Add("RegimeCode", GetType(String))
dt.Columns.Add("RegimeDescription", GetType(String))
dt.Columns.Add("HSCode", GetType(String))
dt.Columns.Add("HSDescription", GetType(String))
dt.Columns.Add("CommercialDescription", GetType(String))
dt.Columns.Add("InvoiceAmount", GetType(Decimal))
dt.Columns.Add("InvoiceCurrencyCode", GetType(String))
dt.Columns.Add("Quantity", GetType(Decimal))
dt.Columns.Add("QuantityUnit", GetType(String))
dt.Columns.Add("NetWeightKg", GetType(Decimal))
dt.Columns.Add("CalculatedLineValueUSD", GetType(Decimal))
dt.Columns.Add("StatisticalValueUSD", GetType(Decimal))
dt.Columns.Add("SourceFile", GetType(String))
dt.Columns.Add("ImportedAtUtc", GetType(DateTime))
Return dt
End Function
' --- Excel -> DataTable ---
Private Sub FillDataTable(ws As IXLWorksheet,
headers As List(Of String),
dt As DataTable,
isExport As Boolean,
sourceFile As String)
Dim rowFirst = 2
Dim rowLast = ws.LastRowUsed().RowNumber()
Dim colLast = ws.Row(1).LastCellUsed().Address.ColumnNumber
Dim map As Dictionary(Of String, String) =
If(isExport, GetExportHeaderMap(), GetImportHeaderMap())
For r = rowFirst To rowLast
Dim dr = dt.NewRow()
dr("SourceFile") = sourceFile
dr("ImportedAtUtc") = DateTime.UtcNow
For c = 1 To colLast
Dim rawHeader = NormalizeHeader(ws.Cell(1, c).GetString())
If Not map.ContainsKey(rawHeader) Then Continue For
Dim targetCol = map(rawHeader)
Dim txt = ws.Cell(r, c).GetFormattedString().Trim()
If String.IsNullOrWhiteSpace(txt) Then
' skip
ElseIf dt.Columns(targetCol).DataType Is GetType(Date) Then
dr(targetCol) = ParseDate(txt)
ElseIf dt.Columns(targetCol).DataType Is GetType(Decimal) Then
dr(targetCol) = ParseDecimal(txt)
ElseIf dt.Columns(targetCol).DataType Is GetType(Integer) Then
Dim i As Integer
If Integer.TryParse(txt, NumberStyles.Any, _de, i) OrElse
Integer.TryParse(txt, NumberStyles.Any, CultureInfo.InvariantCulture, i) Then
dr(targetCol) = i
End If
Else
dr(targetCol) = txt
End If
Next
' Mindestprüfung: RegistrationNo muss da sein
If dt.Columns.Contains("RegistrationNo") AndAlso
Not IsDBNull(dr("RegistrationNo")) AndAlso
Not String.IsNullOrWhiteSpace(CStr(dr("RegistrationNo"))) Then
dt.Rows.Add(dr)
End If
Next
End Sub
Private Function ParseDecimal(s As String) As Decimal
Dim d As Decimal
If Decimal.TryParse(s, NumberStyles.Any, _de, d) Then Return d ' 3.499,09
If Decimal.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, d) Then Return d ' 3499.09
Return 0D
End Function
Private Function ParseDate(s As String) As Date
Dim d As Date
Dim formats = {
"dd.MMM.yyyy", "d.MMM.yyyy",
"dd.MM.yyyy", "d.MM.yyyy",
"dd.MMM.yy", "dd.MM.yy",
"yyyy-MM-dd", "dd-MMM-yyyy"
}
If Date.TryParseExact(s, formats, _de, DateTimeStyles.None, d) Then Return d
If Date.TryParse(s, _de, DateTimeStyles.None, d) Then Return d
If Date.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.None, d) Then Return d
Return Date.MinValue
End Function
Private Sub BulkInsert(dt As DataTable, targetTable As String)
Using cn As New SqlConnection(_connectionString)
cn.Open()
Using bulk As New SqlBulkCopy(cn)
bulk.DestinationTableName = targetTable
bulk.BulkCopyTimeout = 0
bulk.BatchSize = 10000
For Each col As DataColumn In dt.Columns
bulk.ColumnMappings.Add(col.ColumnName, col.ColumnName)
Next
bulk.WriteToServer(dt)
End Using
End Using
End Sub
' --- Header-Mappings: Türkischer Exceltitel -> EN-Spalte ---
Private Function GetExportHeaderMap() As Dictionary(Of String, String)
Return New Dictionary(Of String, String) From {
{"tcgb", "CustomsOfficeName"},
{"gümrük idaresi adı", "CustomsOfficeName"}, ' manche Dateien haben beide
{"tcgb tescil no", "RegistrationNo"},
{"tcgb tescil tarihi", "RegistrationDate"},
{"gümrük istatistik tarihi (bordro tarihi)", "StatisticsDate"},
{"gonderici / alici vergi no", "ConsignorConsigneeTaxNo"},
{"gonderici/alici adi", "ConsignorConsigneeName"},
{"alici adi", "ConsigneeName"},
{"gidecegi ulke (17) kodu", "DestinationCountryCode"},
{"gidecegi ulke (17) adi", "DestinationCountryName"},
{"mense ulke kodu", "OriginCountryCode"},
{"mense ulke adi", "OriginCountryName"},
{"teslim sekli kodu", "IncotermCode"},
{"kalem sira no", "LineNo"},
{"kalem rejim kodu", "RegimeCode"},
{"kalem rejim aciklamasi", "RegimeDescription"},
{"gtip kodu", "HSCode"},
{"gtip aciklamasi", "HSDescription"},
{"31. ticari tanimi", "CommercialDescription"},
{"tcgb statu aciklamasi", "DeclarationStatus"},
{"fatura tutari", "InvoiceAmount"},
{"fatura tutari doviz turu kodu", "InvoiceCurrencyCode"},
{"olcu (esya) miktari", "Quantity"},
{"olcu birimi aciklamasi", "QuantityUnit"},
{"net agirlik (kg)", "NetWeightKg"},
{"hesaplanmis kalem kiymeti usd degeri", "CalculatedLineValueUSD"},
{"istatistiki kiymet usd degeri", "StatisticalValueUSD"}
}
End Function
Private Function GetImportHeaderMap() As Dictionary(Of String, String)
Return New Dictionary(Of String, String) From {
{"gümrük idaresi kodu", "CustomsOfficeCode"},
{"gumruk idaresi kodu", "CustomsOfficeCode"},
{"gümrük idaresi adı", "CustomsOfficeName"},
{"gumruk idaresi adi", "CustomsOfficeName"},
{"tcgb tescil no", "RegistrationNo"},
{"tcgb tescil tarihi", "RegistrationDate"},
{"tcgb kapanis tarihi", "ClosingDate"},
{"gonderici / alici vergi no", "ConsignorConsigneeTaxNo"},
{"gonderici/alici adi", "ConsignorConsigneeName"},
{"gonderen adi", "SenderName"},
{"cikis ulkesi kodu", "DispatchCountryCode"},
{"cikis ulkesi adi", "DispatchCountryName"},
{"mense ulke kodu", "OriginCountryCode"},
{"mense ulke adi", "OriginCountryName"},
{"teslim sekli kodu", "IncotermCode"},
{"kalem sira no", "LineNo"},
{"kalem rejim kodu", "RegimeCode"},
{"kalem rejim aciklamasi", "RegimeDescription"},
{"gtip kodu", "HSCode"},
{"gtip aciklamasi", "HSDescription"},
{"31. ticari tanimi", "CommercialDescription"},
{"fatura tutari", "InvoiceAmount"},
{"fatura doviz kodu", "InvoiceCurrencyCode"},
{"olcu (esya) miktari", "Quantity"},
{"olcu birimi aciklamasi", "QuantityUnit"},
{"net agirlik (kg)", "NetWeightKg"},
{"hesaplanmis kalem kiymeti usd degeri", "CalculatedLineValueUSD"},
{"istatistiki kiymet usd degeri", "StatisticalValueUSD"}
}
End Function
End Class