rohdaten(excel)-Verarbeitung in vb.net

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von tragl.

    rohdaten(excel)-Verarbeitung in vb.net

    Moin zusammen.

    Ich muss in meinem Projekt Rohdaten (Excel) aus unserem WaWi-System verwursten, um Monatswerte zu bekommen
    allerdings ist vb.net ja kein Excel und ich will ungern die Interop-Funktion nutzen müssen, da ich denke dass vb.net das auch so kann ;)
    Ich versuch's mal ordentlich zu erklären:

    Die Rohdaten sind pro Monat eine Datei und sehen in etwa so aus:


    Folgende relevante Spalten gibts in den Rohdaten:
    Datum
    Kundennummer
    TourNr
    Picks
    Positionen

    Es gibt 3 Tourarten: (jede Tourart kann mehrere TourNr haben)
    Versand
    Abholer
    Tour
    Alle Werte können mehrfach vorkommen.

    Was ich derzeit mit Excel-VBA mache:

    Tabelle Nach Datum sortieren

    Pro Datum:
    alle Rows markieren, die zum Datum gehören und in ein neues Tabellenblatt kopieren

    im neuen Tabellenblatt:
    alle einträge nach Tour Sortieren. Alles was Versandtournummer ist -> Picks, Position, zeilen und eindeutige Kundennummern zählen
    Alles was Abholer ist -> Positionen zählen
    abschließend noch für den Tag zählen: gesamtzeilen, gesamt Picks, gesamt Position, gesamt eindeutige Kundennummern.

    So erhalte ich pro Tag:
    Position belieferte Kunden (gesamt-Positionen - abholer-Positionen - Versand-Positionen)
    gesamtkunden
    gesamtaufträge (zeilen)
    gesamtpositionen
    gesamtpicks
    versandkunden
    versandaufträge (zeilen)
    versandpositionen
    versandpicks

    Danach dann mit dem nächsten Datum weitermachen.
    Sieht dann fertig so aus:


    Jetzt muss ich das Ganze irgendwie in vb.net nachbauen können.
    Die Excel-Tabelle importiere ich mir in eine neue DataTable und schmeiße schonmal alle Zeilen raus, die ich nicht benötige
    Monat und Jahr wird auf der Form ausgewählt, damit kann ich schonmal eine Schleife bauen (Do While datumMonatsanfang < datumMonatsende)

    Was mir dazu fehlt:
    - kann ich DataRows aus der QuellDataTable in eine neue (temporäre) DataTable kopieren? (z.B. alle Einträge die Datum = aktuelles Datum Schleife haben)
    - gibt's eine Möglichkeit die Anzahl eindeutiger Werte (z.B. Kundennummer) aus einer Spalte auszulesen? (Ein Kunde kann mehrere Aufträge haben)

    Codeansatz bis jetzt:
    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub importLager()
    2. msgInformation("Bitte im Folgenden die Lagerdatei auswählen.")
    3. Dim importFile = openFile("Excel-Dateien (*.xlsx)|*.xlsx")
    4. If Not importFile = "" Then
    5. Using excelCon = New OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source='" & importFile & "'; " & "Extended Properties='Excel 12.0;HDR=YES;IMEX=1;'")
    6. excelCon.Open()
    7. Using da = New OleDbDataAdapter("Select [Datum],[Li#-Kunde#Nummer],[Tour#Nr],[Picks],[Positions-Anzahl],[Ersteller#Info],[Umsatzart] From [Tabelle1$]", excelCon)
    8. Dim tblSrc As New DataTable("kennzahlenSource")
    9. da.Fill(tblSrc)
    10. Dim lstUmsatzarten = New List(Of String)
    11. Dim lstTourenOhneRelevanz = New List(Of String)
    12. Dim lstTourenVersand = New List(Of String)
    13. Dim lstTourenAbholer = New List(Of String)
    14. 'Optionen auslesen und in Listen packen
    15. For Each rwOpt In Dts.KennzahlenOpt
    16. If rwOpt.Standort = _standort Then
    17. For Each uArt In rwOpt.Umsatzarten.Split(","c)
    18. lstUmsatzarten.Add(uArt)
    19. Next
    20. For Each tNr In rwOpt.TourenOhneRelevanz.Split(","c)
    21. lstTourenOhneRelevanz.Add(tNr)
    22. Next
    23. For Each tNr In rwOpt.TourenVersand.Split(","c)
    24. lstTourenVersand.Add(tNr)
    25. Next
    26. For Each tNr In rwOpt.TourenAbholer.Split(","c)
    27. lstTourenAbholer.Add(tNr)
    28. Next
    29. End If
    30. Next
    31. 'Vorab unnötige Zeilen löschen
    32. For Each rwSrc As DataRow In tblSrc.Rows
    33. Dim ersteller = $"{rwSrc.Item("Ersteller#Info")}"
    34. Dim umsatzart = $"{rwSrc.Item("Umsatzart")}"
    35. Dim tournr = $"{rwSrc.Item("Tour#Nr")}"
    36. If Not ersteller Like "*Logistik*" Then
    37. rwSrc.Delete() 'alle Ersteller <> Logistik löschen
    38. End If
    39. For Each uArt In lstUmsatzarten
    40. If umsatzart = uArt Then rwSrc.Delete() 'irrelevante Umsatzarten löschen
    41. Next
    42. For Each tourOhneRelevanz In lstTourenOhneRelevanz
    43. If tournr = tourOhneRelevanz Then rwSrc.Delete() 'Touren ohne Relevanz löschen
    44. Next
    45. Next
    46. dgvSrc.DataSource = tblSrc 'bereinigte Daten in DGV anzeigen (nur für Testzwecke)
    47. 'Ab hier Verarbeitung der restlichen Daten
    48. Dim startDate = Date.Parse($"01.{_monatnummer}.{_setYear}")
    49. Dim endDate = MonatsEnde(_monatnummer.ToString, _setYear)
    50. Dim loopDate = startDate.Date
    51. Do While loopDate < endDate.Date.AddDays(1)
    52. Dim fahrerPos = 0 'Positionen belieferte Kunden
    53. Dim lagerKd = 0 'Kunden Lager
    54. Dim lagerAu = 0 'Aufträge Lager
    55. Dim lagerPos = 0 'Positionen Lager
    56. Dim lagerPicks = 0 'Picks Lager
    57. Dim paketKd = 0 'davon Kunden Paket
    58. Dim paketAu = 0 'davon Aufträge Paket
    59. Dim paketPos = 0 'davon Positionen Paket
    60. Dim paketPicks = 0 'davon Picks Paket
    61. Dim abholerPos = 0 'Positionen Abholer-Touren (für Berechnung Fahrer-Positionen nötig)
    62. For Each rw As DataRow In tblSrc.Rows
    63. If Not rw.RowState = DataRowState.Deleted Then
    64. 'alles was zu loopDate gehört in neue DT kopieren
    65. 'in neuer DT dann Werte auslesen
    66. End If
    67. Next
    68. 'wenn alle Werte für das Datum abgegriffen wurden, diese in das typDTS kopieren
    69. Dts.Kennzahlen.AddKennzahlenRow(loopDate, _standort, fahrerPos, lagerKd, lagerAu, lagerPos, lagerPicks,
    70. paketKd, paketAu, paketPos, paketPicks, 0, 0, 0, 0)
    71. Loop
    72. End Using
    73. End Using
    74. Else
    75. Return
    76. End If
    77. End Sub


    Hier noch (falls interessant) der mit Sicherheit schlechteste Excel-VBA-Code, den die Welt gesehen hat (hab ich vor ein paar Jahren geschrieben)(aber klappt) :D
    Spoiler anzeigen

    Quellcode

    1. Option Explicit
    2. 'Fenster on Top
    3. Public Const SWP_NOSIZE = &H1
    4. Public Const SWP_NOMOVE = &H2
    5. Public Const SWP_NOACTIVATE = &H10
    6. Public Const SWP_SHOWWINDOW = &H40
    7. Public Const HWND_TOPMOST = -1
    8. #If Win64 Then
    9. Public Declare PtrSafe Function SetWindowPos Lib "user32" ( _
    10. ByVal hwnd As LongPtr, ByVal hWndInsertAfter As LongPtr, _
    11. ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, _
    12. ByVal wFlags As Long) As Long
    13. Public Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    14. ByVal lpClassName As String, ByVal lpWindowName As String) As LongPtr
    15. #Else
    16. Public Declare Function SetWindowPos Lib "user32" ( _
    17. ByVal hwnd As Long, ByVal hWndInsertAfter As Long, _
    18. ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, _
    19. ByVal wFlags As Long) As Long
    20. Public Declare Function FindWindow Lib "user32" Alias "FindWindowA" ( _
    21. ByVal lpClassName As String, ByVal lpWindowName As String) As Long
    22. #End If
    23. '
    24. Public shname As String
    25. Public wsNew As Worksheet
    26. Public mainwb As String, mainwbfull As String
    27. Public sourcewb_lager As String, sourcewbfull_lager As String
    28. Public sourcewb_sangro As String, sourcewbfull_sangro As String
    29. Public source_lager As String, source_sangro As String
    30. Public lager_active As Integer, sangro_active As Integer
    31. Public rmax As Long, cmax As Long, rmax_versand As Long, rmax_abholer As Long, rmax_touren As Long, rmax_mitarbeiter As Long, rmax_tag As Long, rmax_tag_summe As Long, rmax_datum As Long, row As Long, rmax_filter As Long, rmax_filtercopy As Long, rmax_umsatzart As Long
    32. Public i As Integer
    33. Public arr_monate As Variant
    34. Public ups As String
    35. Public formname As Object
    36. Public auswahl As String
    37. Public modulname As String
    38. Public jahr As String
    39. Public picks As Long, positionen As Long, auftrag As Long, kunden As Long, positionen_abholer As Long, positionen_versand As Long
    40. Public suchen As String, suchen_anzahl As Long
    41. Public rngRow As Range
    42. Public crit As String
    43. Public wks As Worksheet
    44. Sub daten()
    45. arr_monate = Array("Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember")
    46. jahr = Year(Now)
    47. End Sub
    48. Sub run_lager()
    49. On Error GoTo errhandler
    50. ups = ""
    51. Application.ScreenUpdating = False
    52. 'daten laden
    53. daten
    54. 'allgemeines
    55. wb_main
    56. 'prüfen, ob Vorlage noch vorhanden ist
    57. shname = "Vorlage"
    58. If Not sheet_exists(shname) Then
    59. MsgBox ("Das Tabellenblatt Vorlage ist nicht mehr vorhanden! Bitte an d.hornickel wenden"), vbCritical
    60. Exit Sub
    61. Else
    62. 'Monat auswählen
    63. frm_auswahl.ListBox1.List = arr_monate
    64. frm_auswahl.Show
    65. If Not auswahl = "" Then
    66. Application.ScreenUpdating = False
    67. 'Vorlage kopieren und Monat eintragen
    68. If sheet_exists(auswahl) Then
    69. Application.DisplayAlerts = False
    70. Sheets(auswahl).Delete
    71. Application.DisplayAlerts = True
    72. End If
    73. Sheets("Vorlage").Visible = True
    74. Sheets("Vorlage").Copy after:=Sheets(Sheets.Count)
    75. ActiveSheet.Name = auswahl
    76. Sheets("Vorlage").Visible = False
    77. Sheets(auswahl).Activate
    78. Select Case auswahl
    79. Case "Januar"
    80. Range("A3").Value = "01.01." & jahr
    81. Case "Februar"
    82. Range("A3").Value = "01.02." & jahr
    83. Case "März"
    84. Range("A3").Value = "01.03." & jahr
    85. Case "April"
    86. Range("A3").Value = "01.04." & jahr
    87. Case "Mai"
    88. Range("A3").Value = "01.05." & jahr
    89. Case "Juni"
    90. Range("A3").Value = "01.06." & jahr
    91. Case "Juli"
    92. Range("A3").Value = "01.07." & jahr
    93. Case "August"
    94. Range("A3").Value = "01.08." & jahr
    95. Case "September"
    96. Range("A3").Value = "01.09." & jahr
    97. Case "Oktober"
    98. Range("A3").Value = "01.10." & jahr
    99. Case "November"
    100. Range("A3").Value = "01.11." & jahr
    101. Case "Dezember"
    102. Range("A3").Value = "01.12." & jahr
    103. End Select
    104. 'Quelldaten laden
    105. quelldaten_lager_laden
    106. If Not source_lager = "Falsch" Then
    107. frm_progress.Show vbModeless
    108. 'Daten verarbeiten
    109. Sheets("source_lager").Activate
    110. cmax = Sheets("source_lager").UsedRange.Columns.Count
    111. rmax = Sheets("source_lager").UsedRange.Rows.Count
    112. 'Format Picks
    113. Columns("I:I").Select
    114. Selection.NumberFormat = "0"
    115. 'Summenzeile löschen
    116. If Range("D" & rmax).Value = "Summe" Then
    117. Rows(rmax).Delete
    118. End If
    119. 'umsatzart löschen
    120. rmax = Sheets("source_lager").UsedRange.Rows.Count
    121. rmax_umsatzart = Sheets("Start").Cells(Rows.Count, 1).End(xlUp).row
    122. frm_progress.bar_type.Max = rmax
    123. frm_progress.lbl_type.Caption = "Umsatzart löschen"
    124. For i = 2 To rmax
    125. fn_progress_u (i)
    126. If Not Sheets("Start").Range("A2:A" & rmax_umsatzart).Find(Sheets("source_lager").Range("AK" & i).Value) Is Nothing Then
    127. Rows(i).Delete
    128. i = i - 1
    129. If Range("AK" & i + 1).Value = "" Then
    130. Exit For
    131. End If
    132. End If
    133. Next
    134. i = 0
    135. rmax = Sheets("source_lager").UsedRange.Rows.Count
    136. 'nicht-Logistik Mitarbeiter löschen
    137. frm_progress.bar_type.Max = rmax
    138. frm_progress.lbl_type.Caption = "nicht-Logistik Mitarbeiter löschen"
    139. Dim suchbegriff As String
    140. suchbegriff = "*logistik*"
    141. For i = 2 To rmax
    142. Rows(i).Select
    143. fn_progress_u (i)
    144. If Not LCase(Cells(i, 15).Value) Like suchbegriff Then
    145. Rows(i).Delete
    146. i = i - 1
    147. If Range("A" & i + 1).Value = "" Then
    148. Exit For
    149. End If
    150. End If
    151. Next
    152. i = 0
    153. 'unnötige Touren rauslöschen
    154. rmax = Sheets("source_lager").UsedRange.Rows.Count
    155. rmax_touren = Sheets("Start").Cells(Rows.Count, 2).End(xlUp).row
    156. frm_progress.bar_type.Max = rmax
    157. frm_progress.lbl_type.Caption = "nicht relevante Touren löschen"
    158. For i = 2 To rmax
    159. fn_progress_u (i)
    160. 'Rows(i).Select
    161. If Not Sheets("Start").Range("B2:B" & rmax_touren).Find(Sheets("source_lager").Range("G" & i).Value) Is Nothing Then
    162. Rows(i).Delete
    163. i = i - 1
    164. If Range("A" & i + 1).Value = "" Then
    165. Exit For
    166. End If
    167. End If
    168. Next
    169. i = 0
    170. rmax = Sheets("source_lager").UsedRange.Rows.Count
    171. 'nach datum sortieren
    172. Columns(1).Resize(, cmax).EntireColumn.Select
    173. ActiveWorkbook.Worksheets("source_lager").Sort.SortFields.Clear
    174. ActiveWorkbook.Worksheets("source_lager").Sort.SortFields.Add Key:=Range("B2:B" & rmax), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    175. With ActiveWorkbook.Worksheets("source_lager").Sort
    176. .SetRange Range(ActiveWorkbook.Worksheets("source_lager").Cells(1, 1), ActiveWorkbook.Worksheets("source_lager").Cells(rmax, cmax))
    177. .Header = xlYes
    178. .MatchCase = False
    179. .Orientation = xlTopToBottom
    180. .SortMethod = xlPinYin
    181. .Apply
    182. End With
    183. 'Tag kopieren
    184. Dim day As Integer
    185. Dim dayend As Long
    186. Dim datum As String
    187. frm_progress.lbl_type = ""
    188. For day = 1 To 31
    189. kunden = 0
    190. positionen_abholer = 0
    191. positionen_versand = 0
    192. auftrag = 0
    193. positionen = 0
    194. picks = 0
    195. frm_progress.lbl_type_o.Caption = datum
    196. frm_progress.bar_gesamt.Max = 31
    197. fn_progress_o (day)
    198. datum = Range("B2").Value
    199. If Not datum = "" Then
    200. 'Tag sammeln
    201. For i = 2 To rmax
    202. If Not Cells(i, 2).Value = datum Then
    203. dayend = i - 1
    204. Exit For
    205. End If
    206. Next
    207. i = 0
    208. shname = datum
    209. If sheet_exists(shname) Then
    210. Application.DisplayAlerts = False
    211. Sheets(shname).Delete
    212. Application.DisplayAlerts = True
    213. End If
    214. Set wsNew = Worksheets.Add
    215. With wsNew
    216. .Name = shname
    217. .Move after:=Sheets(Sheets.Count)
    218. End With
    219. Set wsNew = Nothing
    220. Sheets("source_lager").Activate
    221. Range(Cells(1, 1), Cells(dayend, cmax)).Select
    222. Selection.Copy
    223. Sheets(datum).Activate
    224. Range("A1").Select
    225. Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:= _
    226. xlNone, SkipBlanks:=False, Transpose:=False
    227. 'tag aus quelle löschen
    228. Sheets("source_lager").Activate
    229. Rows("2:" & dayend).Delete
    230. 'nach Tour sortieren
    231. Sheets(datum).Activate
    232. rmax_tag = Sheets(datum).UsedRange.Rows.Count
    233. Columns(1).Resize(, cmax).EntireColumn.Select
    234. ActiveWorkbook.Worksheets(datum).Sort.SortFields.Clear
    235. ActiveWorkbook.Worksheets(datum).Sort.SortFields.Add Key:=Range("G2:G" & rmax_tag), SortOn:=xlSortOnValues, Order:=xlAscending, DataOption:=xlSortNormal
    236. With ActiveWorkbook.Worksheets(datum).Sort
    237. .SetRange Range(ActiveWorkbook.Worksheets(datum).Cells(1, 1), ActiveWorkbook.Worksheets(datum).Cells(rmax_tag, cmax))
    238. .Header = xlYes
    239. .MatchCase = False
    240. .Orientation = xlTopToBottom
    241. .SortMethod = xlPinYin
    242. .Apply
    243. End With
    244. '#################
    245. 'Versand ermitteln
    246. '#################
    247. rmax_versand = Sheets("Start").Cells(Rows.Count, 3).End(xlUp).row
    248. shname = "Versand" & datum
    249. If sheet_exists(shname) Then
    250. Application.DisplayAlerts = False
    251. Sheets(shname).Delete
    252. Application.DisplayAlerts = True
    253. End If
    254. Set wsNew = Worksheets.Add
    255. With wsNew
    256. .Name = shname
    257. .Move after:=Sheets(Sheets.Count)
    258. End With
    259. Set wsNew = Nothing
    260. Sheets(shname).Activate
    261. rmax_filtercopy = ActiveSheet.UsedRange.Rows.Count
    262. Sheets(datum).Activate
    263. '
    264. For i = 2 To rmax_versand
    265. crit = Sheets("Start").Range("C" & i).Value
    266. 'prüfen, ob kriterium existiert
    267. suchen_anzahl = 0
    268. suchen_anzahl = Application.WorksheetFunction.CountIf(Sheets(datum).Range("G:G"), crit)
    269. If suchen_anzahl = 0 Then
    270. GoTo hierweiter
    271. End If
    272. Columns("G:G").Select
    273. Selection.AutoFilter
    274. ActiveSheet.Range("$G$1:$G$" & rmax_tag).AutoFilter Field:=1, Criteria1:=crit
    275. rmax_filter = ActiveSheet.UsedRange.Rows.Count
    276. Rows("2:" & rmax_filter).Select
    277. Selection.Copy
    278. Sheets(shname).Activate
    279. Range("A" & rmax_filtercopy).Select
    280. Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:= _
    281. xlNone, SkipBlanks:=False, Transpose:=False
    282. rmax_filtercopy = ActiveSheet.UsedRange.Rows.Count + 1
    283. Sheets(datum).Activate
    284. Columns("G:G").Select
    285. Selection.AutoFilter
    286. hierweiter:
    287. Next
    288. Sheets(shname).Activate
    289. If Range("A1").Value = "" Then
    290. Sheets(datum).Activate
    291. GoTo versand_nixgefunden
    292. End If
    293. 'Aufträge
    294. Range("A" & rmax_filtercopy).Value = rmax_filtercopy - 1
    295. auftrag = Range("A" & rmax_filtercopy).Value
    296. 'Picks
    297. Range("I" & rmax_filtercopy).FormulaLocal = "=SUMME(I2:I" & rmax_filtercopy - 1 & ")"
    298. picks = Range("I" & rmax_filtercopy).Value
    299. 'Positionen
    300. Range("J" & rmax_filtercopy).FormulaLocal = "=SUMME(J2:J" & rmax_filtercopy - 1 & ")"
    301. positionen = Range("J" & rmax_filtercopy).Value
    302. positionen_versand = positionen
    303. 'doppelte Kunden löschen
    304. Columns("C:C").Select
    305. ActiveSheet.Range("$C$1:$C$" & rmax_filtercopy - 1).RemoveDuplicates Columns:=1, Header:=xlYes
    306. Range("C" & rmax_filtercopy).Value = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).row
    307. kunden = Range("C" & rmax_filtercopy).Value
    308. 'eintragen
    309. Sheets(auswahl).Activate
    310. 'datum suchen
    311. row = 0
    312. rmax_datum = ActiveSheet.UsedRange.Rows.Count
    313. i = 0
    314. For i = 1 To rmax_datum
    315. If Range("A" & i).Value = datum Then
    316. row = Range("A" & i).row
    317. Range("C" & row).Select
    318. Exit For
    319. End If
    320. Next i
    321. If row = 0 Then
    322. GoTo datumerror
    323. End If
    324. Range("H" & row).Value = kunden
    325. Range("I" & row).Value = auftrag
    326. Range("J" & row).Value = positionen
    327. Range("K" & row).Value = picks
    328. Sheets(datum).Activate
    329. versand_nixgefunden:
    330. 'Versandsheet löschen
    331. Application.DisplayAlerts = False
    332. Sheets(shname).Delete
    333. Application.DisplayAlerts = True
    334. '#################
    335. 'Abholer ermitteln
    336. '#################
    337. rmax_abholer = Sheets("Start").Cells(Rows.Count, 4).End(xlUp).row
    338. shname = "Abholer" & datum
    339. If sheet_exists(shname) Then
    340. Application.DisplayAlerts = False
    341. Sheets(shname).Delete
    342. Application.DisplayAlerts = True
    343. End If
    344. Set wsNew = Worksheets.Add
    345. With wsNew
    346. .Name = shname
    347. .Move after:=Sheets(Sheets.Count)
    348. End With
    349. Set wsNew = Nothing
    350. Sheets(shname).Activate
    351. rmax_filtercopy = ActiveSheet.UsedRange.Rows.Count
    352. Sheets(datum).Activate
    353. '
    354. For i = 2 To rmax_abholer
    355. crit = Sheets("Start").Range("D" & i).Value
    356. 'prüfen, ob kriterium existiert
    357. suchen_anzahl = 0
    358. suchen_anzahl = Application.WorksheetFunction.CountIf(Sheets(datum).Range("G:G"), crit)
    359. If suchen_anzahl = 0 Then
    360. positionen_abholer = 0
    361. GoTo hierweiter_abholer
    362. End If
    363. Columns("G:G").Select
    364. Selection.AutoFilter
    365. ActiveSheet.Range("$G$1:$G$" & rmax_tag).AutoFilter Field:=1, Criteria1:=crit
    366. rmax_filter = ActiveSheet.UsedRange.Rows.Count
    367. Rows("2:" & rmax_filter).Select
    368. Selection.Copy
    369. Sheets(shname).Activate
    370. Range("A" & rmax_filtercopy).Select
    371. Selection.PasteSpecial Paste:=xlPasteValuesAndNumberFormats, Operation:= _
    372. xlNone, SkipBlanks:=False, Transpose:=False
    373. rmax_filtercopy = ActiveSheet.UsedRange.Rows.Count + 1
    374. Sheets(datum).Activate
    375. Columns("G:G").Select
    376. Selection.AutoFilter
    377. hierweiter_abholer:
    378. Next
    379. Sheets(shname).Activate
    380. 'doppelte Kunden löschen
    381. If Range("C1").Value = "" Then
    382. Sheets(datum).Activate
    383. GoTo abholer_nixgefunden
    384. End If
    385. Range("J" & rmax_filtercopy).FormulaLocal = "=SUMME(J2:J" & rmax_filtercopy - 1 & ")"
    386. positionen_abholer = Range("J" & rmax_filtercopy)
    387. Sheets(datum).Activate
    388. abholer_nixgefunden:
    389. 'Abholersheet löschen
    390. Application.DisplayAlerts = False
    391. Sheets(shname).Delete
    392. Application.DisplayAlerts = True
    393. '#####
    394. 'REST
    395. '#####
    396. rmax_tag_summe = rmax_tag + 1
    397. 'Aufträge
    398. Range("A" & rmax_tag_summe).Value = rmax_tag - 1
    399. auftrag = Range("A" & rmax_tag_summe).Value
    400. 'Picks
    401. Range("I" & rmax_tag_summe).FormulaLocal = "=SUMME(I2:I" & rmax_tag & ")"
    402. picks = Range("I" & rmax_tag_summe).Value
    403. 'Positionen
    404. Range("J" & rmax_tag_summe).FormulaLocal = "=SUMME(J2:J" & rmax_tag & ")"
    405. positionen = Range("J" & rmax_tag_summe).Value
    406. 'doppelte Kunden löschen
    407. Columns("C:C").Select
    408. ActiveSheet.Range("$C$1:$C$" & rmax_tag).RemoveDuplicates Columns:=1, Header:=xlYes
    409. Range("C" & rmax_tag_summe).Value = ActiveSheet.Cells(Rows.Count, 3).End(xlUp).row - 1
    410. kunden = Range("C" & rmax_tag_summe).Value
    411. 'eintragen
    412. Sheets(auswahl).Activate
    413. 'datum suchen
    414. row = 0
    415. rmax_datum = ActiveSheet.UsedRange.Rows.Count + 1
    416. i = 0
    417. For i = 1 To rmax_datum
    418. Rows(i).Select
    419. If Range("A" & i).Value = datum Then
    420. row = Range("A" & i).row
    421. 'Range("C" & row).Select
    422. Exit For
    423. End If
    424. Next i
    425. If row = 0 Then
    426. GoTo datumerror
    427. End If
    428. Range("D" & row).Value = kunden
    429. Range("E" & row).Value = auftrag
    430. Range("F" & row).Value = positionen
    431. Range("G" & row).Value = picks
    432. Range("C" & row).Value = positionen - positionen_abholer - positionen_versand
    433. '
    434. Application.DisplayAlerts = False
    435. Sheets(datum).Delete
    436. Application.DisplayAlerts = True
    437. 'nächster Tag
    438. Sheets("source_lager").Activate
    439. End If
    440. Next
    441. '#########
    442. 'Aufräumen
    443. '#########
    444. Sheets(auswahl).Select
    445. Range("C3").Select
    446. Application.DisplayAlerts = False
    447. Sheets("source_lager").Delete
    448. Application.DisplayAlerts = True
    449. Unload frm_progress
    450. If MsgBox("Mit Sangro weitermachen?", Buttons:=vbYesNo + vbQuestion) = vbYes Then
    451. run_sangro
    452. Else
    453. Application.ScreenUpdating = True
    454. Exit Sub
    455. End If
    456. Else
    457. Sheets("Start").Activate
    458. Application.DisplayAlerts = False
    459. Sheets(auswahl).Delete
    460. Application.DisplayAlerts = True
    461. Application.ScreenUpdating = True
    462. Exit Sub
    463. End If
    464. Else
    465. MsgBox "keine Auswahl getroffen, Abbruch!", vbExclamation
    466. Application.ScreenUpdating = True
    467. Exit Sub
    468. End If
    469. End If
    470. Application.ScreenUpdating = True
    471. Exit Sub
    472. datumerror:
    473. Unload frm_progress
    474. MsgBox "Das Datum " & datum & " aus der Quelldatei wurde in der Vorlage nicht gefunden, wurde der richtige Monat gewählt?", vbExclamation
    475. Sheets("Start").Activate
    476. 'alle sheets löschen
    477. Application.DisplayAlerts = False
    478. For Each wks In ThisWorkbook.Sheets
    479. If wks.Name <> "Start" And wks.Name <> "Vorlage" Then
    480. wks.Delete
    481. End If
    482. Next
    483. Application.DisplayAlerts = True
    484. Exit Sub
    485. errhandler:
    486. modulname = "run_lager"
    487. error.handler (ups)
    488. Unload frm_progress
    489. Sheets("Start").Activate
    490. 'alle sheets löschen
    491. Application.DisplayAlerts = False
    492. For Each wks In ThisWorkbook.Sheets
    493. If wks.Name <> "Start" And wks.Name <> "Vorlage" Then
    494. wks.Delete
    495. End If
    496. Next
    497. Application.DisplayAlerts = True
    498. Exit Sub
    499. End Sub


    EDIT: wird ggf. sogar reichen das nicht pro Tag sondern direkt für den ganzen Monat alles zu summieren (ändert aber recht wenig an dem Weg)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „tragl“ ()

    tragl schrieb:

    - kann ich DataRows aus der QuellDataTable in eine neue (temporäre) DataTable kopieren? (z.B. alle Einträge die Datum = aktuelles Datum Schleife haben)
    Könntest Du. Aber wozu? Wenn Du nur einen Teil der DataRows haben willst, arbeite doch mit einem Filter. LINQ macht sich da ganz gut:

    VB.NET-Quellcode

    1. Dim DeineZeilenFuerHeute = DataSet1.KennzahlenOpt.Where(Function(x) x.Datum = Date.Today)
    Where gibt einen Teil der Daten wieder, und zwar die Daten, die die Bedingung in der Klammer erfüllen, bei denen hier also das Datum = Heute ist.
    Oder gleich zur Anzeige in einem DGV:

    VB.NET-Quellcode

    1. DgvFilteredData.DataSource = DataSet1.KennzahlenOpt.Where(Function(x) x.Datum = Date.Today).AsDataRowView

    tragl schrieb:

    - gibt's eine Möglichkeit die Anzahl eindeutiger Werte (z.B. Kundennummer) aus einer Spalte auszulesen?
    Ebenfalls mit LINQ:

    VB.NET-Quellcode

    1. Dim AnzahlDerKunden = DataSet1.KennzahlenOpt.DistinctBy(Function(x) x.Kundennummer).Count
    DistinctBy holt nur Die Datenzeilen her, die sich in der Bedingung unterschieden, hier also eine anderen Kundennummer haben.

    Ah, Moment. DistinctBy war ne Extension von mit. :D
    So geht's mit LINQ-Bordmitteln:

    VB.NET-Quellcode

    1. Dim AnzahlDerKunden = DataSet1.KennzahlenOpt.Select(Function(x) x.Kundennummer).Count

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    tragl schrieb:

    Die Excel-Tabelle importiere ich mir in eine neue DataTable und schmeiße schonmal alle Zeilen raus, die ich nicht benötige
    Ich hoffe, du verwendest eine typisierte DataTable.
    Ansonsten sollte das bereits alles sein, was du an Excel-herumfummelst - alle weitere Verarbeitung kann dann an der typDataTable ansetzen.
    Daraus wiederum kannste eine List(Of ExcelDataRow) zusammensammeln, und mit der kannste deine Zählungen beginnen.
    Ein paar Ansätze hat Vaporized ja bereits gezeigt.
    Nur das letzte Snippet muss glaub so aussehen:

    VB.NET-Quellcode

    1. Dim AnzahlDerKunden = DataSet1.KennzahlenOpt.Select(Function(x) x.Kundennummer).Distinct.Count


    tragl schrieb:

    Es gibt 3 Tourarten
    Fein - aber äh - wie ist das mit den gezeigten ExcelDaten verknüpft?
    Vermutlich kann man mit Linq-Grouping eine sehr elegante Lösung basteln, aber dazu muss die typDataTable erstmal da sein.
    Und wenn die noch eine Extra-Spalte TourArt hätte - wäre nicht verkehrt.


    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ErfinderDesRades“ ()

    Da hast Du recht, da hab ich einfach mal den Distinct-Zusatz vergessen :S
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Dts.Kennzahlen.AddKennzahlenRow(...) sieht mir streng typisiert aus.

    .Distinct.Count macht man da ohne runde Klammern in VB.Net? Ich würde ja gleich Liste von Kunden machen draus, dann kannst auf Liste.Count() zugreifen aber halt auch auf jede einezelne Kundennummer wenn nötig.
    also .Distinct().ToList(). Nur wenn das benötigt wird. Spart evtl. später im Code eine fast identische LinQ Abfrage.

    VaporiZed schrieb:

    Könntest Du. Aber wozu? Wenn Du nur einen Teil der DataRows haben willst, arbeite doch mit einem Filter.


    danke, das is genau das wonach ich such.

    ErfinderDesRades schrieb:

    Ich hoffe, du verwendest eine typisierte DataTable.


    jain. die rohdaten brauch ich nicht speichern deshalb ist das keine typisierte Table. Die Ergebnisse aus den ganzen Filterungen sollen dann in eine typisierte gespeichert werden.
    Geht das trotzdem?

    ErfinderDesRades schrieb:

    Und wenn die noch eine Extra-Spalte TourArt hätte - wäre nicht verkehrt.


    würde das vermutlich vereinfachen, gibt unser system aber nicht her. Also muss ich das über die Tournummern machen. Ich hab ne Optionen-Table gebaut, da ist für jeden Lagerort hinterlegt
    welche Touren unnötig sind, welche sind versand, welche abholer usw...

    Dksksm schrieb:

    Ich würde ja gleich Liste von Kunden machen draus, dann kannst auf Liste.Count() zugreifen

    brauche ich in dem Fall nicht, denn ich brauch nur einmal die anzahl der Kunden, danach brauch ich die Kundennummern nicht mehr ;)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    tragl schrieb:

    gibt unser system aber nicht her. Also muss ich das über die Tournummern machen.
    Wenn Du das aus der Tournummer herleiten kannst, geht es in 99% der Fälle auch automatisiert. Denn so, wie Du eine Auswahl im Kopf triffst, kannst Du es auch dem Programm hinterlegen. Wodurch ergibt sich denn aus der Tournummer die Tourart?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.

    VaporiZed schrieb:

    Denn so, wie Du eine Auswahl im Kopf triffst, kannst Du es auch dem Programm hinterlegen


    aber nicht in unserem WaWi...
    Das ist da alles seeeehr speziell :P
    Legen wir Logistiker prinzipiell selbst fest. Ich leg' ne Tournummer an und entscheide dann ob ich die für den Versand benutze oder für einen Fahrer - das kann ich höchstens über die Bezeichnung noch erkenntlich machen.
    Versand ist z.B. derzeit über "DHL-Versand LAGERORT" bei uns hinterlegt, allerdings gibt's dann noch GO!Express (aber nur teilweise) und wir haben auch noch 1-2 Standorte die UPS benutzen.. deshalb löse ich das über die
    Optionen und hinterlege da pro Lagerort alles (ist bei der Excel-Variante genauso):



    Und den ganzen Kram fange ich dann eben in Listen ab:

    VB.NET-Quellcode

    1. Dim lstUmsatzarten = New List(Of String)
    2. Dim lstTourenOhneRelevanz = New List(Of String)
    3. Dim lstTourenVersand = New List(Of String)
    4. Dim lstTourenAbholer = New List(Of String)
    5. For Each rwOpt In Dts.KennzahlenOpt
    6. If rwOpt.Standort = _standort Then
    7. For Each uArt In rwOpt.Umsatzarten.Split(","c)
    8. lstUmsatzarten.Add(uArt)
    9. Next
    10. For Each tNr In rwOpt.TourenOhneRelevanz.Split(","c)
    11. lstTourenOhneRelevanz.Add(tNr)
    12. Next
    13. For Each tNr In rwOpt.TourenVersand.Split(","c)
    14. lstTourenVersand.Add(tNr)
    15. Next
    16. For Each tNr In rwOpt.TourenAbholer.Split(","c)
    17. lstTourenAbholer.Add(tNr)
    18. Next
    19. End If
    20. Next
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    ErfinderDesRades schrieb:

    Ich hoffe, du verwendest eine typisierte DataTable.

    mal anders gefragt:

    Wenn es zwingend notwendig ist eine typTable dafür zu nutzen (ist ja scheinbar der einzige Weg da ordentlich Summen zu ziehen), wie bekomm' ich das hin
    die Excel-Daten ohne ID darein zu importieren und nach Abschluss meiner Zählungen / Zusammenfassungen genau die Daten wieder aus
    der typTable rauszulöschen? (Ich denke jetzt schonmal weiter für den Fall, dass mehrere Standorte die Funktion später ggf. zeitgleich ausführen -
    da kannste nicht einfach die komplette Table leer machen)

    Edit: Dann würde ich eine "KennzahlenCache"-Table im DTS anlegen, die nur zur Laufzeit mit Daten aus Excel gefüttert wird und danach wieder leer ist.
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    tragl schrieb:

    wie bekomm' ich das hin
    die Excel-Daten ohne ID darein zu importieren und nach Abschluss meiner Zählungen / Zusammenfassungen genau die Daten wieder aus
    der typTable rauszulöschen? (Ich denke jetzt schonmal weiter für den Fall, dass mehrere Standorte die Funktion später ggf. zeitgleich ausführen -
    da kannste nicht einfach die komplette Table leer machen)
    Komische Fragen das. Weil ich glaub, das folgende wusstest du bereits:
    zB mit KennzahlenCache.AddKennzahlenCacheRow(...)kannst du eine DataRow hinzufügen.
    Und mit KennzahlenCache.Remove(...)kannste eine solche wieder entfernen.
    Mit KennzahlenCache.Clear() kannste...
    Eine ID ist für sone TempTable natürlich nicht von belang - du willst ja nix abspeichern, und untergeordnete Tabellen sind auch nicht in Sicht.

    Hingegen die von mir vorgeschlagene

    ErfinderDesRades schrieb:

    TourArt
    -Spalte - dafür käme tatsächlich eine winzige übergeordnete Tabelle in Frage, die die 4 TourArten enthält, die bislang bekannt sind.
    Aber könnte man auch quickndirty als Integer belassen, den man dann allerdings auf ein TourArt-Enum casten müsste.
    (So Standard-Werte zuverlässig bereitstellen ist immer bischen nervig im TypDataset)
    Das Q&D hätte dann aber die Auswirkung, dass keine Relation über die Daten-Integrität dieser Spalte wacht.

    interessant auch wieder die Benamung zu betrachten: Ein einzelner Datensatz ist natürlich kein KennzahlenCache - ein Cache ist was ganz was anneres.
    Aber der einzelne Datensatz enthält mehrere Kennzahlen - also hier könnte man eine Pluralisierung tatsächlich mal geltenlassen (muss man aber nicht: Kennzahl.Picks wäre auch schön formuliert)

    Hmm jetzt denke ich "Kennzahl" ist eh voll der falsche Begriff.
    Ich weiss nicht, was deine Excel-Tabelle darstellt, aber sind das Kennzahlen? Und wenn ja, Kennzahlen von was?
    Ich rede vom ersten bildle in post#1 - das will ich in eine typTempTable übertragen haben.
    Die TempTable soll ja nur die Excel-Tabelle aufnehmen, und gerne noch die TourArt pro Datensatz hinzufügen.
    Das sei der Ausgangspunkt all weiterer Verarbeitung - und zwar in .Net und ohne Excel.

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „ErfinderDesRades“ ()

    ErfinderDesRades schrieb:

    -Spalte - dafür käme tatsächlich eine winzige übergeordnete Tabelle in Frage, die die 4 TourArten enthält, die bislang bekannt sind.

    Mal eine andere Überlegung... ich hab' alle TourNummern, welche in unserem WaWi existent sind sowieso in meinem Programm in einer Tabelle. Wenn ich da jetzt noch die TourArt als Spalte reinbaue, sollte sich das doch mit den
    Rohdaten vergleichen lassen oder?



    ErfinderDesRades schrieb:

    Hmm jetzt denke ich "Kennzahl" ist eh voll der falsche Begriff.
    Ich weiss nicht, was deine Excel-Tabelle darstellt, aber sind das Kennzahlen? Und wenn ja, Kennzahlen von was?

    Naja, schimpft sich bei uns halt Kennzahlen. Bezeichnet die Arbeit, die die Logistik mit einem Lieferschein hatte (unterschiedliche Artikel (Position), anzahl Artikel (Picks) und wieviele Kunden pro Tag
    wurden verschickt, wieviele gefahren etc.)

    Edit:
    Ich hab' die TourArt jetzt bei meinen TourNummern hinterlegt (wie oben beschrieben).
    Gibt es eine einfachere Alternative, die TourNr der Quelldaten abzufragen, ob die zu einer bestimmten Tour-Art gehört als ein For Each? (Zeile 4-12)

    So mach' ich das momentan:

    VB.NET-Quellcode

    1. 'Vorab unnötige Daten rausschmeißen
    2. For Each rwTemp In Dts.KennzahlenTemp
    3. If rwTemp.Umsatzart = "Handlieferschein" Or Not rwTemp._Ersteller_Info Like "*Logistik*" Then rwTemp.Delete() 'Rows löschen, die Umsatzart "Handlieferschein" oder Bearbeiter <> Logistik haben
    4. For Each rwArt In Dts.Tour
    5. If rwArt.Art = "Ohne Relevanz" Then
    6. If Not rwTemp.RowState = DataRowState.Deleted Then
    7. If rwTemp._Tour_Nr = rwArt.TourNr Then
    8. rwTemp.Delete() 'Rows mit Touren ohne Relevanz löschen
    9. End If
    10. End If
    11. End If
    12. Next
    13. Next
    14. Dts.SaveDts(Me) 'hier zwischenspeichern, damit ohne Überprüfung auf deleted rows weitergemacht werden kann. // GEHT DAS AUCH ANDERS??
    15. '
    16. 'weitere Bearbeitung


    Als Beispiel an anderer Stelle:
    z.B. sowas in der Art: (Zeile 2 dient als Beispiel und funzt natürlich nicht!)

    VB.NET-Quellcode

    1. Dim datumDaten = Dts.KennzahlenTemp.Where(Function(x) x.Datum.Date = loopDate) 'alle Einträge von loopDate in eine Liste packen
    2. Dim versandDaten = datumDaten.Where(Function(x) x._Tour_Nr = alle TourNr In dts.tour Where(Function(x) x.TourArt = "Versand"))


    UND wenn ich rows gelöscht habe, gibt's was damit ich "normal" weiterarbeiten kann (mit filtern und summieren), ohne dabei If Not rwTemp.RowState = DataRowState.Deleted Then abzufragen
    und OHNE das dts davor zu speichern? (Mit Speicherung des DTS sind alle rows mit rowstate = Deleted ja weg...)
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 4 mal editiert, zuletzt von „tragl“ ()

    DataRow.Delete ist eiglich für die Zusammenarbeit mit Datenbanken gedacht - also das entfernt die Row nicht wirklich, sondern setzt ihren RowState auf .Deleted - damit das später an die DB gesendet werden kann.
    DataTable.Remove(Row) lässt eine Row blankweg verschwinden.
    DAtaSet.AcceptChanges, DAtaTable.AcceptChanges hat eine ähnliche NebenWirkung: Hierdurch wird die ÄnderungsVerfolgung resetted, wobei als .Deleted markierte Rows dann auch entfernt werden.
    Meine DataTable.All() - Extension aus den Helpers enthält aber auch diesen Filter.

    Eine Frage wäre auch, wieso du diese unnützen Rows ühaupt zufügst - kannste die nicht schon beim Einlesen aussieben?
    Überhaupt beim Einlesen ja auch die TourArt setzen.
    Also der Excel-Row die TourNr entnehmen, diese in Dts.Tour suchen, von der TourRow die TourArt gleich in die KennzahlenTemp eintragen - kann doch net schwer sein.
    Also poste besser die Einlese-Routine (und bitte eine ganze Methode).

    Achso: Or ist böse. Es heisst: OrElse!!!!!

    ErfinderDesRades schrieb:

    Or ist böse. Es heisst: OrElse
    Naja, das ist n bisken übertrieben. Es tut ja seinen Zweck. Nur muss man es manchmal damit komplizierter machen, weil immer beide Seiten ausgewertet werden. @tragl: Das folgende geht dank OrElse, mit Or ginge es aber nicht:

    VB.NET-Quellcode

    1. Dim Text As String = Nothing
    2. If Text Is Nothing OrElse Text.Length = 0 Then Stop

    siehe: Der Unterschied zwischen And und AndAlso/Or und OrElse
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    ich bleibe dabei: Boolean-Or ist böse.
    Seit Einführung von OrElse (2005) gibt es keinen Grund mehr, Or für boolsche Logik noch zu verwenden.
    Gehört in die Mottenkiste wie zB ArrayList auch.
    Es hat nachwievor seine Berechtigung als Bit-Operator - und das ist auch gut, dass nun Boolean-Oder nun von Bit-Oder unterschieden ist.
    (Diesen Unterschied soll man bitte aber auch nicht wieder verwischen)

    Es sind natürlich Konstruktionen theoretisch denkbar, wo man den zweiten Teilausdruck ausgewertet haben will, obwohl der Rückgabewert keine Relevanz hat. Dabei würde es sich aber ums (höchst verdeckte) Nutzniessen eines Seiteneffekts handeln - und das wäre ein ziemlich gruseliger ArchitekturFehler.
    Praktisch ist mir ist auch nie derartiges untergekommen.
    Moin.

    ErfinderDesRades schrieb:

    Achso: Or ist böse. Es heisst: OrElse!!!!!

    Danke für den Hinweis, war mir nicht bekannt.

    ErfinderDesRades schrieb:

    (und bitte eine ganze Methode)

    ich muss immer aufpassen, was genau ich hier poste - denn es handelt sich ja um Unternehmensdaten ;)
    Also bei "sKd", "sPicks" usw. nicht wundern, das hat schon seine Berechtigung - kann ich hier nur nicht ausschreiben :)

    Aber hier mal der aktuelle Stand:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Private Sub excelDaten()
    2. msgInformation("Bitte im Folgenden die Lager-Datei auswählen.")
    3. Dim importLager = openFile("Excel-Dateien (*.xlsx)|*.xlsx")
    4. msgInformation("Bitte im Folgenden die S-Datei auswählen.")
    5. Dim importSg = openFile("Excel-Dateien (*.xlsx)|*.xlsx")
    6. If Not importLager = "" Then
    7. Using excelCon = New OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source='" & importLager & "'; " & "Extended Properties='Excel 12.0;HDR=YES;IMEX=1;'")
    8. excelCon.Open()
    9. Using da = New OleDbDataAdapter("Select [Datum],[Li#-Kunde#Nummer],[Tour#Nr],[Picks],[Positions-Anzahl],[Ersteller#Info],[Umsatzart] From [Tabelle1$]", excelCon)
    10. da.Fill(Dts.KennzahlenTemp)
    11. End Using
    12. End Using
    13. If Not importSg = "" Then
    14. Using excelCon = New OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source='" & importSg & "'; " & "Extended Properties='Excel 12.0;HDR=YES;IMEX=1;'")
    15. excelCon.Open()
    16. Using da = New OleDbDataAdapter("Select [Datum],[Li#-Kunde#Nummer],[Tour#Nr],[Picks],[Positions-Anzahl],[Ersteller#Info],[Umsatzart] From [Tabelle1$]", excelCon)
    17. da.Fill(Dts.KennzahlenTemp)
    18. End Using
    19. End Using
    20. getKennzahlen()
    21. Else
    22. Return
    23. End If
    24. Else
    25. Return
    26. End If
    27. End Sub
    28. Private Sub getKennzahlen()
    29. 'Vorab unnötige Daten rausschmeißen
    30. Dim tempTb = Dts.KennzahlenTemp
    31. For Each rwTemp In tempTb
    32. If rwTemp.Umsatzart = "Handlieferschein" OrElse Not rwTemp._Ersteller_Info Like "*Logistik*" Then
    33. tempTb.RemoveKennzahlenTempRow(rwTemp) 'Rows löschen, die Umsatzart "Handlieferschein" oder Bearbeiter <> Logistik haben
    34. End If
    35. For Each rwArt In Dts.Tour
    36. If rwArt.Art = "Ohne Relevanz" Then
    37. If rwTemp._Tour_Nr = rwArt.TourNr Then
    38. tempTb.RemoveKennzahlenTempRow(rwTemp) 'Rows mit Touren ohne Relevanz löschen
    39. End If
    40. End If
    41. Next
    42. Next
    43. 'weitere Bearbeitung
    44. Dim startDate = Date.Parse($"01.{_monatnummer}.{_setYear}")
    45. Dim endDate = MonatsEnde(_monatnummer.ToString, _setYear)
    46. Dim loopDate = startDate.Date
    47. Do While loopDate < endDate.Date.AddDays(1)
    48. 'fahrer
    49. Dim fahrerPos = 0 'Positionen belieferte Kunden
    50. Dim abholerPos = 0 'Positionen Abholer-Touren (für Berechnung Fahrer-Positionen nötig)
    51. 'lager
    52. Dim lagerKd = 0 'Kunden Lager
    53. Dim lagerAu = 0 'Aufträge Lager
    54. Dim lagerPos = 0 'Positionen Lager
    55. Dim lagerPicks = 0 'Picks Lager
    56. 'paket
    57. Dim paketKd = 0 'davon Kunden Paket
    58. Dim paketAu = 0 'davon Aufträge Paket
    59. Dim paketPos = 0 'davon Positionen Paket
    60. Dim paketPicks = 0 'davon Picks Paket
    61. 's
    62. Dim sKd = 0
    63. Dim sAu = 0
    64. Dim sPos = 0
    65. Dim sPicks = 0
    66. '
    67. Dim datumDaten = tempTb.Where(Function(x) x.Datum.Date = loopDate) 'alle Einträge von loopDate in eine Liste packen
    68. lagerKd = datumDaten.Select(Function(x) x._Li__Kunde_Nummer).Distinct.Count
    69. lagerAu = datumDaten.Count
    70. lagerPos = datumDaten.Sum(Function(x) x._Positions_Anzahl)
    71. lagerPicks = datumDaten.Sum(Function(x) x.Picks)
    72. 'abholer, versand
    73. Dim versandtouren = Dts.Tour.Where(Function(x) x.Art = "Paketversand")
    74. 'Dim versandDaten = datumDaten.Where(Function(x) x._Tour_Nr = ve)
    75. 's
    76. Dts.Kennzahlen.AddKennzahlenRow(loopDate, _standort, fahrerPos, lagerKd, lagerAu, lagerPos, lagerPicks, paketKd, paketAu, paketPos, paketPicks, sKd, sAu, sPos, sPicks)
    77. loopDate = loopDate.AddDays(1)
    78. Loop
    79. End Sub


    ErfinderDesRades schrieb:

    Eine Frage wäre auch, wieso du diese unnützen Rows ühaupt zufügst - kannste die nicht schon beim Einlesen aussieben?

    Naja, die "unnützen" rows sind eben in den Rohdaten vorhanden, sowie sehr viele andere Spalten auch (die kann ich beim Einlesen aber ja schon weglassen)
    ich wüsste nicht wie - ist das für den Fall nicht "egal" in welcher Methode die rausfliegen?

    ErfinderDesRades schrieb:

    Überhaupt beim Einlesen ja auch die TourArt setzen.

    könnte man sicher machen, nur weiß ich aber noch immer nicht, wie ich z.B. Zeile 36-43 verkürzt abgleichen kann, ob der Wert vorhanden ist ohne das mit For-Each lösen zu müssen. Geht doch bestimmt oder? ;)
    Das würde dafür helfen ;)

    Edit: Mit RemoveRow hantiert er trotzdem noch mit den gelöschten Rows rum: X(
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „tragl“ ()

    tragl schrieb:

    nur weiß ich aber noch immer nicht, wie ich z.B. Zeile 36-43 verkürzt abgleichen kann, ob der Wert vorhanden ist ohne das mit For-Each lösen zu müssen

    aus

    VB.NET-Quellcode

    1. For Each rwArt In Dts.Tour
    2. If rwArt.Art = "Ohne Relevanz" Then
    3. If rwTemp._Tour_Nr = rwArt.TourNr Then
    4. tempTb.RemoveKennzahlenTempRow(rwTemp) 'Rows mit Touren ohne Relevanz löschen
    5. End If
    6. End If
    7. Next
    mach

    VB.NET-Quellcode

    1. If Dts.Tour.Any(Function(x) x.Art = "Ohne Relevanz" AndAlso rwTemp._Tour_Nr = x.TourNr) Then tempTb.RemoveKennzahlenTempRow(rwTemp)

    'oder vielleicht stattdessen einfach Then rwTemp.Delete?
    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „VaporiZed“, mal wieder aus Grammatikgründen.

    Aufgrund spontaner Selbsteintrübung sind all meine Glaskugeln beim Hersteller. Lasst mich daher bitte nicht den Spekulatiusbackmodus wechseln.
    Ah - du importierst mittels OleDb - habichja net gewusst!
    Da kannste beim Einlesen tatsächlich nicht filtern - bzw. den Filter müsste man in Sql formulieren, was was anneres ist als typisierte Datenverarbeitung.
    Als erstes würde ich aber die Architektur korrigieren.
    ZB ist im (schlecht benamten) excelDaten() zweimal derselbe Code - das sollte in eine Methode ausgelagert werden.

    Also mir schwebt diese Architektur vor:

    VB.NET-Quellcode

    1. ''' <param name="import1">erste Import-Datei</param>
    2. ''' <param name="import2">zweite Import-Datei</param>
    3. ''' <param name="timeRange">Date-Array aus 2 Elementen: 0: untere Inklusiv-Schranke, 1: obere Exklusiv-Schranke </param>
    4. Public Sub FillKennzahlenFromExcel(import1 As String, import2 As String, timeRange As Date())
    5. If import1 = "" OrElse import2 = "" Then Return
    6. FillTempTableFromExcel(import1)
    7. FillTempTableFromExcel(import2)
    8. PurgeTempTable(timeRange)
    9. FillKennzahlenFromTempTable()
    10. End Sub
    11. Private Sub FillTempTableFromExcel(import As String)
    12. End Sub
    13. ''' <summary>entfernt irrelevante DataRows aus KennzahlenTemp </summary>
    14. Private Sub PurgeTempTable(timeRange() As Date)
    15. End Sub
    16. ''' <summary>Wertet KennzahlenTemp aus, und befüllt damit Kennzahlen</summary>
    17. Private Sub FillKennzahlenFromTempTable()
    18. End Sub
    So kann man Schritt für Schritt die Probleme lösen.
    Man kann sogar ein TestForm anzeigen, was beliebige DataTables anzeigen kann, und dem übergibt man den erreichten Stand in Form einer DataTable, und kann sehen, obs inhaltlich korrekt ist.
    Wennde soweit bist, könnemer uns das Purge vorknöpfen.
    Ein Tipp noch: Sql kann Spalten umbenennen - solche Properties: _Li__Kunde_Nummer sind nicht nötig.
    Probierma

    SQL-Abfrage

    1. Select [Datum],[Li#-Kunde#Nummer] AS LiKundeNr,[Tour#Nr],[Picks],[Positions-Anzahl] As PositionCount,[Ersteller#Info],[Umsatzart] From [Tabelle1$]


    Wenns um viele Datensätze geht, könnte man den timeRange-Filter auch ins Sql verlegen.



    Zum Problem dass das mit Remove nicht funzt: Eine Schleife, die aus sich selbst Elemente rauslöscht muss rückwärts durchlaufen werden.
    Einfacher ist allerdings, die Kandidaten in ein Array einzulesen, sodass dieses sich nicht selbst die Elemente weghaut.
    So:

    VB.NET-Quellcode

    1. For Each rwTemp In tempTb.ToArray
    und schon gehts.



    PS: Noch eine Architektur-Alternative ohne ausdrückliche Purge-Methode:

    VB.NET-Quellcode

    1. ''' <param name="import1">erste Import-Datei</param>
    2. ''' <param name="import2">zweite Import-Datei</param>
    3. ''' <param name="timeRange">Date-Array aus 2 Elementen: 0: untere Inklusiv-Schranke, 1: obere Exklusiv-Schranke </param>
    4. Public Sub FillKennzahlenFromExcel(import1 As String, import2 As String, timeRange As Date())
    5. If import1 = "" OrElse import2 = "" Then Return
    6. FillTempTableFromExcel(import1)
    7. FillTempTableFromExcel(import2)
    8. KenndatenTemp.Where(Function(x) Not IsRelevant(x, timeRange)).ForEach(AddressOf KenndatenTemp.Remove) ' Purge-Alternative
    9. FillKennzahlenFromTempTable()
    10. End Sub
    11. Private Sub FillTempTableFromExcel(import As String)
    12. End Sub
    13. Private Function IsRelevant(rw As KenndatenTempRow, timeRange As Date()) As Boolean
    14. If Not rw.Datum.IsBetween(timeRange(0), timeRange(1), False, True, False) Then Return False
    15. If rw.Umsatzart = "Handlieferschein" OrElse Not rw._Ersteller_Info Like "*Logistik*" Then Return False
    16. ' ...
    17. Return True
    18. End Function
    19. '[...]

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „ErfinderDesRades“ ()

    aaaalso ^^

    ErfinderDesRades schrieb:

    Ah - du importierst mittels OleDb - habichja net gewusst!

    welche Variante schwebt dir vor? Mir wäre es ohne OleDb eigentlich lieber, weil für OleDb müsste auf den Rechnern noch Zeugs installiert werden damit das läuft - bin also über jede Variante froh,
    die nix mit OleDB oder JetDB zu tun hat.. :!:

    ErfinderDesRades schrieb:

    Als erstes würde ich aber die Architektur korrigieren.

    hatter gemacht - allerdings ohne timeRange, denn die Rohdaten beinhalten immer den kompletten Monat (ggf. auch mal nur ein paar Tage)-das kann ich im System bei uns so einstellen wie ich möchte.
    Wir erstellen aber grundsätzlich keine Monatsübergreifenden Rohdaten, falls doch würden die halt in meinem Programm ignoriert werden :D
    Die Benamung hat mir auch nicht gefallen, war mir aber erstmal wurscht. Das hätte ich geändert, sobald das komplett gelaufen wäre - aber ist nun auch erledigt.

    ErfinderDesRades schrieb:

    Man kann sogar ein TestForm anzeigen, was beliebige DataTables anzeigen kann, und dem übergibt man den erreichten Stand in Form einer DataTable, und kann sehen, obs inhaltlich korrekt ist.

    Das mach' ich sowieso. Auf der Form gibt's testweise ein DGV, welches an die bsKennzahlenTemp gebunden ist ;)

    ErfinderDesRades schrieb:

    Ein Tipp noch: Sql kann Spalten umbenennen - solche Properties: _Li__Kunde_Nummer sind nicht nötig.
    Probierma

    Wusste ich auch nicht, dass das geht. Klappt natürlich wunderbar, dann sind die kryptischen Benamungen auch Geschichte. :thumbup:

    ErfinderDesRades schrieb:

    PS: Noch eine Architektur-Alternative ohne ausdrückliche Purge-Methode:

    Auch gut, ich hab das wie folgt für die ersten Schritte gelöst: (hier jetz auchmal die komplette form-class)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports Logistik_Tool.dtsLogistik
    2. Imports System.Data.OleDb
    3. Public Class frmKennzahlen
    4. Private _setYear As String
    5. Private _monatname As String
    6. Private _monatnummer As Integer
    7. Private _standort As String
    8. Private Sub frmKennzahlen_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    9. If My.Settings.KennzahlenJahr = "" Then My.Settings.KennzahlenJahr = Date.Now.ToString("yyyy") 'Voreinstellung, damit "JAHR" nicht Nothing oder "" ist
    10. lblEingestelltesJahr.Text = $"Eingestellt: {My.Settings.KennzahlenJahr}"
    11. cmbMonat.Text = MonatName(Date.Now.Month)
    12. End Sub
    13. Private Sub btn_Click(sender As Object, e As EventArgs) Handles btnJahrAendern.Click, Button1.Click
    14. Select Case True
    15. Case sender Is Button1
    16. _setYear = My.Settings.KennzahlenJahr
    17. _monatname = cmbMonat.Text
    18. _monatnummer = MonatNummer(_monatname)
    19. _standort = bsStandort.At(Of StandortRow).Name
    20. If Not _monatnummer = 0 Then
    21. If Dts.HasChanges Then
    22. Dts.askSaveDts(Me)
    23. End If
    24. msgInformation("Bitte im Folgenden die Lager-Datei auswählen.")
    25. Dim import1 = openFile("Excel-Dateien (*.xlsx)|*.xlsx")
    26. msgInformation("Bitte im Folgenden die S-Datei auswählen.")
    27. Dim import2 = openFile("Excel-Dateien (*.xlsx)|*.xlsx")
    28. FillKennzahlenFromExcel(import1, import2)
    29. Else
    30. msgInformation("Bitte wählen Sie einen Monat aus.")
    31. End If
    32. Case sender Is btnJahrAendern
    33. Using dlg As New dlgJahrÄndern
    34. If dlg.ShowDialog = DialogResult.OK Then
    35. My.Settings.KennzahlenJahr = dlg.tbJahr.Text
    36. End If
    37. End Using
    38. lblEingestelltesJahr.Text = $"Eingestellt: {My.Settings.KennzahlenJahr}"
    39. End Select
    40. End Sub
    41. ''' <param name="import1">erste Import-Datei</param>
    42. ''' <param name="import2">zweite Import-Datei</param>
    43. Public Sub FillKennzahlenFromExcel(import1 As String, import2 As String)
    44. If import1 = "" OrElse import2 = "" Then Return
    45. FillTempTableFromExcel(import1)
    46. FillTempTableFromExcel(import2)
    47. addTourArt()
    48. Dts.KennzahlenTemp.Where(Function(x) Not IsRelevant(x)).ForEach(AddressOf Dts.KennzahlenTemp.RemoveKennzahlenTempRow)
    49. FillKennzahlenFromTempTable()
    50. End Sub
    51. ''' <summary>Holt sich bestimmte Spalten aus der Excel-Datei (import) und fügt die Daten der KennzahlenTemp-Table zu</summary>
    52. Private Sub FillTempTableFromExcel(import As String)
    53. Using excelCon = New OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; Data Source='" & import & "'; " & "Extended Properties='Excel 12.0;HDR=YES;IMEX=1;'")
    54. excelCon.Open()
    55. Using da = New OleDbDataAdapter("Select [Datum],[Li#-Kunde#Nummer] As LiKundeNr,[Tour#Nr] As TourNr,[Picks],[Positions-Anzahl] As Pos,[Ersteller#Info] As Ersteller,[Umsatzart] From [Tabelle1$]", excelCon)
    56. da.Fill(Dts.KennzahlenTemp)
    57. End Using
    58. End Using
    59. End Sub
    60. ''' <summary>Wertet KennzahlenTemp aus, und befüllt damit Kennzahlen</summary>
    61. Private Sub FillKennzahlenFromTempTable()
    62. End Sub
    63. ''' <summary>Fügt die TourArt der Tabelle "KennzahlenTemp" hinzu</summary>
    64. Private Sub addTourArt()
    65. For Each rwTemp In Dts.KennzahlenTemp
    66. For Each rwTour In Dts.Tour
    67. If rwTemp.TourNr = rwTour.TourNr Then
    68. rwTemp.TourArt = rwTour.Art
    69. End If
    70. Next
    71. Next
    72. End Sub
    73. ''' <summary>Prüft die KennzahlenTempRows auf irrelevante Daten</summary>
    74. Private Function IsRelevant(rw As KennzahlenTempRow) As Boolean
    75. If rw.Umsatzart = "Handlieferschein" OrElse Not rw.Ersteller Like "*Logistik*" Then Return False
    76. If rw.TourArt = "Ohne Relevanz" Then Return False
    77. Return True
    78. End Function
    79. End Class


    Zeile 52 macht allerdings Probleme: (hat bestimmt wieder was mit der dusseligen Lösch-Methode zu tun X/ ) Ich find's ja gut, dass "gelöschte" Daten nicht direkt weg sind
    aber beim Entwickeln nervt das ungemein! Was gelöscht is, is gelöscht und fertig.


    Edit: Ah, so geht's (hast du ja selbst oben geschrieben :P ) Dts.KennzahlenTemp.ToArray.Where(Function(x) Not IsRelevant(x)).ForEach(AddressOf Dts.KennzahlenTemp.RemoveKennzahlenTempRow)
    Funzt nun so, wie ich mir das vorgestellt hab. Mal wieder Danke für die Hilfe!
    "Na, wie ist das Wetter bei dir?"
    "Caps Lock."
    "Hä?"
    "Shift ohne Ende!" :thumbsup:

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „tragl“ ()