' Serien-Kalendereinträge aus Excel erstellen mit Serienlogik, Löschung alter Einträge, Logging, Laufzeitmessung, Zusammenfassung und Simulationsmodus Sub SerienKalendereintraegeErstellen() ' Benutzer wird gefragt, ob Simulation gewünscht ist Dim userResponse As VbMsgBoxResult userResponse = MsgBox("Möchtest du eine Simulation durchführen (keine Einträge werden erstellt oder gelöscht)?", vbYesNo + vbQuestion, "Simulationsmodus") Dim DRYRUN As Boolean DRYRUN = (userResponse = vbYes) ' True = Simulation, False = Echtbetrieb Dim olApp As Object, olNS As Object Dim allCalendars As Collection, selectedCalendar As Object Dim calendarNames() As String, selectedIndex As Variant Dim olItems As Object, ws As Worksheet Dim lastRow As Long, i As Long, j As Long, erstelltCount As Long, serienCount As Long, geloeschtCount As Long, uebersprungenCount As Long Dim eintraege As Collection Dim datum As Date, startzeit As Date, endzeit As Date Dim produkt As String, hinweis As String, veranstaltungsnummer As String Dim titel As String, ort As String Dim alreadyProcessed() As Boolean Dim startTime As Double Dim logSheet As Worksheet startTime = Timer On Error Resume Next Set olApp = GetObject(, "Outlook.Application") If olApp Is Nothing Then Set olApp = CreateObject("Outlook.Application") On Error GoTo 0 If olApp Is Nothing Then MsgBox "Outlook konnte nicht gestartet werden.", vbCritical Exit Sub End If Set olNS = olApp.GetNamespace("MAPI") Set allCalendars = New Collection Dim store As Object, folder As Object For Each store In olNS.Folders For Each folder In store.Folders If folder.DefaultItemType = 1 Then allCalendars.Add folder Next folder Next store ReDim calendarNames(1 To allCalendars.Count) For i = 1 To allCalendars.Count calendarNames(i) = allCalendars(i).Parent.Name & " – " & allCalendars(i).Name Next i selectedIndex = Application.InputBox("Wähle den Zielkalender aus (Zahl):" & vbCrLf & Join(calendarNames, vbCrLf), "Kalenderauswahl", Type:=1) If Not IsNumeric(selectedIndex) Or selectedIndex < 1 Or selectedIndex > allCalendars.Count Then Exit Sub Set selectedCalendar = allCalendars(selectedIndex) MsgBox "Ausgewählter Kalender: " & selectedCalendar.Name, vbInformation, "Kalenderbestätigung" Set olItems = selectedCalendar.Items olItems.Sort "[Start]" olItems.IncludeRecurrences = True Dim gefilterteItems As Object Dim filterStart As String filterStart = "[Start] >= '" & Format(Date, "ddddd h:nn AMPM") & "'" Set gefilterteItems = olItems.Restrict(filterStart) Debug.Print "Kalender geladen: " & selectedCalendar.Name & ", " & gefilterteItems.Count & " gefilterte Einträge" Set ws = ThisWorkbook.Sheets(1) lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row ReDim alreadyProcessed(1 To lastRow) Set eintraege = New Collection For i = 2 To lastRow Debug.Print "---" Debug.Print "Verarbeite Zeile: " & i Debug.Print "Datum: " & ws.Cells(i, "B").Text Debug.Print "Startzeit: " & ws.Cells(i, "C").Text Debug.Print "Endzeit: " & ws.Cells(i, "D").Text Debug.Print "Produkt: " & ws.Cells(i, "G").Text Debug.Print "Hinweis für Trainer: " & ws.Cells(i, "L").Text Debug.Print "Veranstaltungsnummer: " & ws.Cells(i, "F").Text Debug.Print "Ort: " & ws.Cells(i, "J").Text If alreadyProcessed(i) Then GoTo Weiter If Not IsDate(ws.Cells(i, "B").Value) Then ws.Cells(i, "M").Value = "übersprungen (Datum fehlt)" uebersprungenCount = uebersprungenCount + 1 GoTo Weiter End If If ws.Cells(i, "C").Value = "" Then ws.Cells(i, "M").Value = "übersprungen (Startzeit fehlt)" uebersprungenCount = uebersprungenCount + 1 GoTo Weiter End If If ws.Cells(i, "G").Value = "" Then ws.Cells(i, "M").Value = "übersprungen (kein Produkt)" uebersprungenCount = uebersprungenCount + 1 GoTo Weiter End If datum = DateValue(ws.Cells(i, "B").Value) If IsDate(ws.Cells(i, "C").Value) Then startzeit = TimeValue(ws.Cells(i, "C").Value) Else ws.Cells(i, "M").Value = "übersprungen (ungültige Startzeit)" GoTo Weiter End If If IsDate(ws.Cells(i, "D").Value) Then endzeit = TimeValue(ws.Cells(i, "D").Value) Else ws.Cells(i, "M").Value = "übersprungen (ungültige Endzeit)" GoTo Weiter End If produkt = Trim(ws.Cells(i, "G").Value) veranstaltungsnummer = Trim(ws.Cells(i, "F").Value) hinweis = Trim(ws.Cells(i, "L").Value) ort = Trim(ws.Cells(i, "J").Value) If InStr(1, hinweis, "Lehrgang: ", vbTextCompare) > 0 Then hinweis = Mid(hinweis, InStr(1, hinweis, "Lehrgang: ", vbTextCompare) + 10) End If titel = produkt & " - " & hinweis If titel = " - " Or titel = "-" Then ws.Cells(i, "M").Value = "übersprungen (kein gültiger Titel)" GoTo Weiter End If ' Duplikatprüfung: Wenn in Outlook bereits ein Termin mit Datum und Veranstaltungsnummer vorhanden ist Dim skip As Boolean: skip = False If Not DRYRUN Then Dim existingItem As Object, itemDate As Date For Each existingItem In gefilterteItems If existingItem.Class = 26 Then itemDate = Int(existingItem.Start) If itemDate = datum Then If InStr(existingItem.Body, veranstaltungsnummer) > 0 Then If existingItem.Subject <> titel Then Dim msg As VbMsgBoxResult msg = MsgBox("Ein Eintrag mit gleicher Veranstaltungsnummer aber abweichendem Titel existiert: " & existingItem.Subject & vbCrLf & _ "Neuer Titel wäre: " & titel & vbCrLf & "Trotzdem ersetzen?", vbYesNo + vbExclamation) If msg = vbNo Then skip = True Else skip = True End If End If End If End If Next existingItem End If If skip Then ' Bestehenden Termin ggf. löschen If Not DRYRUN Then For Each existingItem In gefilterteItems If existingItem.Class = 26 And Int(existingItem.Start) = datum Then If InStr(existingItem.Body, veranstaltungsnummer) > 0 Then existingItem.Delete geloeschtCount = geloeschtCount + 1 Exit For End If End If Next End If ws.Cells(i, "M").Value = "ersetzt (gelöscht + neu)" GoTo Weiter End If ' Erstellung des Outlook-Termins oder Simulation If DRYRUN Then ws.Cells(i, "M").Value = "(Simulation) " & titel ws.Cells(i, "M").Interior.Color = RGB(200, 200, 200) Else Dim appt As Object Set appt = olApp.CreateItem(1) With appt .Start = datum + startzeit .End = datum + endzeit .Subject = titel .Location = ort .Body = veranstaltungsnummer .ReminderSet = False .BusyStatus = 2 .Save End With ws.Cells(i, "M").Value = titel erstelltCount = erstelltCount + 1 End If alreadyProcessed(i) = True ' Serientermin-Erkennung: gleiche Veranstaltungsnummer an aufeinanderfolgenden Werktagen Dim serieEndRow As Long: serieEndRow = i Do While serieEndRow + 1 <= lastRow And Not alreadyProcessed(serieEndRow + 1) Dim nextDatum As Date If Not IsDate(ws.Cells(serieEndRow + 1, "B").Value) Then Exit Do nextDatum = DateValue(ws.Cells(serieEndRow + 1, "B").Value) If ws.Cells(serieEndRow + 1, "F").Value <> veranstaltungsnummer Then Exit Do If Weekday(datum, vbMonday) = 5 Then ' Freitag If DateDiff("d", datum, nextDatum) <> 3 Then Exit Do ' Freitag → Montag Else If DateDiff("d", datum, nextDatum) <> 1 Then Exit Do End If If ws.Cells(serieEndRow + 1, "G").Value = "" Then Exit Do serieEndRow = serieEndRow + 1 Loop If serieEndRow > i Then ' Serien-Eintrag If Not DRYRUN Then Dim recurrenceAppt As Object Set recurrenceAppt = olApp.CreateItem(1) With recurrenceAppt .Start = datum + startzeit .End = datum + endzeit .Subject = titel .Location = ort .Body = veranstaltungsnummer .ReminderSet = False .BusyStatus = 2 .Save Dim pattern Set pattern = .GetRecurrencePattern pattern.RecurrenceType = 1 ' daily pattern.PatternStartDate = datum pattern.Occurrences = serieEndRow - i + 1 .Save End With For j = i To serieEndRow alreadyProcessed(j) = True ws.Cells(j, "M").Value = titel & " (Serie)" Next j serienCount = serienCount + 1 GoTo Weiter Else For j = i To serieEndRow alreadyProcessed(j) = True ws.Cells(j, "M").Value = "(Simulation) " & titel & " (Serie)" ws.Cells(j, "M").Interior.Color = RGB(180, 180, 180) Next j serienCount = serienCount + 1 GoTo Weiter End If End If Weiter: Next i Dim elapsedTime As Double elapsedTime = Timer - startTime MsgBox "Fertig. " & erstelltCount & " Termine erstellt, " & serienCount & " Serientermine erstellt, " & geloeschtCount & " ersetzt, " & uebersprungenCount & " übersprungen." & vbCrLf & _ "Laufzeit: " & Format(elapsedTime, "0.00") & " Sekunden", vbInformation End Sub