web-dev-qa-db-fra.com

Créez des événements Google Agenda à partir d'une feuille de calcul, mais évitez les doublons

J'essaie d'écrire un script qui prendra les données d'une feuille de calcul Google et créera des événements dans mon calendrier Google.

J'ai bien réussi mais cela a produit des doublons à chaque fois que je l'ai exécuté. Alors maintenant, j'essaie d'éviter cela en créant une colonne 17 dans la feuille de calcul avec un ID d'événement unique généré automatiquement pour chaque ligne, puis chaque fois que le script est exécuté, il examinera l'ID d'événement pour chaque ligne et supprimera l'événement correspondant dans le calendrier avant de le recréer avec les données d'origine ou les données mises à jour si j'ai modifié la ligne.

Je suis nouveau dans les scripts de toute nature et j'ai bricolé cela ensemble, mais je frappe un mur maintenant. Quelqu'un peut-il aider à résoudre ce problème?

function CalInsert() {
    var cal = CalendarApp.getDefaultCalendar();
    var id = SpreadsheetApp.getActiveSheet().getRange(2,17).getValue();

    if (id != 0) {
        var event = cal.getEventSeriesById(id);
        event.deleteEventSeries();
    }

    var sheet = SpreadsheetApp.getActiveSheet();
    var startRow = 2; // First row of data to process
    var numRows = sheet.getLastRow(); // Number of rows to process
    var dataRange = sheet.getRange(startRow, 1, numRows, sheet.getLastColumn());
    var data = dataRange.getValues();

    for (i in data) {
        var row = data[i];
        var title = row[0]; // First column
        var desc = row[13]; // Second column
        var tstart = row[14];
        var tstop = row[15];

        var event = cal.createEvent(title, tstart, tstop, {description:desc});
        var eventid = event.getId();
        SpreadsheetApp.getActiveSheet().getRange(2,17).setValue(eventid);
    }
}
26
user2240577

Ceci est très similaire à une question posée il y a seulement deux jours, qui concernait la synchronisation d'une feuille de calcul d'événements avec un calendrier. Il semble que vous souhaitiez considérer la feuille de calcul comme le maître des événements dont elle est issue, ce qui simplifierait considérablement le problème. Les bases de ce que vous devez faire sont décrites dans cette réponse . Si vous préférez simplement modifier le code existant, j'ai une implémentation ci-dessous.

J'ai une version modifiée du code de ce blog , qui modifiera les entrées de calendrier préexistantes pour qu'elles correspondent aux informations de la feuille de calcul. J'ai organisé ma feuille de calcul différemment, et cela se reflète dans le code.

Date | Titre | Heure de début | Heure de fin | Localisation | Description | EventID

La colonne ID d'événement est remplie par le script lorsque de nouveaux événements sont créés, puis est utilisée dans des appels ultérieurs pour récupérer des événements du calendrier, évitant ainsi la duplication.

Scénario

/**
 * Adds a custom menu to the active spreadsheet, containing a single menu item
 * for invoking the exportEvents() function.
 * The onOpen() function, when defined, is automatically invoked whenever the
 * spreadsheet is opened.
 * For more information on using the Spreadsheet API, see
 * https://developers.google.com/apps-script/service_spreadsheet
 */
function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Export Events",
    functionName : "exportEvents"
  }];
  sheet.addMenu("Calendar Actions", entries);
};

/**
 * Export events from spreadsheet to calendar
 */
function exportEvents() {
  var sheet = SpreadsheetApp.getActiveSheet();
  var headerRows = 1;  // Number of rows of header info (to skip)
  var range = sheet.getDataRange();
  var data = range.getValues();
  var calId = "YOUR_CALENDAR_ID";
  var cal = CalendarApp.getCalendarById(calId);
  for (i=0; i<data.length; i++) {
    if (i < headerRows) continue; // Skip header row(s)
    var row = data[i];
    var date = new Date(row[0]);  // First column
    var title = row[1];           // Second column
    var tstart = new Date(row[2]);
    tstart.setDate(date.getDate());
    tstart.setMonth(date.getMonth());
    tstart.setYear(date.getYear());
    var tstop = new Date(row[3]);
    tstop.setDate(date.getDate());
    tstop.setMonth(date.getMonth());
    tstop.setYear(date.getYear());
    var loc = row[4];
    var desc = row[5];
    var id = row[6];              // Sixth column == eventId
    // Check if event already exists, update it if it does
    try {
      var event = cal.getEventSeriesById(id);
    }
    catch (e) {
      // do nothing - we just want to avoid the exception when event doesn't exist
    }
    if (!event) {
      //cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
      var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
      row[6] = newEvent;  // Update the data array with event ID
    }
    else {
      event.setTitle(title);
      event.setDescription(desc);
      event.setLocation(loc);
      // event.setTime(tstart, tstop); // cannot setTime on eventSeries.
      // ... but we CAN set recurrence!
      var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
      event.setRecurrence(recurrence, tstart, tstop);
    }
    debugger;
  }
  // Record all event IDs to spreadsheet
  range.setValues(data);
}

Supprimer/recréer

Dans cette alternative, l'ID d'événement est utilisé pour rechercher et supprimer l'événement existant précédemment. Après cela, un nouvel événement est créé avec les données dans la feuille de calcul. Cela présente l'avantage que toutes les valeurs de l'événement peuvent être mises à jour, y compris les heures de début et de fin (voir les notes ci-dessous). En revanche, toutes les modifications apportées à l'événement d'origine seront perdues - par exemple, si d'autres personnes ont été invitées à l'événement ou si des rappels personnalisés ont été ajoutés.

Pour utiliser cette alternative, remplacez simplement le code correspondant par ceci:

// Check if event already exists, delete it if it does
try {
  var event = cal.getEventSeriesById(id);
  event.deleteEventSeries();
  row[6] = '';  // Remove event ID    
}
catch (e) {
  // do nothing - we just want to avoid the exception when event doesn't exist
}
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop, {description:desc,location:loc}).getId();
row[6] = newEvent;  // Update the data array with event ID
debugger;

Remarques

  • La documentation de getEventSeriesById indique à tort qu'elle renvoie null lorsqu'aucun événement correspondant n'est trouvé, alors qu'à la place, elle lève une exception. (méchant!) Je l'ai donc enfermé dans un bloc try/catch juste pour continuer à nager.
  • Malheureusement, alors que getEventSeriesById fonctionne pour récupérer un événement, il returns un objet EventSeries, qui ne prend pas en charge la méthode setTime(). Si vous ne vous attendez pas à changer l'heure des événements, c'est OK. Sinon, vous pouvez changer les Event en EventSeries en définissant les règles et heures récurrence, ou supprimer l'ancien événement et en créer un nouveau, comme indiqué dans Supprimer/Recréer . Numéro 1154 .
  • La feuille de calcul gagne toujours. Tout changement d'événement (dans les champs pertinents) enregistré via Google Agenda sera écrasé par le script.
38
Mogsdad

Je voudrais publier ceci pour toute personne qui souhaite l'utiliser, j'ai modifié le script pour qu'il fonctionne dans une feuille que j'utilisais déjà. Le format de date et la duplication d'événements étaient quelques problèmes qui devaient être corrigés, mais après quelques tests, je suis assez satisfait de la façon dont cela fonctionne.Je l'utilise pour réserver des emplois et les partager avec mes employés qui sont mobiles et effectuent des travaux de type construction à travers le ville. La prochaine étape consiste à extraire les événements du calendrier dans la feuille de calcul afin qu'il puisse fonctionner dans les deux sens et que je puisse utiliser l'application de calendrier sur mon téléphone pour réserver des emplois à la volée, donc si quelqu'un a des conseils à toutes les oreilles, j'ai également besoin d'un script pour insérer former des données de réponse dans la même feuille et ajouter des lignes complètes où les numéros de travail correspondent en gardant les données existantes intactes.

`function onOpen() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var entries = [{
name : "Export Events",
functionName : "exportEvents"
}];     sheet.addMenu("Calendar Actions", entries);
};

function parseDate(s) {
var months = {jan:0,feb:1,mar:2,apr:3,may:4,jun:5,
            jul:6,aug:7,sep:8,oct:9,nov:10,dec:11};
var p = s.replace(".", "").split('-');
return new Date(p[2], months[p[1].toLowerCase()], p[0]);
}

/**
* Export events from spreadsheet to calendar
*/
function exportEvents() {
var sheet = SpreadsheetApp.getActiveSheet();

var headerRows = 6;  // Number of rows of header info (to skip)
var range = sheet.getDataRange();
var data = range.getDisplayValues();
//var calId = "Your calendar Id"; // PRODUCTION
var calId = "Your_calendar Id to test"; // TEST
var cal = CalendarApp.getCalendarById(calId);
//Logger.log(cal);
//Logger.log(data.length);
for (i=0; i<data.length; i++) {
if (i < headerRows) continue; // Skip header row(s)
if (data[i][0].length < 1) continue; // Skip if no content.

var row    = data[i];
Logger.log(row);
var date   = parseDate(row[0]);  // First column
//Logger.log(date);
var title  = row[1];           // Second column

var tstart = new Date();
var s = row[2].split(":");
tstart.setHours(s[0]);
tstart.setMinutes(s[1]);
tstart.setSeconds(s[2]);
tstart.setDate(date.getDate());
tstart.setMonth(date.getMonth());
tstart.setYear(date.getYear());

var tstop = new Date();
var e = row[3].split(":");
tstop.setHours(e[0]);
tstop.setMinutes(e[1]);
tstop.setSeconds(e[2]);

tstop.setDate(date.getDate());
tstop.setMonth(date.getMonth());
tstop.setYear(date.getYear());
var loc  = row[4];
var desc = row[5];
var id   = row[6];              // Sixth column == eventId
// Check if event already exists, update it if it does
var event = null;
if (id.length > 0) {
try {
event = cal.getEventSeriesById(id);
}
catch (e) {
// do nothing - we just want to avoid the exception when event doesn't            exist
} 
}
if (!event) {
//cal.createEvent(title, new Date("March 3, 2010 08:00:00"), new
Date("March 3, 2010 09:00:00"), {description:desc,location:loc});
var newEvent = cal.createEvent(title, tstart, tstop,                                     
{description:desc,location:loc}).getId();                     
var r = i + 1;
var cell = sheet.getRange("G" + r);
cell.setValue(newEvent);
}
else {
Logger.log(event);
event.setTitle(title);
event.setDescription(desc);
event.setLocation(loc);
// event.setTime(tstart, tstop); // cannot setTime on eventSeries.
// ... but we CAN set recurrence!
var recurrence = CalendarApp.newRecurrence().addDailyRule().times(1);
event.setRecurrence(recurrence, tstart, tstop);
}
debugger;
}
}

"

4
Jarrod Rapson