Last active 1753356033

gistfile1.txt Raw
1' Serien-Kalendereinträge aus Excel erstellen mit Serienlogik, Löschung alter Einträge, Logging, Laufzeitmessung, Zusammenfassung und Simulationsmodus
2
3Sub SerienKalendereintraegeErstellen()
4 ' Benutzer wird gefragt, ob Simulation gewünscht ist
5 Dim userResponse As VbMsgBoxResult
6 userResponse = MsgBox("Möchtest du eine Simulation durchführen (keine Einträge werden erstellt oder gelöscht)?", vbYesNo + vbQuestion, "Simulationsmodus")
7 Dim DRYRUN As Boolean
8 DRYRUN = (userResponse = vbYes) ' True = Simulation, False = Echtbetrieb
9
10 Dim olApp As Object, olNS As Object
11 Dim allCalendars As Collection, selectedCalendar As Object
12 Dim calendarNames() As String, selectedIndex As Variant
13 Dim olItems As Object, ws As Worksheet
14 Dim lastRow As Long, i As Long, j As Long, erstelltCount As Long, serienCount As Long, geloeschtCount As Long, uebersprungenCount As Long
15 Dim eintraege As Collection
16 Dim datum As Date, startzeit As Date, endzeit As Date
17 Dim produkt As String, hinweis As String, veranstaltungsnummer As String
18 Dim titel As String, ort As String
19 Dim alreadyProcessed() As Boolean
20 Dim startTime As Double
21 Dim logSheet As Worksheet
22
23 startTime = Timer
24
25 If Not DRYRUN Then
26 On Error Resume Next
27 Set olApp = GetObject(, "Outlook.Application")
28 If olApp Is Nothing Then Set olApp = CreateObject("Outlook.Application")
29 On Error GoTo 0
30 If olApp Is Nothing Then
31 MsgBox "Outlook konnte nicht gestartet werden.", vbCritical
32 Exit Sub
33 End If
34 Set olNS = olApp.GetNamespace("MAPI")
35 Set allCalendars = New Collection
36
37 Dim store As Object, folder As Object
38 For Each store In olNS.Folders
39 For Each folder In store.Folders
40 If folder.DefaultItemType = 1 Then allCalendars.Add folder
41 Next folder
42 Next store
43
44 ReDim calendarNames(1 To allCalendars.Count)
45 For i = 1 To allCalendars.Count
46 calendarNames(i) = allCalendars(i).Parent.Name & " – " & allCalendars(i).Name
47 Next i
48 selectedIndex = Application.InputBox("Wähle den Zielkalender aus (Zahl):" & vbCrLf & Join(calendarNames, vbCrLf), "Kalenderauswahl", Type:=1)
49 If Not IsNumeric(selectedIndex) Or selectedIndex < 1 Or selectedIndex > allCalendars.Count Then Exit Sub
50
51 Set selectedCalendar = allCalendars(selectedIndex)
52 MsgBox "Ausgewählter Kalender: " & selectedCalendar.Name, vbInformation, "Kalenderbestätigung"
53 Set olItems = selectedCalendar.Items
54 olItems.Sort "[Start]"
55 olItems.IncludeRecurrences = True
56
57 Dim gefilterteItems As Object
58 Dim filterDatum As String
59 filterDatum = Format(Date, "mm/dd/yyyy 12:00 AM")
60 Set gefilterteItems = olItems.Restrict("[Start] >= '" & filterDatum & "'")
61 Debug.Print "Gefilterte Einträge: " & gefilterteItems.Count
62
63 On Error Resume Next
64 Set logSheet = ThisWorkbook.Sheets("Gelöschte Termine")
65 If logSheet Is Nothing Then
66 Set logSheet = ThisWorkbook.Sheets.Add
67 logSheet.Name = "Gelöschte Termine"
68 logSheet.Range("A1:D1").Value = Array("Datum", "Startzeit", "Titel", "Kalender")
69 End If
70 On Error GoTo 0
71 End If
72
73 Set ws = ThisWorkbook.Sheets(1)
74 lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
75 ReDim alreadyProcessed(1 To lastRow)
76
77 For i = 2 To lastRow
78 If alreadyProcessed(i) Then GoTo Weiter
79
80 If ws.Cells(i, "B").Value < DateSerial(Year(Date), Month(Date), Day(Date)) Then
81 ws.Cells(i, "M").Value = "übersprungen (Vergangenheit)"
82 uebersprungenCount = uebersprungenCount + 1
83 GoTo Weiter
84 End If
85
86 If Not IsDate(ws.Cells(i, "B").Value) Or ws.Cells(i, "G").Value = "" Then
87 ws.Cells(i, "M").Value = "übersprungen (kein Datum/kein Produkt)"
88 uebersprungenCount = uebersprungenCount + 1
89 GoTo Weiter
90 End If
91
92 Set eintraege = New Collection
93 veranstaltungsnummer = Trim(ws.Cells(i, "F").Value)
94 produkt = Trim(ws.Cells(i, "G").Value)
95 hinweis = Trim(ws.Cells(i, "L").Value)
96 If InStr(hinweis, "Lehrgang: ") > 0 Then
97 hinweis = Mid(hinweis, InStr(hinweis, "Lehrgang: ") + 10)
98 End If
99 titel = produkt & " - " & hinweis
100 If Trim(titel) = "-" Or Trim(titel) = "- -" Or Trim(titel) = "" Then
101 ws.Cells(i, "M").Value = "übersprungen (leerer Titel)"
102 uebersprungenCount = uebersprungenCount + 1
103 GoTo Weiter
104 End If
105 ort = ws.Cells(i, "J").Value
106
107 datum = ws.Cells(i, "B").Value
108 eintraege.Add i
109 alreadyProcessed(i) = True
110
111 For j = i + 1 To lastRow
112 If alreadyProcessed(j) Then GoTo SkipJ
113 If Trim(ws.Cells(j, "F").Value) <> veranstaltungsnummer Then GoTo SkipJ
114 If ws.Cells(j, "G").Value = "" Then GoTo SkipJ
115 If Not IsDate(ws.Cells(j, "B").Value) Then GoTo SkipJ
116 If ws.Cells(j, "B").Value - datum = 1 Or _
117 (Weekday(datum, vbMonday) = 5 And ws.Cells(j, "B").Value - datum = 3) Then
118 eintraege.Add j
119 alreadyProcessed(j) = True
120 datum = ws.Cells(j, "B").Value
121 Else
122 Exit For
123 End If
124SkipJ:
125 Next j
126
127 If eintraege.Count = 1 Then
128 Dim idx As Variant: idx = eintraege(1)
129 If IsDate(ws.Cells(idx, "C").Value) Then
130 startzeit = TimeValue(ws.Cells(idx, "C").Value)
131 Else
132 ws.Cells(idx, "M").Value = "übersprungen (ungültige Startzeit)"
133 GoTo Weiter
134 End If
135
136 If IsDate(ws.Cells(idx, "D").Value) Then
137 endzeit = TimeValue(ws.Cells(idx, "D").Value)
138 Else
139 ws.Cells(idx, "M").Value = "übersprungen (ungültige Endzeit)"
140 GoTo Weiter
141 End If
142 datum = DateValue(ws.Cells(idx, "B").Value)
143 If DRYRUN Then
144 ws.Cells(idx, "M").Value = "[Simulation] Einzel: " & titel
145 Else
146 Call OutlookEintragErstellen(selectedCalendar, gefilteteItems, datum, startzeit, endzeit, titel, ort, veranstaltungsnummer)
147 ws.Cells(idx, "M").Value = titel
148 End If
149 ws.Cells(idx, "N").Value = IIf(DRYRUN, "(Simulation)", selectedCalendar.Name)
150 erstelltCount = erstelltCount + 1
151 With ws.Cells(idx, "M").Interior: .Color = RGB(198, 239, 206): End With
152 Else
153 For Each idx In eintraege
154 datum = ws.Cells(idx, "B").Value
155 If Not DRYRUN Then
156 Call OutlookEintragLoeschen(gefilteteItems, datum, titel, logSheet, selectedCalendar.Name)
157 geloeschtCount = geloeschtCount + 1
158 End If
159 Next idx
160 If DRYRUN Then
161 For Each idx In eintraege
162 ws.Cells(idx, "M").Value = "[Simulation] Serie: " & titel
163 ws.Cells(idx, "N").Value = "(Simulation)"
164 serienCount = serienCount + 1
165 With ws.Cells(idx, "M").Interior: .Color = RGB(255, 235, 156): End With
166 Next idx
167 Else
168 Dim appt As Object
169 Set appt = selectedCalendar.Items.Add
170 With appt
171 .Start = ws.Cells(eintraege(1), "B").Value + ws.Cells(eintraege(1), "C").Value
172 .End = ws.Cells(eintraege(1), "B").Value + ws.Cells(eintraege(1), "D").Value
173 .Subject = titel
174 .Location = ort
175 .Body = "Veranstaltungsnummer: " & veranstaltungsnummer
176 .BusyStatus = 2
177 .ReminderSet = False
178 Dim pattern As Object
179 Set pattern = .GetRecurrencePattern
180 pattern.RecurrenceType = 0
181 pattern.Interval = 1
182 pattern.PatternStartDate = ws.Cells(eintraege(1), "B").Value
183 pattern.PatternEndDate = ws.Cells(eintraege(eintraege.Count), "B").Value
184 pattern.NoEndDate = False
185 .Save
186 End With
187 For Each idx In eintraege
188 ws.Cells(idx, "M").Value = "Serie: " & titel
189 ws.Cells(idx, "N").Value = selectedCalendar.Name
190 serienCount = serienCount + 1
191 With ws.Cells(idx, "M").Interior: .Color = RGB(255, 235, 156): End With
192 Next idx
193 End If
194 End If
195Weiter:
196 Next i
197
198 MsgBox "Fertig in " & Format(Timer - startTime, "0.00") & " Sekunden." & vbCrLf & _
199 erstelltCount & " Einzeltermine erstellt" & vbCrLf & _
200 serienCount & " Serien-Einträge erstellt" & vbCrLf & _
201 geloeschtCount & " alte Termine gelöscht" & vbCrLf & _
202 uebersprungenCount & " Zeilen übersprungen", vbInformation
203End Sub
204
205
206' Hilfsfunktion zum Erstellen eines Einzeltermins
207Sub OutlookEintragErstellen(ByVal selectedCalendar As Object, ByVal gefilteteItems As Object, ByVal datum As Date, ByVal startzeit As Date, ByVal endzeit As Date, ByVal titel As String, ByVal ort As String, ByVal veranstaltungsnummer As String)
208 Dim item As Object, existingItem As Object
209 Dim itemDate As Date
210 Dim bodyText As String
211
212 For Each existingItem In gefilteteItems
213 If existingItem.Class = 26 Then ' nur AppointmentItems
214 itemDate = Int(existingItem.Start)
215 If itemDate = datum Then
216 bodyText = "" & existingItem.Body
217 If InStr(bodyText, veranstaltungsnummer) > 0 Then
218 If existingItem.Subject <> titel Then
219 Dim msg As VbMsgBoxResult
220 msg = MsgBox("Ein Kalendereintrag mit derselben Veranstaltungsnummer existiert, aber der Titel unterscheidet sich:" & vbCrLf & _
221 "Bestehender Titel: " & existingItem.Subject & vbCrLf & _
222 "Neuer Titel: " & titel & vbCrLf & vbCrLf & _
223 "Trotzdem neuen Eintrag erstellen?", vbYesNo + vbExclamation, "Unstimmigkeit bei Titel")
224 If msg = vbNo Then Exit Sub
225 Else
226 Debug.Print "Duplikat gefunden für Datum: " & datum & ", Titel: " & titel
227 Exit Sub ' Duplikat mit gleichem Titel und Veranstaltungsnummer
228 End If
229 End If
230 Debug.Print "Übersprungen wegen vorhandenem Eintrag: " & datum & " - " & titel
231 Exit Sub
232 End If
233 End If
234 Next
235
236 Set item = selectedCalendar.Items.Add
237 With item
238 .Start = datum + startzeit
239 .End = datum + endzeit
240 .Subject = titel
241 .Location = ort
242 .Body = "Veranstaltungsnummer: " & veranstaltungsnummer
243 .BusyStatus = 2
244 .ReminderSet = False
245 .Save
246 End With
247End Sub
248
249
250' Hilfsfunktion zum Löschen vorhandener Einzeltermine mit gleichem Titel am gegebenen Datum
251Sub OutlookEintragLoeschen(ByVal gefilteteItems As Object, ByVal datum As Date, ByVal titel As String, ByVal logSheet As Worksheet, ByVal kalenderName As String)
252 Dim item As Object
253 Dim itemDate As Date
254 For Each item In gefilteteItems
255 If item.Class = 26 Then ' nur AppointmentItems
256 itemDate = Int(item.Start)
257 If itemDate = datum And item.Subject = titel Then
258 logSheet.Cells(logSheet.Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).Resize(1, 4).Value = _
259 Array(Format(item.Start, "dd.mm.yyyy"), Format(item.Start, "hh:nn"), titel, kalenderName)
260 item.Delete
261 Exit For
262 End If
263 End If
264 Next
265End Sub
266