Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1928to1932
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

iCal bzw. ics Datei erstellen.

iCal bzw. ics Datei erstellen.
19.04.2023 19:14:06
Pappawinni

Ich war auf der Suche nach einer Lösung, um Dateien vom Typ iCalendar zu erzeugen.
Hintergrund war, dass in einem Verein Terminlisten verschickt wurden, die dann jeder vielleicht händisch in seinen Kalender übertragen hat.
Ich dachte, dass es sinnvoll sein könnte, das gleich als Kalenderdatei zu verschicken, damit die Leute das, sofern sie das denn wollen in ihren Kalender einfach importieren können.
Ich bin nun bei meiner Suche nach Lösungen auf einen Beitrag im Archiv gestoßen:
https://www.herber.de/forum/archiv/1224to1228/1225493_iCal_Datei_aus_Excel_erstellen_Kalender_ics.html
was schon etwas hilft, aber doch diverse Schwächen hat.
Primär sollte die Datei UTF-8 sein, was sie nicht ist.
Dann ist es offenbar so, dass da pro Termin eine UID aus dem aktuellem Datum und der Zeit generiert wird, was insofern ungünstig ist,
als man eine Änderung an einem Termin nur mit einer bekannten UID vornehmen kann.
Ich habe also ein Tabellenblatt angelegt, das in der 2ten Zeile nacheinander folgende Titel ausweist:
UID, Datum, Beginn, Ende, Titel, Ort, Beschreibung
In Zeile 1, Spalte 2 hab ich den Dateinamen mit Pfad und dazu folgendes in VBA:


Option Explicit

Sub ICS_Erstellen()

'Erstellt den Zeitstempel für den aktuellen Zeitpunkt
Dim strTimeStamp As String

strTimeStamp = getTimeStamp(Now, Now)

'Erstellt den Inhalt der Kalenderdatei

Dim sText As String

sText = ""
'Schreibt den allgemeinen Teil der Kalenderdatei in Variable sText
sText = sText & "BEGIN:VCALENDAR" & vbCrLf
sText = sText & "VERSION:2.0" & vbCrLf
sText = sText & "PRODID:MV_Schwebheim" & vbCrLf
sText = sText & "METHOD:PUBLISH" & vbCrLf

Dim iLine As Integer
Dim strStartStamp As String
Dim strEndStamp As String
Dim strTitle As String
Dim strPlace As String
Dim strDesc As String
Dim strID As String

'Schleife zur Ermittlung aller Einträge
'Benutzt alle Datensätze, die ein Datum enthalten

iLine = 3

While ThisWorkbook.Sheets(1).Cells(iLine, 2).Value > ""

strID = ThisWorkbook.Sheets(1).Cells(iLine, 1).Value
strStartStamp = getTimeStamp(ThisWorkbook.Sheets(1).Cells(iLine, 2).Value, ThisWorkbook.Sheets(1).Cells(iLine, 3).Value)
strEndStamp = getTimeStamp(ThisWorkbook.Sheets(1).Cells(iLine, 2).Value, ThisWorkbook.Sheets(1).Cells(iLine, 4).Value)
strTitle = ThisWorkbook.Sheets(1).Cells(iLine, 5).Value
strPlace = ThisWorkbook.Sheets(1).Cells(iLine, 6).Value
strDesc = ThisWorkbook.Sheets(1).Cells(iLine, 7).Value

'Ergänzt einen Kalendereintrag

sText = sText & "BEGIN:VEVENT" & vbCrLf
sText = sText & "UID:" & strID & vbCrLf
sText = sText & "CLASS:PUBLIC" & vbCrLf
sText = sText & "SUMMARY:" & strTitle & vbCrLf
sText = sText & "DESCRIPTION:" & strDesc & vbCrLf
sText = sText & "LOCATION:" & strPlace & vbCrLf
sText = sText & "DTSTART;TZID=Europe/Berlin:" & strStartStamp & vbCrLf
sText = sText & "DTEND;TZID=Europe/Berlin:" & strEndStamp & vbCrLf
sText = sText & "DTSTAMP:" & strTimeStamp & vbCrLf
sText = sText & "LAST-MODIFIED:" & strTimeStamp & vbCrLf
sText = sText & "BEGIN:VALARM" & vbCrLf
sText = sText & "TRIGGER;VALUE=DURATION:-PT30M" & vbCrLf
sText = sText & "REPEAT:2" & vbCrLf
sText = sText & "DURATION:PT5M" & vbCrLf
sText = sText & "ACTION:DISPLAY" & vbCrLf
sText = sText & "DESCRIPTION: Termin " & strTitle & vbCrLf
sText = sText & "END:VALARM" & vbCrLf
sText = sText & "END:VEVENT" & vbCrLf

iLine = iLine + 1

Wend
'Ende der Schleife
sText = sText & "END:VCALENDAR"
'Ende der Kalenderdatei

'sText nach UTF streamen
Dim adodbStreamUTF
Dim adodbStreamBIN
Set adodbStreamUTF = CreateObject("ADODB.Stream")
Set adodbStreamBIN = CreateObject("ADODB.Stream")

With adodbStreamUTF
 .Type = 2 'Text Type
 .Charset = "UTF-8"
 .Open
 .WriteText sText 'Text schreiben
 .flush
End With

'UTF Stream als Binary schreiben (ohne Byte Order Mark)
With adodbStreamBIN
 .Type = 1 'Binary Type
 .Open
 adodbStreamUTF.Position = 3 'nach BOM
 adodbStreamUTF.copyto adodbStreamBIN
 .SaveToFile ThisWorkbook.Sheets(1).Cells(1, 2).Value, 2 'Datei speichern, ggf. neu erzeugen
 .Close
End With

adodbStreamUTF.Close


MsgBox "Datei geschrieben"

End Sub

Function getTimeStamp(Datum As Date, Zeit As Date) As String

Dim strTimeStamp

strTimeStamp = Right("0000" & Year(Datum), 4)
strTimeStamp = strTimeStamp & Right("00" & Month(Datum), 2)
strTimeStamp = strTimeStamp & Right("00" & Day(Datum), 2)
strTimeStamp = strTimeStamp & "T"
strTimeStamp = strTimeStamp & Right("00" & Hour(Zeit), 2)
strTimeStamp = strTimeStamp & Right("00" & Minute(Zeit), 2)
strTimeStamp = strTimeStamp & Right("00" & Second(Zeit), 2)
strTimeStamp = strTimeStamp & "Z"

getTimeStamp = strTimeStamp

End Function



Das erfüllt jetzt schon mal grob den Zweck.
Vielleicht hat aber jemand auch noch eine Idee, wie man den Terminen eine Kategorie oder Farbe zuordnen kann?
Ich habe hier eingebaut, dass grundsätzlich eine halbe Stunde vor Termin noch ne Meldung kommt , die dann noch 2 mal jeweils nach 5 Minuten wiederholt wird.
Das denke ich jedenfalls.
Vielleicht hat da jemand auch da noch eine Idee, wie man das etwas flexibler lösen kann.
Ein Hinweis auf eine ausführliche Beschreibung zu .iCalendar Dateien würde mich evtl. auch schon weiter bringen.
Danke

21
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: iCal bzw. ics Datei erstellen.
19.04.2023 21:45:06
Yal
Moin Papawinni,

das ist ja immer die Frage, wenn etwas schon funktioniert und verständlich ist, ob man etwas dazu noch beitragen kann.

Folgende Code ist nur Spielerei, da keine wesentliche Änderungen. Der Umweg über einen Array macht den Code ein bisschen leichter. Mein Ziel war soviel Variable wie möglich zu sparen.

Const cID = 1
Const cDatum = 2
Const cStart = 3
Const cEnde = 4
Const cTitle = 5
Const cPlace = 6
Const cDesc = 7

Sub ICS_Erstellen()
Dim P
Dim ics()
Dim ub As Long
Dim iLine As Long
Dim StreamBIN

'Schreibt den allgemeinen Teil der Kalenderdatei in Variable sText
    ReDim ics(3)
    ics(0) = "BEGIN:VCALENDAR"
    ics(1) = "VERSION:2.0"
    ics(2) = "PRODID:MV_Schwebheim"
    ics(3) = "METHOD:PUBLISH"
'Schleife zur Ermittlung aller Einträge
'Benutzt alle Datensätze, die ein Datum enthalten
    iLine = 3
    With ThisWorkbook.Sheets(1)
        While .Cells(iLine, 2).Value > ""
        'Ergänzt einen Kalendereintrag
            P = Application.Transpose(Application.Transpose(.Cells(iLine, 1).Resize(1, 7)))
            ub = UBound(ics)
            ReDim Preserve ics(ub + 18)
            ics(ub + 1) = "BEGIN:VEVENT"
            ics(ub + 2) = "UID:" & P(cID)
            ics(ub + 3) = "CLASS:PUBLIC"
            ics(ub + 4) = "SUMMARY:" & P(cTitle)
            ics(ub + 5) = "DESCRIPTION:" & P(cDesc)
            ics(ub + 6) = "LOCATION:" & P(cPlace)
            ics(ub + 7) = "DTSTART;TZID=Europe/Berlin:" & Format(P(cDatum), "YYYYMMDDT") & Format(P(cStart), "hhmmssZ")
            ics(ub + 8) = "DTEND;TZID=Europe/Berlin:" & Format(P(cDatum), "YYYYMMDDT") & Format(P(cEnde), "hhmmssZ")
            ics(ub + 9) = "DTSTAMP:" & Format(Now, "YYYYMMDDThhmmssZ")
            ics(ub + 10) = "LAST-MODIFIED:" & Format(Now, "YYYYMMDDThhmmssZ")
            ics(ub + 11) = "BEGIN:VALARM"
            ics(ub + 12) = "TRIGGER;VALUE=DURATION:-PT30M"
            ics(ub + 13) = "REPEAT:2"
            ics(ub + 14) = "DURATION:PT5M"
            ics(ub + 15) = "ACTION:DISPLAY"
            ics(ub + 16) = "DESCRIPTION: Termin " & P(cTitle)
            ics(ub + 17) = "END:VALARM"
            ics(ub + 18) = "END:VEVENT"
            iLine = iLine + 1
        Loop
    End With
'Ende der Schleife
    ReDim Preserve ics(UBound(ics) + 1)
    ics(UBound(ics)) = "END:VCALENDAR"
'Ende der Kalenderdatei

'ics nach UTF dann nach BIN streamen
    Set StreamBIN = CreateObject("ADODB.Stream")
    With StreamBIN
        .Type = 1 'Binary Type
        .Open
        With CreateObject("ADODB.Stream") 'UTF Stream
            .Type = 2 'Text Type
            .Charset = "UTF-8"
            .Open
            .WriteText Join(ics, vbCrLf)  'Text schreiben
            .flush
            .Position = 3 'nach BOM
            .copyto StreamBIN
            .Close
        End With
        .SaveToFile ThisWorkbook.Sheets(1).Cells(1, 2).Value, 2 'Datei speichern, ggf. neu erzeugen
        .Close
    End With
    MsgBox "Datei geschrieben"
End Sub
(ungetestet)

Wenn Du schon die Zeit in Zulu-Form eingibst, müsstest Du eine Timezone und Daylight eingabe machen. Siehe https://de.wikipedia.org/wiki/ICalendar

VG
Yal


Anzeige
AW: iCal bzw. ics Datei erstellen.
19.04.2023 22:57:10
Pappawinni
Danke für deine Mühe,
Das Format() werd ich wohl einbauen, array eher nicht, bringt IMHO nix.
Ja und ich bin auch inzwischen darauf gestoßen, dass ich
- VTIMEZONE nicht weglassen darf
- bei local time der Zeitstempel ohne das Z am Ende sein muss...
Hab den Output mal mit
https://icalendar.org/validator.html
geprüft und das ist jetzt im grünen Bereich.
Ich werde mich wohl mal durch die Seiten da durchquälen müssen, wenn ich weiter kommen will.
Make it nice kommt eigentlich erst am Ende, auch nur, wenn's nix kost


Anzeige
AW: iCal bzw. ics Datei erstellen.
20.04.2023 18:14:13
Pappawinni
probier es damit


Option Explicit

Const cID = 1
Const cDatum = 2
Const cStart = 3
Const cEnde = 4
Const cTitle = 5
Const cPlace = 6
Const cDesc = 7

Sub ICS_Erstellen()

'Erstellt den Zeitstempel für den aktuellen Zeitpunkt
Dim strTimeStamp As String

strTimeStamp = Format(Now, "YYYYMMDDThhmmssZ")

'Erstellt den Inhalt der Kalenderdatei

Dim sText As String

sText = ""
'Schreibt den allgemeinen Teil der Kalenderdatei in Variable sText
sText = sText & "BEGIN:VCALENDAR" & vbCrLf
sText = sText & "VERSION:2.0" & vbCrLf
sText = sText & "PRODID: VEREIN XY" & vbCrLf
sText = sText & "METHOD:PUBLISH" & vbCrLf
sText = sText & "BEGIN:VTIMEZONE" & vbCrLf
sText = sText & "TZID:Europe/Berlin" & vbCrLf
sText = sText & "X-LIC-LOCATION:Europe/Berlin" & vbCrLf
sText = sText & "BEGIN:DAYLIGHT" & vbCrLf
sText = sText & "TZOFFSETFROM:+0100" & vbCrLf
sText = sText & "TZOFFSETTO:+0200" & vbCrLf
sText = sText & "TZNAME:CEST" & vbCrLf
sText = sText & "DTSTART:19700329T020000" & vbCrLf
sText = sText & "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3" & vbCrLf
sText = sText & "END:DAYLIGHT" & vbCrLf
sText = sText & "BEGIN:STANDARD" & vbCrLf
sText = sText & "TZOFFSETFROM:+0200" & vbCrLf
sText = sText & "TZOFFSETTO:+0100" & vbCrLf
sText = sText & "TZNAME:CET" & vbCrLf
sText = sText & "DTSTART:19701025T030000" & vbCrLf
sText = sText & "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10" & vbCrLf
sText = sText & "END:STANDARD" & vbCrLf
sText = sText & "END:VTIMEZONE" & vbCrLf


Dim iLine As Integer
Dim strStartStamp As String
Dim strEndStamp As String
Dim strTitle As String
Dim strPlace As String
Dim strDesc As String
Dim strID As String

'Schleife zur Ermittlung aller Einträge
'Benutzt alle Datensätze, die ein Datum enthalten

iLine = 3
Dim p() As Variant

While ThisWorkbook.Sheets(1).Cells(iLine, 2).Value > ""

 With ThisWorkbook.Sheets(1)
  p = WorksheetFunction.Transpose(Range(.Cells(iLine, 1), .Cells(iLine, 7)).Value)
 End With

 'Ergänzt einen Kalendereintrag
 sText = sText & "BEGIN:VEVENT" & vbCrLf
 sText = sText & "UID:" & p(cID, 1) & vbCrLf
 sText = sText & "CLASS:PUBLIC" & vbCrLf
 sText = sText & "SUMMARY:" & p(cTitle, 1) & vbCrLf
 sText = sText & "DESCRIPTION:" & p(cDesc, 1) & vbCrLf
 sText = sText & "LOCATION:" & p(cPlace, 1) & vbCrLf
 sText = sText & "DTSTART;TZID=Europe/Berlin:" & Format(p(cDatum, 1), "YYYYMMDDT") & Format(p(cStart, 1), "hhmmss") & vbCrLf
 sText = sText & "DTEND;TZID=Europe/Berlin:" & Format(p(cDatum, 1), "YYYYMMDDT") & Format(p(cEnde, 1), "hhmmss") & vbCrLf
 sText = sText & "DTSTAMP:" & strTimeStamp & vbCrLf
 sText = sText & "LAST-MODIFIED:" & strTimeStamp & vbCrLf
 sText = sText & "BEGIN:VALARM" & vbCrLf
 sText = sText & "TRIGGER;VALUE=DURATION:-PT30M" & vbCrLf
 sText = sText & "REPEAT:2" & vbCrLf
 sText = sText & "DURATION:PT5M" & vbCrLf
 sText = sText & "ACTION:DISPLAY" & vbCrLf
 sText = sText & "DESCRIPTION: Termin " & strTitle & vbCrLf
 sText = sText & "END:VALARM" & vbCrLf
 sText = sText & "END:VEVENT" & vbCrLf

 iLine = iLine + 1

Wend
'Ende der Schleife
sText = sText & "END:VCALENDAR"
'Ende der Kalenderdatei

Dim adodbStreamUTF
Dim adodbStreamBIN
Set adodbStreamUTF = CreateObject("ADODB.Stream")
Set adodbStreamBIN = CreateObject("ADODB.Stream")

'ics nach UTF und dann als Binary schreiben (ohne Byte Order Mark)

With adodbStreamBIN
 .Type = 1 'Binary Type
 .Open
 With adodbStreamUTF
  .Type = 2 'Text Type
  .Charset = "UTF-8"
  .Open
  .WriteText sText 'Text schreiben
  .flush
  .Position = 3 'nach BOM
  .copyto adodbStreamBIN
  .Close
 End With
 .SaveToFile ThisWorkbook.Sheets(1).Cells(1, 2).Value, 2 'Datei speichern, ggf. neu erzeugen
 .Close
End With

MsgBox "Datei geschrieben"

End Sub



Anzeige
AW: iCal bzw. ics Datei erstellen.
20.04.2023 14:48:12
Wolfgang
Hallo,
nun hat mich dieses Thema auch mal interessiert und versuchte so eine Tabelle nachzubilden.
Das hat so einigermaßen geklappt, aber das Ergebnis in Outlook war nicht das Wahre. Der erste Versuch mit dem Makro von papawinni brachte die Meldung in Outlook, dass die Zeiten (Anfang und Ende) nicht sio erkannt wurden, wie sie in der Tabelle standen und dann die Terminüberscheidnung passte auch nicht.
Siehe Bild: Userbild

Dann wollte ich das Makro von Yal einfügen und dann kam der Fehler, denn ich nicht nachvollziehen kann. Siehe Bild: Userbild

Da ich nicht so perfekt mit dem VBA bin (ausser Makrorecorder), habe ich keine Ahnung wie ich da eine Lösung bekomme.

Wolfgang


Anzeige
AW: iCal bzw. ics Datei erstellen.
20.04.2023 16:12:52
Pappawinni
Kleines Problem
While -> Wend
Do -> Loop
D.h. ersetze Loop durch Wend


AW: iCal bzw. ics Datei erstellen.
20.04.2023 18:06:57
Wolfgang
Hallo Pappawinni,
danke für den Hinweis. Wurde geändert, aber ...
Userbild

Wolfgang


AW: iCal bzw. ics Datei erstellen.
20.04.2023 18:40:09
Wolfgang
Hallo Pappawinni,
also, das war nun doch ein Fehler von mir, es ist scheinbar die Leertaste aus Versehen gedrückt worden und dadruch wurde ein Leerzeichen erstellt und das Makro produdzierte den Fehler.
Was mich aber trotzdem wundert, es sind zwar in meinen Testeingaben zwei total verschieden Termine eingetragen, aber im Outlook werden andere Zeiten angegeben und die Meldung mit den Terminüberschneidungen.
Irgendwie komisch...
Habe es mit beiden Makros so bekommen, siehe Bsp-Datei: https://www.herber.de/bbs/user/158811.xlsb

Wolfgang


Anzeige
AW: iCal bzw. ics Datei erstellen.
20.04.2023 18:57:36
Pappawinni
Ich hatte noch ne neue Version gepostet, leider ist die aber an die Falsche stelle gegangen.
Es braucht, das hatte ich schon geschrieben, noch etwas im Header, damit das funktioniert.
Schau mal...


AW: iCal bzw. ics Datei erstellen.
20.04.2023 21:23:48
Pappawinni
Du solltest bei UID natürlich etwas rein schreiben, das den Termin eindeutig identifiziert,
damit erreichst du, dass Termine aktualisieren kannst.
Ich hab da einfach einen Datumstempel und ne laufende Nummer dahinter, also etwas in der Art:
20230425TWINNI001
20230425TWINNI002
usw.
Ohne die UID müsstest du schon vorhandene Termine löschen und dann wieder neu laden.


Anzeige
AW: iCal bzw. ics Datei erstellen.
20.04.2023 22:49:42
Pappawinni
Ich hab da noch n kleines Problemchen entdeckt, also für dich noch diese Version.
Jetzt will ich mich aber mal um Erweiterung kümmern.


Option Explicit

Const cID = 1
Const cDatum = 2
Const cStart = 3
Const cEnde = 4
Const cTitle = 5
Const cPlace = 6
Const cDesc = 7

Sub ICS_Erstellen()

'Erstellt den Zeitstempel für den aktuellen Zeitpunkt
Dim strTimeStamp As String

strTimeStamp = Format(Now, "YYYYMMDDThhmmssZ")

'Erstellt den Inhalt der Kalenderdatei

Dim sText As String

sText = ""
'Schreibt den allgemeinen Teil der Kalenderdatei in Variable sText
sText = sText & "BEGIN:VCALENDAR" & vbCrLf
sText = sText & "VERSION:2.0" & vbCrLf
sText = sText & "PRODID:MV_Schwebheim" & vbCrLf
sText = sText & "METHOD:PUBLISH" & vbCrLf
sText = sText & "BEGIN:VTIMEZONE" & vbCrLf
sText = sText & "TZID:Europe/Berlin" & vbCrLf
sText = sText & "X-LIC-LOCATION:Europe/Berlin" & vbCrLf
sText = sText & "BEGIN:DAYLIGHT" & vbCrLf
sText = sText & "TZOFFSETFROM:+0100" & vbCrLf
sText = sText & "TZOFFSETTO:+0200" & vbCrLf
sText = sText & "TZNAME:CEST" & vbCrLf
sText = sText & "DTSTART:19700329T020000" & vbCrLf
sText = sText & "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3" & vbCrLf
sText = sText & "END:DAYLIGHT" & vbCrLf
sText = sText & "BEGIN:STANDARD" & vbCrLf
sText = sText & "TZOFFSETFROM:+0200" & vbCrLf
sText = sText & "TZOFFSETTO:+0100" & vbCrLf
sText = sText & "TZNAME:CET" & vbCrLf
sText = sText & "DTSTART:19701025T030000" & vbCrLf
sText = sText & "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10" & vbCrLf
sText = sText & "END:STANDARD" & vbCrLf
sText = sText & "END:VTIMEZONE" & vbCrLf

'Schleife zur Ermittlung aller Einträge
'Benutzt alle Datensätze, die ein Datum enthalten
Dim iLine As Integer
Dim p() As Variant

iLine = 3

While ThisWorkbook.Sheets(1).Cells(iLine, 2).Value > ""

 With ThisWorkbook.Sheets(1)
  p = WorksheetFunction.Transpose(WorksheetFunction.Transpose(Range(.Cells(iLine, 1), .Cells(iLine, 7)).Value))
 End With

 'Ergänzt einen Kalendereintrag
 sText = sText & "BEGIN:VEVENT" & vbCrLf
 sText = sText & "UID:" & p(cID) & vbCrLf
 sText = sText & "CLASS:PUBLIC" & vbCrLf
 sText = sText & "SUMMARY:" & p(cTitle) & vbCrLf
 sText = sText & "DESCRIPTION:" & p(cDesc) & vbCrLf
 sText = sText & "LOCATION:" & p(cPlace) & vbCrLf
 sText = sText & "DTSTART;TZID=Europe/Berlin:" & Format(p(cDatum), "YYYYMMDDT") & Format(p(cStart), "hhmmss") & vbCrLf
 sText = sText & "DTEND;TZID=Europe/Berlin:" & Format(p(cDatum), "YYYYMMDDT") & Format(p(cEnde), "hhmmss") & vbCrLf
 sText = sText & "DTSTAMP:" & strTimeStamp & vbCrLf
 sText = sText & "LAST-MODIFIED:" & strTimeStamp & vbCrLf
 sText = sText & "BEGIN:VALARM" & vbCrLf
 sText = sText & "TRIGGER;VALUE=DURATION:-PT30M" & vbCrLf
 sText = sText & "REPEAT:2" & vbCrLf
 sText = sText & "DURATION:PT5M" & vbCrLf
 sText = sText & "ACTION:DISPLAY" & vbCrLf
 sText = sText & "DESCRIPTION: Termin " & p(cTitle) & vbCrLf
 sText = sText & "END:VALARM" & vbCrLf
 sText = sText & "END:VEVENT" & vbCrLf

 iLine = iLine + 1

Wend
'Ende der Schleife
sText = sText & "END:VCALENDAR"
'Ende der Kalenderdatei

Dim adodbStreamUTF
Dim adodbStreamBIN
Set adodbStreamUTF = CreateObject("ADODB.Stream")
Set adodbStreamBIN = CreateObject("ADODB.Stream")

'ics nach UTF und dann als Binary schreiben (ohne Byte Order Mark)

With adodbStreamBIN
 .Type = 1 'Binary Type
 .Open
 With adodbStreamUTF
  .Type = 2 'Text Type
  .Charset = "UTF-8"
  .Open
  .WriteText sText 'Text schreiben
  .flush
  .Position = 3 'nach BOM
  .copyto adodbStreamBIN
  .Close
 End With
 .SaveToFile ThisWorkbook.Sheets(1).Cells(1, 2).Value, 2 'Datei speichern, ggf. neu erzeugen
 .Close
End With

MsgBox "Datei geschrieben"

End Sub




Anzeige
AW: iCal bzw. ics Datei erstellen.
21.04.2023 08:49:33
Wolfgang
Hallo Pappawinni,
danke für die nochmalige Hilfe bzw. Makro. So wie es im Moment ist, klappt alles wunderbar.
Eine Frage habe ich noch: Wenn ein Termin mehr als ein Tag, z.B. 3 Tage oder 1 Woche gehen soll, wo muss das End-Datum eingetragen werden oder kann man einen sog, "Tageszähler" mit Zahlen "füttern", damit das End-Datum berechnet wird?
Vielleicht hast Du einen Tipp?

Wolfgang


AW: iCal bzw. ics Datei erstellen.
21.04.2023 09:34:04
Pappawinni
Naja, ich hab das Ding so gebaut, weil ich in aller Regel nur Termine habe, die nicht über einen Tag hinaus gehen.
Sollte ausnahmsweise mal ein Termin mehrtätig sein, bräuchte es wahrscheinlich ohnehin eine größere Vorwarnzeit.
Egal, wenn du den Endtermin an einem anderen Tag haben willst, könntest du eine weiter Spalte für das Enddatum einführen.
Dann brauchst du aber eine weitere Konstante: z.B. wenn deine Spalten dann
UID, Anfangsdatum, Anfangszeit, Enddatum, Endzeit usw. sind.:

Const cID = 1
Const cDatum = 2
Const cStart = 3
Const cDatum2 = 4
Const cEnde = 5
usw.
Bedeutet, dass du auch den Range der in das Array p geladen wird erweitern musst
p= ..... ,.Cells(iLine,8)...
und dann baust du DTEND nicht aus p(cDatum) und p(cEnde) zusammen, sondern aus p(cDatum2) und p(cEnde)
Wenn das nicht schön genug ist, kannst du deine Konstanten dann auch anders nennen.

Du schaffst das...


Anzeige
AW: iCal bzw. ics Datei erstellen.
24.04.2023 14:43:19
Pappawinni
Nachdem ich bei den meissten Posts vergessen habe, "Frage noch offen" zu markieren, war nicht zu erwarten, dass da noch etwas neues kommt.
Mein aktueller Stand ist nun, dass ich nun im ersten Arbeitsblatt

in Zeile 1, Spalte 2 den Dateipfad habe,
in Zeile 2, Spalte 2 den Dateinamen
in Zeile 3, Spalte 2 den Ersteller

In Zeile 5 ab Spalte 1 die Titel
ID, Datum Beginn, Zeit Beginn, Datum Ende, Zeit Ende, Status, Titel, Ort, Beschreibung

die ID fülle ich mit einem Datumsstempel, und einer fortlaufenden Nummer, um den Eintrag eindeutig zu kennzeichnen, z.B. 20230424TWINNI23001,
Datum und Zeit dürfte klar sein,

Bei Status sind nur die Werte TENTATIVE, CONFIRMED und CANCELLED zulässig
google Kalender macht zwischen TENTATIVE und CONFIRMED offenbar keinen Unterschied, aber wenn ich einmal einen Termin angelegt habe,
dann kann ich den löschen indem ich den als CANCELLED markiere. Das geht halt nur mit Terminen, für die ich die ID kenne.

Bei Beschreibung kann \n oder \N in den Text geschrieben werden, um im Kalendereintrag einen Zeilenvorschub zu erzeugen.
Bei Texten wird den Zeichen ,;: , sofern nicht vorhanden, durch das Makro ein \ vorangestellt, ansonsten werden \ eliminiert.

Hier das Makro dazu


Option Explicit

Const cID = 1
Const cDateStart = 2
Const cTimeStart = 3
Const cDateEnd = 4
Const cTimeEnd = 5
Const cStatus = 6
Const cTitle = 7
Const cPlace = 8
Const cDesc = 9

Sub ICS_Erstellen()

Dim strTimeStamp As String
Dim strFilePath As String
Dim strFileName As String
Dim strCreator As String
Dim iExt As Integer

On Error GoTo Fehler

'Liest Dateipfad mit Dateiname aus der Tabelle prüft sie und setzt sie zusammen
strFilePath = Trim(ThisWorkbook.Sheets(1).Cells(1, 2).Value)
strFilePath = strFilePath & IIf(Right(strFilePath, 1) = "\", "", "\")
If Not (IsValidFileNameOrPath(strFilePath)) Then
  MsgBox "Dateipfad enthält ungültige Zeichen oder fehlt"
  Exit Sub
End If
If Dir(strFilePath, vbDirectory) = "" Then
  MsgBox "Dateipfad existiert nicht"
  Exit Sub
End If
strFileName = Trim(ThisWorkbook.Sheets(1).Cells(2, 2).Value)
If Not (IsValidFileNameOrPath(strFileName, False)) Then
  MsgBox "Dateiname enthält ungültige Zeichen oder fehlt"
  Exit Sub
End If
iExt = InStrRev(strFileName, ".")
If iExt = 0 Then
  strFileName = strFileName & ".ics"
Else
  If (InStr(".ical> .ics>  .ifb>  .icalendar>", "" & (LCase(Right(strFileName, Len(strFileName) - iExt + 1))) & ">") Mod 8) > 1 Then
    MsgBox "Nur Dateien .cal .ics .ifb .icalendar zulässig"
    Exit Sub
  End If
End If

strFilePath = strFilePath & strFileName

'Liest die ProdId aus dem Tabellenblatt Zeile 3, Spalte 2
strCreator = getIcalText(ThisWorkbook.Sheets(1).Cells(3, 2).Value)

'Erstellt den Zeitstempel für den aktuellen Zeitpunkt
strTimeStamp = Format(Now, "YYYYMMDDThhmmssZ")

'Erstellt den Inhalt der Kalenderdatei

Dim sText As String

sText = ""
'Schreibt den allgemeinen Teil der Kalenderdatei in Variable sText
sText = sText & "BEGIN:VCALENDAR" & vbCrLf
sText = sText & "VERSION:2.0" & vbCrLf
sText = sText & "PRODID:" & strCreator & vbCrLf
sText = sText & "METHOD:PUBLISH" & vbCrLf
sText = sText & "BEGIN:VTIMEZONE" & vbCrLf
sText = sText & "TZID:Europe/Berlin" & vbCrLf
sText = sText & "X-LIC-LOCATION:Europe/Berlin" & vbCrLf
sText = sText & "BEGIN:DAYLIGHT" & vbCrLf
sText = sText & "TZOFFSETFROM:+0100" & vbCrLf
sText = sText & "TZOFFSETTO:+0200" & vbCrLf
sText = sText & "TZNAME:CEST" & vbCrLf
sText = sText & "DTSTART:19700329T020000" & vbCrLf
sText = sText & "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3" & vbCrLf
sText = sText & "END:DAYLIGHT" & vbCrLf
sText = sText & "BEGIN:STANDARD" & vbCrLf
sText = sText & "TZOFFSETFROM:+0200" & vbCrLf
sText = sText & "TZOFFSETTO:+0100" & vbCrLf
sText = sText & "TZNAME:CET" & vbCrLf
sText = sText & "DTSTART:19701025T030000" & vbCrLf
sText = sText & "RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10" & vbCrLf
sText = sText & "END:STANDARD" & vbCrLf
sText = sText & "END:VTIMEZONE" & vbCrLf

'Schleife zur Ermittlung aller Einträge
'Benutzt alle Datensätze, die ein Startdatum enthalten
Dim iLine As Integer
Dim p() As Variant
Dim strStatus As String
Dim strDesc As String

iLine = 6 'Erste Datenzeile im Tabellenblatt

With ThisWorkbook.Sheets(1)
 p = WorksheetFunction.Transpose(WorksheetFunction.Transpose(Range(.Cells(iLine, 1), .Cells(iLine, 9)).Value))
End With

While p(cDateStart) > ""
 
 p(cStatus) = UCase(p(cStatus))
 strDesc = getIcalText(p(cDesc), True)
 'Ergänzt einen Kalendereintrag
 
 sText = sText & "BEGIN:VEVENT" & vbCrLf
 sText = sText & "UID:" & p(cID) & vbCrLf
 sText = sText & "CLASS:PUBLIC" & vbCrLf
 'Status nur bei gültigem Wert schreiben
 If InStr("  ", "" & p(cStatus) & ">") Mod 12 = 1 Then
   sText = sText & "STATUS:" & p(cStatus) & vbCrLf
 End If
 sText = sText & "SUMMARY;LANGUAGE=de:" & getIcalText(p(cTitle)) & vbCrLf
 sText = sText & "DESCRIPTION:" & vbCrLf
 ' Zeilenlänge maximal 75 Zeichen
 While Len(strDesc) > 0
   If Len(strDesc) > 74 Then
     sText = sText & " " & Left(strDesc, 74) & vbCrLf
     strDesc = Right(strDesc, Len(strDesc) - 74)
   Else
     sText = sText & " " & strDesc & vbCrLf
     strDesc = ""
   End If
 Wend
 sText = sText & "LOCATION:" & getIcalText(p(cPlace)) & vbCrLf
 sText = sText & "DTSTART;TZID=Europe/Berlin:" & Format(p(cDateStart), "YYYYMMDDT") & Format(p(cTimeStart), "hhmmss") & vbCrLf
 sText = sText & "DTEND;TZID=Europe/Berlin:" & Format(p(cDateEnd), "YYYYMMDDT") & Format(p(cTimeEnd), "hhmmss") & vbCrLf
 sText = sText & "DTSTAMP:" & strTimeStamp & vbCrLf
 sText = sText & "LAST-MODIFIED:" & strTimeStamp & vbCrLf
 sText = sText & "BEGIN:VALARM" & vbCrLf
 sText = sText & "TRIGGER:" & getDurationFromMinutes(-30) & vbCrLf
 sText = sText & "ACTION:DISPLAY" & vbCrLf
 sText = sText & "DESCRIPTION:Reminder" & vbCrLf
 sText = sText & "END:VALARM" & vbCrLf
 sText = sText & "END:VEVENT" & vbCrLf

 iLine = iLine + 1

 With ThisWorkbook.Sheets(1)
  p = WorksheetFunction.Transpose(WorksheetFunction.Transpose(Range(.Cells(iLine, 1), .Cells(iLine, 9)).Value))
 End With
 
Wend
'Ende der Schleife
sText = sText & "END:VCALENDAR"
'Ende der Kalenderdatei

Dim adodbStreamUTF
Dim adodbStreamBIN
Set adodbStreamUTF = CreateObject("ADODB.Stream")
Set adodbStreamBIN = CreateObject("ADODB.Stream")

'ics nach UTF und dann als Binary schreiben (ohne Byte Order Mark)

With adodbStreamBIN
 .Type = 1 'Binary Type
 .Open
 With adodbStreamUTF
  .Type = 2 'Text Type
  .Charset = "UTF-8"
  .Open
  .WriteText sText 'Text schreiben
  .flush
  .Position = 3 'nach BOM
  .copyto adodbStreamBIN
  .Close
 End With
 .SaveToFile strFilePath, 2 'Datei speichern, ggf. neu erzeugen
 .Close
End With

MsgBox "Datei geschrieben"

Exit Sub
 
Fehler:
  'Es ist ein Fehler aufgetreten
  MsgBox "Fehler: " & vbCrLf & Err.Number & vbCrLf & Err.Description

End Sub

Function IsValidFileNameOrPath(ByVal name As String, Optional ByVal bolPath As Boolean = True) As Boolean
    
    Dim BadChars As String
    Dim I As Long
     
    BadChars = IIf(bolPath, ".?*>|" & Chr(34), ":/\?*>|" & Chr(34))
    
    ' Determines if the name is Nothing.
    If name = "" Then
        IsValidFileNameOrPath = False
        Exit Function
    End If
    
    ' Determines if there are bad characters in the name.
    For I = 1 To Len(BadChars)
        If InStr(name, Mid(BadChars, I, 1)) > 0 Then
            IsValidFileNameOrPath = False
            Exit Function
        End If
    Next I
    
    IsValidFileNameOrPath = True

End Function
Function getDurationFromMinutes(ByVal dblMinutes As Double) As String
   Dim lngDurSec As Long
   Dim lngS As Long
   Dim lngM As Long
   Dim lngH As Long
   Dim lngD As Long
   Dim lngSig As Long
   Dim strOut As String
   
   'converts a time in minutes (as double) to an ICalendar conform DURATION
   'for a TRIGGER usually a negative DURATION is needed, so here the time input must be a negative value
   'for a time below one second "P0" is returned
   
   lngDurSec = Abs(dblMinutes) * 60
   lngSig = IIf(lngDurSec > 0, Sgn(dblMinutes), 0)
   
   If lngSig = 0 Then
     getDurationFromMinutes = "P0"
     Exit Function
   End If
   
   lngS = lngDurSec Mod 60
   lngDurSec = lngDurSec - lngS
   lngM = lngDurSec Mod 3600
   lngDurSec = lngDurSec - lngM
   lngM = lngM / 60
   lngH = lngDurSec Mod 86400
   lngDurSec = lngDurSec - lngH
   lngH = lngH / 3600
   lngD = lngDurSec / 86400
   
   strOut = IIf(lngSig  0, "-P", "P")
   strOut = strOut & IIf(lngD > 0, lngD, "")
   
   If lngH > 0 Or lngM > 0 Or lngS > 0 Then
      strOut = strOut & "T"
      strOut = strOut & IIf(lngH > 0, lngH & "H", "")
      strOut = strOut & IIf(lngM > 0, lngM & "M", "")
      strOut = strOut & IIf(lngS > 0, lngS & "S", "")
   End If
   
   getDurationFromMinutes = strOut

End Function

Function getIcalText(ByVal sText As String, Optional bolMultiLine As Boolean = False) As String

Dim strOut As String
Dim strRepl As String

'Make stext ICal compliant text
'The characters ,;: are prefixed with \, \n or \N is kept for multiline texts (bolMultiLine = true)
'and creates a line feed in the calendar entry (e.g. DESCRIPTION)
'The \ character is eliminated from the rest of the text for simplicity, so it cannot appear in the calendar entry.
'If \ should be needed, this character would also have to be escaped, i.e. doubled.

strOut = sText

strOut = Replace(strOut, "\n", IIf(bolMultiLine, Chr(13), ""))
strOut = Replace(strOut, "\N", IIf(bolMultiLine, Chr(13), ""))
strOut = Replace(strOut, "\", "")
strOut = Replace(strOut, ",", "\,")
strOut = Replace(strOut, ";", "\;")
strOut = Replace(strOut, ":", "\:")
strOut = Replace(strOut, Chr(13), "\n")

getIcalText = strOut

End Function
glücklich bin ich damit auch noch nicht ganz.
Vermutlich muss ich im Titel irgend eine Kennung rein schreiben, damit man im Google Kalender einen Unterschied zwischen TENTATIVE und CONFIRMED erkennen kann?


Anzeige
AW: iCal bzw. ics Datei erstellen.
24.04.2023 18:15:28
Pappawinni
Boah, hab gerade mal drüber geschaut und stelle fest, dass es da mindestens eine Code-Zeile verhauen hat.
nach:
'Status nur bei gültigem Wert schreiben
sollte eigentlich stehen

If InStr("!TENTATIVE! !CONFIRMED! !CANCELLED!", "!" & p(cStatus) & "!") Mod 12 = 1 Then
wobei die ! eigentlich die Zeichen größer bzw. kleiner waren.
Das scheint das Forum aber irgendwie nicht zu schlucken.


AW: iCal bzw. ics Datei erstellen.
24.04.2023 18:37:37
Yal
Moin,

warum so umständlich?

Prüfung der Status
Sub test()
Const cStatus = "TENTATIVE CONFIRMED CANCELLED"

    Select Case InStr(1, cStatus, UCase(p(cStatus)))
    Case 1 'Tentative
        '...
    Case 11 'Confirmed
        '...
    Case 21 'Cancelled
        '...
    Case Else
        '...
    End Select
End Sub
Umwandlung Minuten in Std, min, Sek:
Function getDurationFromMinutes(ByVal dblMinutes As Double) As String
    getDurationFromMinutes = Format(TimeSerial(0, dblMinutes, 0), "hhmmss") 'Standard wäre "hh:mm:ss"
End Function
VG
Yal


AW: iCal bzw. ics Datei erstellen.
24.04.2023 19:13:30
Pappawinni
Ich war ja gespannt, was dir schönes eingefallen ist, aber...

du lässt für Status unzulässige Werte zu:
T TEN CON oder was halt so anfängt wie zulässige Werte.
Switch is mir zu viel Aufwand für die Unterscheidung, wenn es mod tut, gut.

DURATION hat ein spezielles Format, beginnt mit P oder -P (für negative Duration)
dann kommt gegebenenfalls die Anzahl Tage
+ wenn Stunden, Minuten, Sekunden ergänzt werden
#H für Stunden, #M für Minuten, #S für Sekunden

da warst du mit deinem Beitrag wohl doch ein bissl zu schnell :)




AW: iCal bzw. ics Datei erstellen.
24.04.2023 22:23:31
Yal
Ja, ich gestehe, ich habe die Lange Sub nicht im Detail analysiert :-)

Zweiter Versuch (auch genauso wenig durchgelesen):
Function getDurationFromMinutes(ByVal dblMinutes As Double) As String
Dim T
    T = TimeSerial(100, dblMinutes, 0)
    getDurationFromMinutes = Format(TimeSerial(0, dblMinutes, 0), "Phhmmss")
    If T  TimeEerial(100, 0, 0) Then getDurationFromMinutes = "-" & getDurationFromMinutes
End Function
Der zusammengefasste Select Case ( Switch bräuchte je einen "break;" ):
Sub test()
Const cStatus = "!TENTATIVE!CONFIRMED!CANCELLED!"

    Select Case InStr(1, cStatus, "!" & UCase(p(cStatus)) & "!")
    Case 1, 11, 21
        '...
    Case Else
        '...
    End Select
End Sub
VG
Yal


AW: iCal bzw. ics Datei erstellen.
24.04.2023 22:55:08
Pappawinni
Hallo,
Nein, der Switch, äh, das Select case braucht es sicher nicht, es sollte sogar genügen auf instr(....) > 0 zu prüfen

Also das Zielformat muss man schon kennen, wenn es richtig werden.
Ich fürchte am Ende bist du mit allen Datums- Zeit- Format- funktionen auch nicht effizienter als meine primitive Lösung.

Ich sehe gerade die Spec ist
dur-value = (["+"] / "-") "P" (dur-date / dur-time / dur-week)
dur-date = dur-day [dur-time]
dur-time = "T" (dur-hour / dur-minute / dur-second)
dur-week = 1*DIGIT "W"
dur-hour = 1*DIGIT "H" [dur-minute]
dur-minute = 1*DIGIT "M" [dur-second]
dur-second = 1*DIGIT "S"
dur-day = 1*DIGIT "D"

Da hab ich doch auch etwas übersehen, naja, war eher eigentlich nicht notwendig, weil ich im Grunde fest "-PT30M" in den Code schreiben könnte,
aber wenn schon... schau ich mir nochmal an.


AW: iCal bzw. ics Datei erstellen.
24.04.2023 23:45:22
Yal
Was ich aber nicht verstehe:

   lngDurSec = Abs(dblMinutes) * 60
   lngSig = IIf(lngDurSec > 0, Sgn(dblMinutes), 0)
Dementsprechend ist lngDurSec immer positiv, da Abs(x) immer positiv ist.
laut Wiki sind DTEND und DURATION "R" Required, aber DTSTART ist "O" Optional. Amazing...

VG
Yal


AW: iCal bzw. ics Datei erstellen.
25.04.2023 01:05:05
Pappawinni
Mit DURATION ist hier ein parameterwert gemeint.
Diesen verwende ich auch nur beim TRIGGER, wie du meinem Code entnehmen kannst.
Ich wollte halt verstehen, was "TRiGGER:-PT30M" genau bedeutet und was da noch so stehen könnte,
weil ich mit dem Gedanken gespielt habe, die Erinnerung zu Terminen variabel zu machen.

Ich gehe so vor, dass ich
a) den Absolutwert der Zeit in Minuten nach Sekunden umrechne und zur Ganzzahl mache.
b) das Vorzeichen von der Zeit erfasse, sofern die Zeit überhaupt eine Sekunde beträgt, sonst setze ich das Vorzeichen zu 0
ist das Vorzeichen 0 setze ich den Rückgabewert "P0D" (neuerdings) Ende
ansonsten beginnt der Wert von Duration mit "P" bei positivem Vorzeichen und mit "-P" bei negativem Vorzeichen
Ich errechne nacheinander unter anderem mit der von dir wenig geliebten Modulo-Funktion (Rest der Division)
Sekunden, Minuten, Stunden, Tage
und daraus bastele ich dann den Rest der Duration zusammen.

So, denk ich, müsste es der Spec entsprechen:

Function getDurationFromMinutes(ByVal dblMinutes As Double) As String
   Dim lngDurSec As Long
   Dim lngS As Long
   Dim lngM As Long
   Dim lngH As Long
   Dim lngD As Long
   Dim lngSig As Long
   Dim strOut As String
   
   'converts a time in minutes (as double) to an ICalendar conform DURATION
   'for a TRIGGER usually a negative DURATION is needed, so here the time input must be a negative value
   'for a time below one second "P0D" is returned
   
   lngDurSec = Abs(dblMinutes) * 60
   lngSig = IIf(lngDurSec > 0, Sgn(dblMinutes), 0)
   
   If lngSig = 0 Then
     getDurationFromMinutes = "P0D"
     Exit Function
   End If
   
   lngS = lngDurSec Mod 60
   lngDurSec = lngDurSec - lngS
   lngM = lngDurSec Mod 3600
   lngDurSec = lngDurSec - lngM
   lngM = lngM / 60
   lngH = lngDurSec Mod 86400
   lngDurSec = lngDurSec - lngH
   lngH = lngH / 3600
   lngD = lngDurSec / 86400
   
   strOut = IIf(lngSig  0, "-P", "P")
   
   If lngH > 0 Or lngM > 0 Or lngS > 0 Then
      strOut = strOut & IIf(lngD > 0, lngD & "D", "")
      strOut = strOut & "T"
      strOut = strOut & IIf(lngH > 0, lngH & "H", "")
      strOut = strOut & IIf(lngM > 0 Or (lngH > 0 And lngS > 0), lngM & "M", "")
      strOut = strOut & IIf(lngS > 0, lngS & "S", "")
   Else
      strOut = strOut & IIf(lngD Mod 7 = 0, lngD / 7 & "W", lngD & "D")
   End If
     
   getDurationFromMinutes = strOut

End Function

siehe dazu auch
https://icalendar.org/iCalendar-RFC-5545/3-3-6-duration.html

Ich werde dann auch mal schauen, was du da bei Wiki findest.
Im Augenblick versteh ich nicht ganz, was du meinst.


AW: iCal bzw. ics Datei erstellen.
25.04.2023 11:46:41
Pappawinni
Ich hab jetzt auch getIcalText nochmal geändert.
Der User kann ja durch betätigen von Alt-Enter einen Zeilenvorschub gerenerieren (vbCR).
Das hatte ich nicht bedacht. Ich ersetzte jetzt im Fall bolMultiLine = True CR oder LF durch \n.
Den Zeichen ,;:\ stelle ich ein \ voran.
Bösartige User könnten natürlich weitere Steuerzeichen rein basteln, aber die sind dann selbst schuld :)


Function getIcalText(ByVal sText As String, Optional bolMultiLine As Boolean = False) As String

Dim strOut As String
Dim lngI As Long
Dim strC As String

'Make stext ICal compliant text
'The characters ,;:\ are prefixed with \, CR and LF are replaced by \n for multiline texts (bolMultiLine = true)
'and otherwise ignored. \n creates a line feed in the calendar entry (e.g. DESCRIPTION)
'CR can be created in a Cell by pressing ALT-Enter

If sText = "" Then
   getIcalText = strOut
   Exit Function
End If

For lngI = 1 To Len(sText)
  strC = Mid(sText, lngI, 1)
  If InStr(",:;\" & vbCrLf, strC) > 0 Then
    strOut = strOut & IIf(InStr(",:;\", strC) > 0, "\" & strC, "")
    strOut = strOut & IIf(InStr(vbCrLf, strC) > 0 And bolMultiLine, "\n", "")
  Else
    strOut = strOut & strC
  End If
Next

getIcalText = strOut

End Function

Zu der Tabelle in Wikipedia aus der du offenbar liest, was Optional ist, kann ich wenig sagen.
Ich habe nur den Eindruck, dass die Komplexität des iCalendar Formats sich damit nicht wirklich darstellen lässt.
Nach Spezifikation muss bei Verwendung eines TRIGGER ein DTSTART gegeben sein.

257 Forumthreads zu ähnlichen Themen

Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige