Développement- Fichiers ICS et Calendrier – Partie 3

Série de 3 articles sur les fichiers ICS : (1) Définition; (2) Création et Partage; (3) Automatisation Excel > Outlook

Partie 3: Créer une Interface entre Excel et Outlook

Mon but : exporter la cellule Excel sélectionnée vers un rendez-vous Outlook pour éviter de devoir rentrer mes rendez-vous en double.

Pré requis :

Exemple de Fichier Excel

Ce fichier Excel contenant un calendrier en mode colonne de mois et lignes de jours.

Ignorez l’anglais car peu importe la langue utilisée nous travaillerons avec les chiffres. Admettons donc :

  • Cellule H1 contenant l’année (2022)
  • Colone L et P – Ligne 1 : mois en chiffre
  • Colone L et P – Lignes 2 à 32 : jour du mois en chiffres
  • Les réunions toujours formattées en utilisant HH:MM Texte (Heure et Minutes sur 2 chiffres)
  • Utilisation : sélectionner cellule M17 > appuyer sur générer > Outlook ouvert avec les champs pré remplis.

Pour effectuer cette action, il faut passer en mode « développeur » sur Excel : Cliquer sur ‘View’ et ‘Macro’ . Voici les macros utilisées.

---- 
Sub Export_ICS_Vers_Outlook()
Dim ICS_str As String
    ICS_str = "BEGIN:VCALENDAR" & vbCrLf
    ICS_str = ICS_str & "VERSION:2.0" & vbCrLf
    ICS_str = ICS_str & "PRODID:-//68600.fr//iCal Event Maker" & vbCrLf
    ICS_str = ICS_str & "CALSCALE:GREGORIAN" & vbCrLf
    ICS_str = ICS_str & "BEGIN:VTIMEZONE" & vbCrLf
    ICS_str = ICS_str & "TZID:Europe/Berlin" & vbCrLf
    ICS_str = ICS_str & "BEGIN:STANDARD" & vbCrLf
    ICS_str = ICS_str & "TZNAME:CET" & vbCrLf
    ICS_str = ICS_str & "TZOFFSETFROM:+0200" & vbCrLf
    ICS_str = ICS_str & "TZOFFSETTO:+0100" & vbCrLf
    ICS_str = ICS_str & "DTSTART:19701025T030000" & vbCrLf
    ICS_str = ICS_str & "RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU" & vbCrLf
    ICS_str = ICS_str & "END:STANDARD" & vbCrLf
    ICS_str = ICS_str & "BEGIN:DAYLIGHT" & vbCrLf
    ICS_str = ICS_str & "TZNAME:CEST" & vbCrLf
    ICS_str = ICS_str & "TZOFFSETFROM:+0100" & vbCrLf
    ICS_str = ICS_str & "TZOFFSETTO:+0200" & vbCrLf
    ICS_str = ICS_str & "DTSTART:19700329T020000" & vbCrLf
    ICS_str = ICS_str & "RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU" & vbCrLf
    ICS_str = ICS_str & "END:DAYLIGHT" & vbCrLf
    ICS_str = ICS_str & "END:VTIMEZONE" & vbCrLf
    ICS_str = ICS_str & "LAST-MODIFIED:20201011T015911Z" & vbCrLf
    ICS_str = ICS_str & "TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin" & vbCrLf
    ICS_str = ICS_str & "X-LIC-LOCATION:Europe/Berlin" & vbCrLf
    ICS_str = ICS_str & "BEGIN:VEVENT" & vbCrLf
    ICS_str = ICS_str & "ATTENDEE;CN=" & """" & "Papa" & """" & ";RSVP=TRUE:mailto:papi@gmail.com" & vbCrLf
    ICS_str = ICS_str & "CLASS:PRIVATE" & vbCrLf
    ICS_str = ICS_str & "CATEGORIES:Important" & vbCrLf
    ICS_str = ICS_str & "DTSTAMP:20220823T131634Z" & vbCrLf
    ICS_str = ICS_str & "UID:'D6D" & Int((100000000 * Rnd) + 1) & "'" & vbCrLf
    ICS_str = ICS_str & "DTSTART;TZID=Europe/Berlin:MyDateStart" & vbCrLf
    ICS_str = ICS_str & "DTEND;TZID=Europe/Berlin:MyDateEnd" & vbCrLf
    ICS_str = ICS_str & "SUMMARY;LANGUAGE=en-us:MyTitle" & vbCrLf
    ICS_str = ICS_str & "DESCRIPTION:MyDescription" & vbCrLf
    ICS_str = ICS_str & "LOCATION:MyLocation" & vbCrLf
    ICS_str = ICS_str & "TRANSP:OPAQUE" & vbCrLf
    ICS_str = ICS_str & "X-MICROSOFT-CDO-BUSYSTATUS:FREE" & vbCrLf
    ICS_str = ICS_str & "BEGIN:VALARM" & vbCrLf
    ICS_str = ICS_str & "ACTION:DISPLAY" & vbCrLf
    ICS_str = ICS_str & "DESCRIPTION:Reminder" & vbCrLf
    ICS_str = ICS_str & "TRIGGER:-PT15M" & vbCrLf
    ICS_str = ICS_str & "END:VALARM" & vbCrLf
    ICS_str = ICS_str & "END:VEVENT" & vbCrLf
    ICS_str = ICS_str & "END:VCALENDAR" & vbCrLf

'MsgBox ICS_str

MyRow = ActiveCell.Row
MyCol = ActiveCell.Column
MeetDay = 0
MeetMonth = 1
MeetTime = 18                                           'Default Meeting Time
MeetText = ActiveCell.Value                             'Default Meeting Text
If (Len(ActiveCell.Value) > 2) Then                      'If more than  digits then we run the rest
    If (Left(ActiveCell.Value, 2) < 24) Then                'If 2 digits then it is a valid info for time
        MeetTime = Left(MeetText, 2)                        'Extract new Meeting Time
        MeetText = Right(MeetText, Len(MeetText) - 3)       'Extract new Meeting Text
        If (Left(MeetText, 2) < 60) Then
            MeetTime = MeetTime & Left(MeetText, 2)
            MeetText = Right(MeetText, Len(MeetText) - 3)
        End If
        If Len(MeetTime > 3) Then
            MeetTime = MeetTime & "00"
        Else
            MeetTime = MeetTime & "0000"
        End If
        
    End If
    'MsgBox (MeetTime)
    If Len(MeetTime < 3) Then MeetTime = MeetTime & "00"    'Complement to have Time on 6 digits (HHMMSS)
    ActiveCell.Offset(0, -1).Select                         'Select Day date in left column
    While MeetDay = 0
     If (ActiveCell.Value > 0 And ActiveCell.Value < 32) Then
       MeetDay = ActiveCell.Value
      Else
       ActiveCell.Offset(0, -1).Select                      'Else Select Day date in one more left column
        If (ActiveCell.Value > 0 And ActiveCell.Value < 32) Then
            MeetDay = ActiveCell.Value
        End If
        'MsgBox ActiveCell.Value & " " & ActiveCell.Row & " " & ActiveCell.Column
      End If
      If (MeetDay < 10) Then MeetDay = "0" & MeetDay
    Wend
    
    ActiveCell.Offset((1 - ActiveCell.Row), 0).Select       'Select Month date in top row same column
    MeetMonth = ActiveCell.Value
    If (MeetMonth < 10) Then MeetMonth = "0" & MeetMonth
    
    Range("J1").Select                                      'Select Year date in top row same column
    MeetYear = ActiveCell.Value
    
    ICS_str = Replace(ICS_str, "MyDescription", MeetText)
    ICS_str = Replace(ICS_str, "MyTitle", MeetText)
    ICS_str = Replace(ICS_str, "MyLocation", "Volgelsheim")
    '20221006T100000
    ICS_str = Replace(ICS_str, "MyDateStart", MeetYear & MeetMonth & MeetDay & "T" & MeetTime & "00")
    ICS_str = Replace(ICS_str, "MyDateEnd", MeetYear & MeetMonth & MeetDay & "T" & MeetTime & "10")
    
    Range(Cells(MyRow, MyCol), Cells(MyRow, MyCol)).Select
    
    ICS_Filename = MeetYear & MeetMonth & MeetDay & "_" & Replace(MeetText, " ", "_") & ".ics"
    lg = Ecrire_Txt(ActiveWorkbook.Path & "\" & ICS_Filename, ICS_str)
    
    Call convertTxttoUTF(ActiveWorkbook.Path & "\" & ICS_Filename, ActiveWorkbook.Path & "\" & "UTF" & ICS_Filename)
    
      'MsgBox "Export vers .ics = Ok"
    If lg = 0 Then Shell ("C:\Program Files\Microsoft Office\root\Office16\OUTLOOK.EXE" & " /ical " & ActiveWorkbook.Path & "\" & "UTF" & ICS_Filename)
    '/ical <icsfilename>
    
   End If
End Sub

Enregister la macro, repartir sur une cellule du tableau Excel et essayer.
Note : Le fichier ICS et fichier ICS format UTF seront sauvegardés dans le meme dossier que fichier Excel utilisé.
Note 2: La durée n’étant pas spécifiée dans le calendrier Excel, la réunion aura une durée d’une seconde; c’est arbitraire et il me suffit de changer cela dans Outlook quand tout le reste sera déjà en place !

Étape finale, ajouter un moyen de lancement facile (plutot que naviguer dans les menus) : ajouter un bouton :

  1. Passez en mode développeur
    • Sous l’onglet Fichier , accédez à Options Personnaliser le ruban.
    • Sous Personnaliser le ruban et Onglets principaux, activez la case à cocher Développeur.
  2. Sélectionnez le menu développeur, insérer > bouton
  3. Dessinez la taille et position du bouton (un gros rectangle )
  4. Définissez la macro « Export_ICS_Vers_Outlook »qui lui sera affecté.
Insertion d’un bouton (étape 3)

Bilan

Comme pour la version HTML ou plutot PHP, j’ai adapté les champs à mon besoin, réunion privée, en mode important, avec rappel et qui ne bloque pas mon calendrier, envoi de l’invitation par courriel à un contact.

Cela conclue cette aventure un peu poilue dans le monde des fichier iCalendar, totalement hors sujet de D6D mais tout de même proche de l’automatisation 😉

Développement- Fichiers ICS et Calendrier – Partie 2

Série de 3 articles sur les fichiers ICS : (1) Définition; (2) Création et Partage; (3) Automatisation Excel > Outlook

Partie 2: Création et partage

Il y a des évènements qui sont importants et pour les garder en mémoire, ou plutôt dans la mémoire de nos assistants numériques, il faut cliquer sur ‘nouveau rendez-vous’ choisir une date de début, de fin, un texte, cliquer, cliquer et encore cliquer. J’ai tellement de paramètres à définir que cela me fatigue, mais aussi qu’il faut parfois partager sans pour autant l’entrer dans mon calendrier. Voici donc le générateur ICS

Simple page PHP, qui demande du texte par ligne, bien entendu formaté correctement, et génère en sortie un fichier ICS automatiquement poussé sur le navigateur client.

Fonctionnement simple, basique dont voilà la source :

<?php
 
setlocale(LC_TIME, 'fr_FR'); //setlocale (LC_TIME, 'fr_FR.utf8','fra'); 

 function test_input($data) {
	 // nettoyer le texte qui sera envoyé
  $data = trim($data);
  $data = stripslashes($data);
  $data = htmlspecialchars($data);
  return $data;
}

 date_default_timezone_set('Europe/Paris');
 if (!isset($_POST['date_start'])) {  ?> 
// si le formulaire est vierge.. alors continue
 <!doctype html>
 <html lang="fr">

 <head>
 <meta http-equiv="content-type" content="text/html; charset=utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 <title>Générateur de fichiers ICS</title>
 <link rel="icon" type="image/x-icon" href="favicon.png">
 </head>
 <body>
 <link rel="stylesheet" href="style.css" />
  <h1>Générateur de fichiers ICS<br> <?
    echo '<form method="post">';
 	echo '<h2>Complétez les champs puis validez<h2>';
	echo "<input class='form-control' type='text' placeholder='".ucfirst(utf8_encode(strftime('%A %d %B %Y, %H:%M'))) ."' readonly>"; 
	echo 'Titre - objet du rendez vous<input type=text id="invalidCheck" required class="form-control" name=titre value="titre">';
	echo 'Début - format Année Mois Jour "T" Heure Minute<input type="text" id="invalidCheck" required class="form-control" name="date_start" value="20221006T100000">';
	echo 'Fin - format Année Mois Jour "T" Heure Minute<input type="text" id="invalidCheck" required class="form-control" name="date_end" value="20221006T110000">';
	echo 'Description - détails sur le rendez-vous<input type="text" id="invalidCheck" class="form-control" name="description" value="description longue">';
	echo 'Emplacement - adresse complète <input type="text" id="invalidCheck" class="form-control" name="emplacement" value="adresse ou lien">';
	echo 'Privé - détails invisibles par les personnes ayant délégation sur votre calendrier <input type="checkbox" id="invalidCheck" class="form-control" name="privat">';
	echo 'Important - rendez vous marqué comme tel <input type="checkbox" id="invalidCheck" class="form-control" name="important">';
?>

 <div class="col-12">  <button class="btn btn-primary" type="submit">Générer</button>  </div>
 </form>
 </body>
</html>
<?php 
}else{
// si le formulaire n'est par vierge.. alors crée le fichier ICS
    $_POST[titre]=test_input($_POST[titre]);
    $_POST[date_start]=test_input($_POST[date_start]);
    $_POST[date_end]=test_input($_POST[date_end]);
    $_POST[emplacement]=test_input($_POST[emplacement]);
    $_POST[description]=test_input($_POST[description]);
    $ics_props =  'BEGIN:VCALENDAR'."\r\n";
    $ics_props .= 'VERSION:2.0'."\r\n";
    $ics_props .= 'PRODID:-//68600.fr//iCal Event Maker'."\r\n";
    $ics_props .= 'CALSCALE:GREGORIAN'."\r\n";
    $ics_props .= 'BEGIN:VTIMEZONE'."\r\n";
    $ics_props .= 'TZID:Europe/Berlin'."\r\n";
    $ics_props .= 'BEGIN:STANDARD'."\r\n";
    $ics_props .= 'TZNAME:CET'."\r\n";
    $ics_props .= 'TZOFFSETFROM:+0200'."\r\n";
    $ics_props .= 'TZOFFSETTO:+0100'."\r\n";
    $ics_props .= 'DTSTART:19701025T030000'."\r\n";
    $ics_props .= 'RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU'."\r\n";
    $ics_props .= 'END:STANDARD'."\r\n";
    $ics_props .= 'BEGIN:DAYLIGHT'."\r\n";
    $ics_props .= 'TZNAME:CEST'."\r\n";
    $ics_props .= 'TZOFFSETFROM:+0100'."\r\n";
    $ics_props .= 'TZOFFSETTO:+0200'."\r\n";
    $ics_props .= 'DTSTART:19700329T020000'."\r\n";
    $ics_props .= 'RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU'."\r\n";
    $ics_props .= 'END:DAYLIGHT'."\r\n";
    $ics_props .= 'END:VTIMEZONE'."\r\n";
    $ics_props .= 'LAST-MODIFIED:20201011T015911Z'."\r\n";
    $ics_props .= 'TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin'."\r\n";
    $ics_props .= 'X-LIC-LOCATION:Europe/Berlin'."\r\n";
    $ics_props .= 'BEGIN:VEVENT'."\r\n";
	if (isset($_POST[privat]))     { $ics_props .= 'CLASS:PRIVATE'."\r\n";}
	if (isset($_POST[important]))  { $ics_props .= 'CATEGORIES:Important'."\r\n";}
	$ics_props .= 'DTSTAMP:20220823T131634Z'."\r\n";
    $ics_props .= 'UID:'.uniqid()."\r\n";
    $ics_props .= 'DTSTART;TZID=Europe/Berlin:'.$_POST[date_start]."\r\n";
    $ics_props .= 'DTEND;TZID=Europe/Berlin:'.$_POST[date_end]."\r\n";
    $ics_props .= 'SUMMARY:'.$_POST[titre]."\r\n";
    $ics_props .= 'DESCRIPTION:'.$_POST[description]."\r\n";
    $ics_props .= 'LOCATION:'.$_POST[emplacement]."\r\n";
    $ics_props .= 'TRANSP:OPAQUE'."\r\n";
    $ics_props .= 'X-MICROSOFT-CDO-BUSYSTATUS:BUSY'."\r\n";
    $ics_props .= 'BEGIN:VALARM'."\r\n";
    $ics_props .= 'ACTION:DISPLAY'."\r\n";
    $ics_props .= 'DESCRIPTION:Reminder'."\r\n";
    $ics_props .= 'TRIGGER:-PT15M'."\r\n";
    $ics_props .= 'END:VALARM'."\r\n";
    $ics_props .= 'END:VEVENT'."\r\n";
    $ics_props .= 'END:VCALENDAR'."\r\n";
// créee le fichier
    $uniqueFileName = uniqid(mt_rand(), true) . '.ics';

// affiche le fichier ICS et force le navigateur à le télécharger

    header('Content-type: text/calendar; charset=utf-8');
    header("Content-Disposition: attachment; filename=".$uniqueFileName);
    echo $ics_props;	
}

?> 

Si tout va bien, vous devriez pouvoir générer vos fichiers rdv et les partager !

Mais cela n’est pas tout : ceux qui me connaissent savent que je ne jure que par Excel. C’est mon outil de prédilection. Voyons comment utiliser Excel comme source > Suite Partie 3

Développement- Fichiers ICS et Calendrier – Partie 1

Série de 3 articles sur les fichiers ICS : (1) Définition; (2) Création et Partage; (3) Automatisation Excel > Outlook

Partie 1 : Définition

Qu’est-ce qu’un fichier ICS ? 

Un fichier ICS est un fichier iCalendar. Ce sont des fichiers en texte brut qui incluent des détails d’événement de calendrier comme une description, les heures de début et de fin, l’emplacement, etc. Le format ICS est généralement utilisé pour envoyer des demandes de réunion à des personnes, mais également un moyen populaire pour s’abonner à des calendriers de vacances ou d’anniversaire. Ces fichiers sont utilisés et échangés entre les applications de calendrier et courriels tels que

  • Microsoft Outlook,
  • Mozilla Thunderbird,
  • Le calendrier Apple,
  • Le calendrier Google,
  • … plein d’autres …

En résumé, quand quelqu’un vous envoie une réunion par courriel, il est fort à parier que ce courriel contient un fichier ICS.

Le type MIME utilisé par les données d’iCalendar est « text/calendar » et son format normé les arguments définis. Il est architecturé en blocs de paramètres. Vous trouverez sur cette page des détails techniques;

Voici le squelette du fichier:

BEGIN:VCALENDAR
   BEGIN:VTIMEZONE
      BEGIN:STANDARD
      END:STANDARD
      BEGIN:DAYLIGHT
      END:DAYLIGHT
   END:VTIMEZONE
   BEGIN:VEVENT
      BEGIN:VALARM
      END:VALARM 
   END:VEVENT
END:VCALENDAR

Tous ces champs ne sont pas nécessaires ! Il faut retenir que le langage est formé de blocs déclarés par « BEGIN » et « END » ainsi que des paramètres entre chacun. Pour les dates, plusieurs formats sont acceptés, ainsi, certaines balises seront nécessaires uniquement sur l’utilisation d’un format donné. Pour ma part j’ai choisi le format 2022126T18250000 et la déclaration de changement d’heure. Chacun verra son opportunité !

Pour aller plus loin, voici un fichier type :

BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//68600.fr//D6D//ics/ Event Maker
CALSCALE:GREGORIAN
BEGIN:VTIMEZONE
TZID:Europe/Berlin
BEGIN:STANDARD
TZNAME:CET
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
DTSTART:19701025T030000
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:CEST
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
DTSTART:19700329T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
END:DAYLIGHT
END:VTIMEZONE
LAST-MODIFIED:20201011T015911Z
TZURL:http://tzurl.org/zoneinfo-outlook/Europe/Berlin
X-LIC-LOCATION:Europe/Berlin
BEGIN:VEVENT
ATTENDEE;CN="Papa";RSVP=TRUE:mailto:pipo@gmail.com
CLASS:PRIVATE
CATEGORIES:Important
DTSTAMP:20220823T131634Z
UID:'D6D30194802'
DTSTART;TZID=Europe/Berlin:2022126T18150000
DTEND;TZID=Europe/Berlin:2022126T18250000
SUMMARY;LANGUAGE=en-us:Réunion
DESCRIPTION:Réunion
LOCATION:Collège 
TRANSP:OPAQUE
X-MICROSOFT-CDO-BUSYSTATUS:FREE
BEGIN:VALARM
ACTION:DISPLAY
DESCRIPTION:Reminder
TRIGGER:-PT15M
END:VALARM
END:VEVENT
END:VCALENDAR

Ici, on peut voir une invitation pour un évènement le 6 décembre de 18h15 à 18h25, qui sera envoyée à ‘Papa’, catégorisée importante, dont un rappel sera effectué 15 minutes avant et qui ne bloquera pas le calendrier (dans le cadre d’un calendrier visible par autrui via TRANSP:OPAQUE & X-MICROSOFT-CDO-BUSYSTATUS:FREE). La portion du code « BEGIN:VTIMEZONE » définit en outre le changement horaire.

Copiez le code, enregistrez le dans un fichier en extension ‘.ics’, puis cliquez dessus pour l’ouvrir, vous devriez voir votre calendrier se remplir d’un nouveau rendez-vous – enfin, si votre appareil possède un des logiciels précédemment évoqué.

Vous pouvez en outre changer les dates de début, fin, et divers textes pour adapter le calendrier à vos besoin… c’est ce que j’ai fait ici – https://www.68600.fr/D6D/ics/

Maintenant que nous avons la base > Suite Partie 2