procedures
This commit is contained in:
301
UID/cTRCustStat.vb
Normal file
301
UID/cTRCustStat.vb
Normal 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
|
||||
Reference in New Issue
Block a user