Last active 1753356033

Revision 338bda07599ae688cabdaa4b12661a2e01399312

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 Set gefilterteItems = olItems.Restrict("[Start] >= '" & Format(Date, "ddddd h:nn AMPM") & "'")
59
60 On Error Resume Next
61 Set logSheet = ThisWorkbook.Sheets("Gelöschte Termine")
62 If logSheet Is Nothing Then
63 Set logSheet = ThisWorkbook.Sheets.Add
64 logSheet.Name = "Gelöschte Termine"
65 logSheet.Range("A1:D1").Value = Array("Datum", "Startzeit", "Titel", "Kalender")
66 End If
67 On Error GoTo 0
68 End If
69
70 Set ws = ThisWorkbook.Sheets(1)
71 lastRow = ws.Cells(ws.Rows.Count, "B").End(xlUp).Row
72 ReDim alreadyProcessed(1 To lastRow)
73
74 For i = 2 To lastRow
75 If alreadyProcessed(i) Then GoTo Weiter
76
77 If ws.Cells(i, "B").Value < Date Then
78 ws.Cells(i, "M").Value = "übersprungen (Vergangenheit)"
79 uebersprungenCount = uebersprungenCount + 1
80 GoTo Weiter
81 End If
82
83 If Not IsDate(ws.Cells(i, "B").Value) Or ws.Cells(i, "G").Value = "" Then
84 ws.Cells(i, "M").Value = "übersprungen (kein Datum/kein Produkt)"
85 uebersprungenCount = uebersprungenCount + 1
86 GoTo Weiter
87 End If
88
89 Set eintraege = New Collection
90 veranstaltungsnummer = Trim(ws.Cells(i, "F").Value)
91 produkt = Trim(ws.Cells(i, "G").Value)
92 hinweis = Trim(ws.Cells(i, "L").Value)
93 If InStr(hinweis, "Lehrgang: ") > 0 Then
94 hinweis = Mid(hinweis, InStr(hinweis, "Lehrgang: ") + 10)
95 End If
96 titel = produkt & " - " & hinweis
97 If Trim(titel) = "-" Or Trim(titel) = "- -" Or Trim(titel) = "" Then
98 ws.Cells(i, "M").Value = "übersprungen (leerer Titel)"
99 uebersprungenCount = uebersprungenCount + 1
100 GoTo Weiter
101 End If
102 ort = ws.Cells(i, "J").Value
103
104 datum = ws.Cells(i, "B").Value
105 eintraege.Add i
106 alreadyProcessed(i) = True
107
108 For j = i + 1 To lastRow
109 If alreadyProcessed(j) Then GoTo SkipJ
110 If Trim(ws.Cells(j, "F").Value) <> veranstaltungsnummer Then GoTo SkipJ
111 If ws.Cells(j, "G").Value = "" Then GoTo SkipJ
112 If Not IsDate(ws.Cells(j, "B").Value) Then GoTo SkipJ
113 If ws.Cells(j, "B").Value - datum = 1 Or _
114 (Weekday(datum, vbMonday) = 5 And ws.Cells(j, "B").Value - datum = 3) Then
115 eintraege.Add j
116 alreadyProcessed(j) = True
117 datum = ws.Cells(j, "B").Value
118 Else
119 Exit For
120 End If
121SkipJ:
122 Next j
123
124 If eintraege.Count = 1 Then
125 Dim idx As Variant: idx = eintraege(1)
126 startzeit = ws.Cells(idx, "C").Value
127 endzeit = ws.Cells(idx, "D").Value
128 datum = ws.Cells(idx, "B").Value
129 If DRYRUN Then
130 ws.Cells(idx, "M").Value = "[Simulation] Einzel: " & titel
131 Else
132 Call OutlookEintragErstellen(selectedCalendar, gefilteteItems, datum, startzeit, endzeit, titel, ort, veranstaltungsnummer)
133 ws.Cells(idx, "M").Value = titel
134 End If
135 ws.Cells(idx, "N").Value = IIf(DRYRUN, "(Simulation)", selectedCalendar.Name)
136 erstelltCount = erstelltCount + 1
137 With ws.Cells(idx, "M").Interior: .Color = RGB(198, 239, 206): End With
138 Else
139 For Each idx In eintraege
140 datum = ws.Cells(idx, "B").Value
141 If Not DRYRUN Then
142 Call OutlookEintragLoeschen(gefilteteItems, datum, titel, logSheet, selectedCalendar.Name)
143 geloeschtCount = geloeschtCount + 1
144 End If
145 Next idx
146 If DRYRUN Then
147 For Each idx In eintraege
148 ws.Cells(idx, "M").Value = "[Simulation] Serie: " & titel
149 ws.Cells(idx, "N").Value = "(Simulation)"
150 serienCount = serienCount + 1
151 With ws.Cells(idx, "M").Interior: .Color = RGB(255, 235, 156): End With
152 Next idx
153 Else
154 Dim appt As Object
155 Set appt = selectedCalendar.Items.Add
156 With appt
157 .Start = ws.Cells(eintraege(1), "B").Value + ws.Cells(eintraege(1), "C").Value
158 .End = ws.Cells(eintraege(1), "B").Value + ws.Cells(eintraege(1), "D").Value
159 .Subject = titel
160 .Location = ort
161 .Body = "Veranstaltungsnummer: " & veranstaltungsnummer
162 .BusyStatus = 2
163 .ReminderSet = False
164 Dim pattern As Object
165 Set pattern = .GetRecurrencePattern
166 pattern.RecurrenceType = 0
167 pattern.Interval = 1
168 pattern.PatternStartDate = ws.Cells(eintraege(1), "B").Value
169 pattern.PatternEndDate = ws.Cells(eintraege(eintraege.Count), "B").Value
170 pattern.NoEndDate = False
171 .Save
172 End With
173 For Each idx In eintraege
174 ws.Cells(idx, "M").Value = "Serie: " & titel
175 ws.Cells(idx, "N").Value = selectedCalendar.Name
176 serienCount = serienCount + 1
177 With ws.Cells(idx, "M").Interior: .Color = RGB(255, 235, 156): End With
178 Next idx
179 End If
180 End If
181Weiter:
182 Next i
183
184 MsgBox "Fertig in " & Format(Timer - startTime, "0.00") & " Sekunden." & vbCrLf & _
185 erstelltCount & " Einzeltermine erstellt" & vbCrLf & _
186 serienCount & " Serien-Einträge erstellt" & vbCrLf & _
187 geloeschtCount & " alte Termine gelöscht" & vbCrLf & _
188 uebersprungenCount & " Zeilen übersprungen", vbInformation
189End Sub
190
191
192' Hilfsfunktion zum Erstellen eines Einzeltermins
193Sub 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)
194 Dim item As Object, existingItem As Object
195 Dim itemDate As Date
196 Dim bodyText As String
197
198 For Each existingItem In gefilteteItems
199 If existingItem.Class = 26 Then ' nur AppointmentItems
200 itemDate = Int(existingItem.Start)
201 If itemDate = datum Then
202 bodyText = "" & existingItem.Body
203 If InStr(bodyText, veranstaltungsnummer) > 0 Then
204 If existingItem.Subject <> titel Then
205 Dim msg As VbMsgBoxResult
206 msg = MsgBox("Ein Kalendereintrag mit derselben Veranstaltungsnummer existiert, aber der Titel unterscheidet sich:" & vbCrLf & _
207 "Bestehender Titel: " & existingItem.Subject & vbCrLf & _
208 "Neuer Titel: " & titel & vbCrLf & vbCrLf & _
209 "Trotzdem neuen Eintrag erstellen?", vbYesNo + vbExclamation, "Unstimmigkeit bei Titel")
210 If msg = vbNo Then Exit Sub
211 Else
212 Exit Sub ' Duplikat mit gleichem Titel und Veranstaltungsnummer
213 End If
214 End If
215 ' Duplikat erkannt
216 Exit Sub
217 End If
218 End If
219 Next
220
221 Set item = selectedCalendar.Items.Add
222 With item
223 .Start = datum + startzeit
224 .End = datum + endzeit
225 .Subject = titel
226 .Location = ort
227 .Body = "Veranstaltungsnummer: " & veranstaltungsnummer
228 .BusyStatus = 2
229 .ReminderSet = False
230 .Save
231 End With
232End Sub
233
234
235' Hilfsfunktion zum Löschen vorhandener Einzeltermine mit gleichem Titel am gegebenen Datum
236Sub OutlookEintragLoeschen(ByVal gefilteteItems As Object, ByVal datum As Date, ByVal titel As String, ByVal logSheet As Worksheet, ByVal kalenderName As String)
237 Dim item As Object
238 Dim itemDate As Date
239 For Each item In gefilteteItems
240 If item.Class = 26 Then ' nur AppointmentItems
241 itemDate = Int(item.Start)
242 If itemDate = datum And item.Subject = titel Then
243 logSheet.Cells(logSheet.Cells(Rows.Count, 1).End(xlUp).Row + 1, 1).Resize(1, 4).Value = _
244 Array(Format(item.Start, "dd.mm.yyyy"), Format(item.Start, "hh:nn"), titel, kalenderName)
245 item.Delete
246 Exit For
247 End If
248 End If
249 Next
250End Sub
251