Export kalendára MS Outlook do súboru vo formáte .ics

AutomatorMožnosti Windows Shell sú naozaj dosť veľké na to, aby v ňom šlo v podstate čokoľvek si zmyslíte. Sľuby máme za sebou a dnes vyberám spôsob ako vyrvať z kalendára Outlooku udalosti do súboru v štandardnom formáte .ics, ktorý je všeobecne používaný. Skript teda „vyzobe“ schôdzky z kalendára a uloží ich do súboru.



var categories = new Array("Private","Holiday");
var exportMode = "all";
var includeHistory = 30;
var icsFilename = "calendar.ics";
var includeBody = false;
var includeAlarm = false;
var olSunday = 1;
var olMonday = 2;
var olTuesday = 4;
var olWednesday = 8;
var olThursday = 16;
var olFriday = 32;
var olSaturday = 64;
var olFolderCalendar = 9;
var olRecursDaily = 0;
var olRecursWeekly = 1;
var olRecursMonthly = 2;
var olRecursMonthNth = 3;
var olRecursYearly = 5;
var olRecursYearNth = 6;
var olNormal = 0;
var olPersonal = 1;
var olPrivate = 2;
var olConfidential = 3;

var ics = "BEGIN:VCALENDAR\n" +
"CALSCALE:GREGORIAN\n" +
"VERSION:2.0\n";

var ol = new ActiveXObject("outlook.application");
var calendar = ol.getnamespace("mapi").getdefaultfolder(olFolderCalendar).items;

function createEvent(item) {

var event = "BEGIN:VEVENT\n";

if (item.alldayevent == true) {
event += "DTSTART;VALUE=DATE:" + formatDate(item.start) + "\n";
if (item.isrecurring == false) {
event += "DTEND;VALUE=DATE:" + formatDate(item.end) + "\n";
}
} else {
event += "DTSTART;TZID=Europe/Bratislava:" +
formatDateTime(item.start) + "\n";
event += "DTEND;TZID=Europe/Bratislava:" +
formatDateTime(item.end) + "\n";
}

if (item.isrecurring == true) {
event += createReoccuringEvent(item);
}

event += "LOCATION:" + item.location + "\n";
event += "SUMMARY:" + item.subject + "\n";

if (item.categories.length < 1) {
event += "CATEGORIES:(none)\n";
} else {
event += "CATEGORIES:" + item.categories + "\n";
}

if (item.sensitivity == olNormal) {
event += "CLASS:PUBLIC\n";
} else if (item.sensitivity == olPersonal) {
event += "CLASS:CONFIDENTIAL\n";
} else {
event += "CLASS:PRIVATE\n";
}

if (includeBody) {
event += "DESCRIPTION:" + cleanLineEndings(item.body) + "\n";
}
if (includeAlarm) {
if (item.reminderminutesbeforestart > 0){
event += "BEGIN:VALARM\n";
event += "TRIGGER:-PT" + item.reminderminutesbeforestart + "M\n";
event += "ACTION:DISPLAY\nDESCRIPTION:Reminder\nEND:VALARM\n";
}
}
event += "END:VEVENT\n";

return event;
}
function createReoccuringEvent(item) {

var recurEvent = "RRULE:";

var pattern = item.getrecurrencepattern;
var patternType = pattern.recurrencetype;

if (patternType == olRecursDaily) {
recurEvent += "FREQ=DAILY";
if (pattern.noenddate != true) {
recurEvent += ";UNTIL=" +
formatDateTime(pattern.patternenddate);
recurEvent = recurEvent.replace(/T000000/g,"T235959");
}
recurEvent += ";INTERVAL=" & pattern.interval;

} else if (patternType == olRecursMonthly) {

recurEvent += "FREQ=MONTHLY";
if (pattern.noenddate != true) {
recurEvent += ";UNTIL=" +
formatDateTime(pattern.patternenddate);
}
recurEvent += ";INTERVAL=" + pattern.interval;
recurEvent += ";BYMONTHDAY=" + pattern.dayofmonth;

} else if (patternType == olRecursMonthNth) {

recurEvent += "FREQ=MONTHLY";
if (pattern.noenddate != true) {
recurEvent += ";UNTIL=" +
formatDateTime(pattern.patternenddate);
}

recurEvent += ";INTERVAL=" + pattern.interval;
if (pattern.instance == 5) {
recurEvent += ";BYWEEK=-1;BYDAY=" & daysOfWeek("", pattern);
} else {
recurEvent += ";BYDAY=" +
daysOfWeek(weekNum(pattern.instance), pattern);
}

} else if (patternType == olRecursWeekly) {

recurEvent += "FREQ=WEEKLY";
if (pattern.noenddate != true) {
recurEvent += ";UNTIL=" +
formatDateTime(pattern.patternenddate);
}
recurEvent += ";INTERVAL=" + pattern.interval;
recurEvent += ";BYDAY=" + daysOfWeek("", pattern);

} else if (patternType == olRecursYearly) {

recurEvent += "FREQ=YEARLY";
if (pattern.noenddate != true) {
recurEvent += ";UNTIL=" +
formatDateTime(pattern.patternenddate);
}
recurEvent += ";INTERVAL=1";
recurEvent += ";BYDAY=" + daysOfWeek("", pattern);

} else if (patternType == olRecursYearNth) {

recurEvent += "FREQ=YEARLY";
if (pattern.noenddate != true) {
recurEvent += ";UNTIL=" +
formatDateTime(pattern.patternenddate);
}
recurEvent += ";BYMONTH=" + monthNum(pattern.monthofyear);
recurEvent += ";BYDAY=" +
daysOfWeek(weekNum(pattern.instance), pattern);

}
recurEvent += "\n";

return recurEvent;
}

function formatDate(date) {
var oDate = new Date(date);
icaldate = "" + oDate.getFullYear() + padzero((oDate.getMonth() +
1)) + padzero((oDate.getDate()));
return icaldate;
}

function formatDateTime(date) {
var oDate = new Date(date);
icaldate = "" + oDate.getFullYear() + padzero((oDate.getMonth() +
1)) + padzero((oDate.getDate())) +
"T" + padzero(oDate.getHours()) + padzero(oDate.getMinutes())
+ padzero(oDate.getSeconds());
return icaldate;
}

function daysOfWeek(week, pattern) {
var mask = pattern.dayofweekmask;
var daysOfWeek = "";

if (mask & olMonday) {
daysOfWeek = week + "MO";
}
if (mask & olTuesday) {
if (daysOfWeek != "") { daysOfWeek += ","; }
daysOfWeek += week + "TU";
}
if (mask & olWednesday) {
if (daysOfWeek != "") { daysOfWeek += ","; }
daysOfWeek += week + "WE";
}
if (mask & olThursday) {
if (daysOfWeek != "") { daysOfWeek += ","; }
daysOfWeek += week + "TH";
}
if (mask & olFriday) {
if (daysOfWeek != "") { daysOfWeek += ","; }
daysOfWeek += week + "FR";
}
if (mask & olSaturday) {
if (daysOfWeek != "") { daysOfWeek += ","; }
daysOfWeek += week + "SA";
}
if (mask & olSunday) {
if (daysOfWeek != "") { daysOfWeek += ","; }
daysOfWeek += week + "SU";
}

return daysOfWeek;
}

function weekNum(week) {
if (week == 5) {
week = "-1";
} else {
padzero(week);
}
return week;
}

function monthNum(month) {
var month = month + "";
month = month.toLowerCase().substr(0,3);

var monthNum = 0;

if (month == "jan") {
monthNum = 1;
} else if (month == "feb") {
monthNum = 2;
} else if (month == "mar") {
monthNum = 3;
} else if (month == "apr") {
monthNum = 4;
} else if (month == "may") {
monthNum = 5;
} else if (month == "jun") {
monthNum = 6;
} else if (month == "jul") {
monthNum = 7;
} else if (month == "aug") {
monthNum = 8;
} else if (month == "sep") {
monthNum = 9;
} else if (month == "oct") {
monthNum = 10;
} else if (month == "nov") {
monthNum = 11;
} else if (month == "dec") {
monthNum = 12;
} else {
monthNum = month;
}

return monthNum;
}

function padzero(string) {
if (String(string).length < 2) {
string = "0" + string;
}
return string;
}

function cleanLineEndings(string) {
string = string.replace(/\r/g,'\n');
string = string.replace(/\n\n/g,'\n');
string = string.replace(/\n/g,'\\n');
string = string.replace(/,/g,'\,');
return string;
}

var today = new Date();
var total = calendar.Count;
var exportItem = true;

for (var i=1; i<=total; i++) {

try {
var rItem = calendar(i);
var item = new ActiveXObject("Redemption.SafeContactItem");
item.item = rItem;
includeBody = true;
} catch(e) {
var item = calendar(i);
}

if ((exportMode == "not") || (exportMode == "only")) {

exportItem = (exportMode=="not") ? true : false;

for (var j=0; j < categories.length; j++) {
if (item.categories.indexOf(categories[j]) != -1) {
exportItem = (exportMode == "only") ? true : false;
}
continue;
}
}

if (exportItem) {
if (!item.isrecurring) {
var date = new Date(item.end);
if (Math.round(((today - date) / (86400000))) >
includeHistory) { continue; }
}
ics += createEvent(item);
}

}

ics += "END:VCALENDAR\n";

var fso = new ActiveXObject("Scripting.FileSystemObject");
var icsFH = fso.CreateTextFile(icsFilename, true);
icsFH.Write(ics);
icsFH.Close();

WScript.Quit();

Po spustení skriptu sa vyberú udalosti mladšie ako 30 dní (v skripte tento parameter nájdete) a vytvorený súbor bude calendar.ics, ktorý je možné importovať do iných kalendárových programov.
Ja napríklad mám problém: chcem si kalendár z Outlooku pozerať v telefóne. Môj telefón našťastie vie „subscribnúť“ kalendár vo formáte .ics, takže ak v telefóne nakonfigurujem, že chcem vidieť udalosti uložené na http://www.example.org/calendar.ics, tak mi ich bude zobrazovať ako ďalší z kalendárov (v aplikácii Calendar mám možnosť použiť NARAZ viac kalendárov z rôznych zdrojov). No a vyššie uvedený skript práve vyrába .ics súbor z dáta v kalendári Outlooku.
Takýto súbor môžete jednorázovo importnúť do iných kalendárových aplikácii (pozor, nie je to synchronizované – jednorazovka znamená, že opúšťate MS Outlook kalendár). Pre synchronizáciu je možné ale použiť aj tento skript. Pravideľne ho spúšťajte, vygenerovaný súbor ukladajte na svoj hosting (môžete použiť aj DROPBOX aj BOX.NET). Takto uložený .ics je teda neustále aktualizovaný. V inej kalendárovej aplikácii teraz nakonfigurujte SUBSCRIBE externého kalendára. Tj. nie import ale trvalé „nazeranie“ do kalednárových dát mimo nej. To je to, čo som spomínal, že mám v telefóne, to isté vie aj Google Calendar (bacha, ten ale update zo zadanej URL robí sporadicky).

Written by rony