Problem
You have a recurring event in your event list:
When you connect above list to Events ShortPoint element, you would not see the recurring event occurrences:
Reason
Recurrences have been handled differently in SharePoint and requesting all list items of calendar does not return all occurrences of events if its recurring event.
Solution
Step 1: Add Events ShortPoint element
In the page where you would want to add Events ShortPoint, add ShortPoint and select Events
Step 2: Connect using REST API Connection
Go to Connect Tab and select REST API Connection Type
In REST API URL, provide below URL:
<https://your-site>/_api/web/lists/getbytitle('<Events List Title>')/items?$select=*,Duration,RecurrenceData
<https://your-site>: Replace with your site URL (for example https://contoso.sharepoint.com)
<Events List Title>: Replace with title of your events list (for example Events)
Example URL: https://shortpoint.sharepoint.com/_api/web/lists/getbytitle('Calendar')/items?$select=*,Duration,RecurrenceData
Step 3: Use custom mapping to expand the recurrences of recurring event
Enable the Advanced Mapping and in Map Results and use the code given below:
Work around code to show events from the next few days:
// REST API URL should look like this (you can use either getbyid or getbyname) // https://MYSHAREPOINTSITE.sharepoint.com/_api/web/lists/getbyid('34ea5a3c-220d-49e0-9f38-528c70da81bd')/items?$select=*,Duration,RecurrenceData,EventType,MasterSeriesItemID var spEventsParser = { parseEvents: parseEvents, formatString: formatString, parseDate: parseDate, parseEvent: parseEvent, cloneObj: cloneObj }; function parseEvents(e, t, n) { for (var a = [], r = 0; r < e.length; r++)e[r]._SHORTPOINT_Recurring_Event_ID = r, a = a.concat(this.parseEvent(e[r], t, n)); return a; } function formatString(e) { var t = e.split("'"); return e = t.join(""), t = e.split('"'), e = t.join(""), t = e.split("="), (e = t.join(" ")).trim(), e.split(" "); } function parseDate(e, t) { if ("string" == typeof e) { if (t) { if (e.lastIndexOf("Z") == e.length - 1) { var n = e.substring(0, e.length - 1); return new Date(n); } return new Date(e); } return new Date(e); } return e; } function parseEvent(e, t, n) { if (e.fRecurrence) { t = t || this.parseDate(e.EventDate, e.fAllDayEvent), n = n || this.parseDate(e.EndDate, e.fAllDayEvent); var a = [], r = ["su", "mo", "tu", "we", "th", "fr", "sa"], D = ["first", "second", "third", "fourth"], s = 0, i = 0, f = /<windowEnd>(.+)<\/windowEnd>/.exec(e.RecurrenceData) || [], o = (f[0], f[1]); if (o && new Date(o) <= new Date) return []; if (-1 != e.RecurrenceData.indexOf("<repeatInstances>") && (s = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<repeatInstances>") + 17), s = parseInt(s.substring(0, s.indexOf("<")))), -1 != e.RecurrenceData.indexOf("<daily ")) if (x = (x = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<daily "))).substring(7, x.indexOf("/>") - 1), -1 != (y = this.formatString(x)).indexOf("dayFrequency")) for (var c = parseInt(y[y.indexOf("dayFrequency") + 1]), g = !0, d = this.parseDate(e.EventDate, e.fAllDayEvent); g;) { if (i++, new Date(d).getTime() >= t.getTime()) { var u = new Date(d), l = e.Duration % 86400; u.setSeconds(u.getSeconds() + l), (m = this.cloneObj(e)).EventDate = new Date(d), m.EndDate = u, m.fRecurrence = !1, m.Id = e.Id, m.ID = m.Id, a.push(m); } d.setDate(d.getDate() + c), (new Date(d) > n || s > 0 && s <= i) && (g = !1); } else -1 != y.indexOf("weekday") && (e.RecurrenceData = e.RecurrenceData + "<weekly mo='TRUE' tu='TRUE' we='TRUE' th='TRUE' fr='TRUE' weekFrequency='1' />"); if (-1 != e.RecurrenceData.indexOf("<weekly ")) { x = (x = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<weekly "))).substring(8, x.indexOf("/>") - 1); for (var y = this.formatString(x), h = (c = parseInt(y[y.indexOf("weekFrequency") + 1]), g = !0, (d = this.parseDate(e.EventDate, e.fAllDayEvent)).getDay()); g;) { for (var w = h; w < 7; w++) { if (-1 != y.indexOf(r[w]) && (s > i || 0 == s)) if (i++, new Date(d).getTime() >= t.getTime()) (I = new Date(d)).setDate(I.getDate() + (w - h)), (u = new Date(I)).setSeconds(u.getSeconds() + e.Duration), (m = this.cloneObj(e)).EventDate = new Date(I), m.EndDate = u, m.fRecurrence = !1, m.Id = e.Id, m.ID = m.Id, a.push(m); } d.setDate(d.getDate() + (7 * c - h)), h = 0, (new Date(d) > n || s > 0 && s <= i) && (g = !1); } } if (-1 != e.RecurrenceData.indexOf("<monthly ")) { x = (x = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<monthly "))).substring(9, x.indexOf("/>") - 1); y = this.formatString(x), c = parseInt(y[y.indexOf("monthFrequency") + 1]), g = !0, d = this.parseDate(e.EventDate, e.fAllDayEvent); for (var O = parseInt(y[y.indexOf("day") + 1]); g;) { if (i++, new Date(d).getTime() >= t.getTime()) if ((I = new Date(d)).setDate(O), I.getMonth() == d.getMonth()) (u = new Date(I)).setSeconds(u.getSeconds() + e.Duration), (m = this.cloneObj(e)).EventDate = new Date(I), m.EndDate = u, m.fRecurrence = !1, m.Id = e.Id, m.ID = m.Id, a.push(m); d.setMonth(d.getMonth() + c), (new Date(d) > n || s > 0 && s <= i) && (g = !1); } } if (-1 != e.RecurrenceData.indexOf("<monthlyByDay ")) { x = (x = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<monthlyByDay "))).substring(14, x.indexOf("/>") - 1); y = this.formatString(x), c = parseInt(y[y.indexOf("monthFrequency") + 1]), g = !0, d = this.parseDate(e.EventDate, e.fAllDayEvent); for (var v = y[y.indexOf("weekdayOfMonth") + 1], E = new Date; g;) { if (i++, new Date(d).getTime() >= t.getTime()) { if ((I = new Date(d)).setDate(1), -1 != y.indexOf("weekday")) if (0 == I.getDay() ? I.setDate(I.getDate() + 1) : 6 == I.getDay() && I.setDate(I.getDate() + 2), "last" == v) { for (; I.getMonth() == d.getMonth();)E = new Date(I), 5 == I.getDay() ? I.setDate(I.getDate() + 3) : I.setDate(I.getDate() + 1); I = new Date(E); } else for (w = 0; w < D.indexOf(v); w++)5 == I.getDay() ? I.setDate(I.getDate() + 3) : I.setDate(I.getDate() + 1); else if (-1 != y.indexOf("weekend_day")) if (0 != I.getDay() && 6 != I.getDay() && I.setDate(I.getDate() + (6 - I.getDay())), "last" == v) { for (; I.getMonth() == d.getMonth();)E = new Date(I), 0 == I.getDay() ? I.setDate(I.getDate() + 6) : I.setDate(I.getDate() + 1); I = new Date(E); } else for (w = 0; w < D.indexOf(v); w++)0 == I.getDay() ? I.setDate(I.getDate() + 6) : I.setDate(I.getDate() + 1); else if (-1 != y.indexOf("day")) { if ("last" == v) (I = I.setMonth(I.getMonth() + 1)).setDate(0); else I.setDate(I.getDate() + D.indexOf(v)); } else { for (w = 0; w < r.length; w++)-1 != y.indexOf(r[w]) && (I.getDay() > w ? I.setDate(I.getDate() + (7 - (I.getDay() - w))) : I.setDate(I.getDate() + (w - I.getDay()))); if ("last" == v) { for (; I.getMonth() == d.getMonth();)E = new Date(I), I.setDate(I.getDate() + 7); I = new Date(E); } else for (w = 0; w < D.indexOf(v); w++)I.setDate(I.getDate() + 7); } if (I.getMonth() == d.getMonth()) (u = new Date(I)).setSeconds(u.getSeconds() + e.Duration), (m = this.cloneObj(e)).EventDate = new Date(I), m.EndDate = u, m.fRecurrence = !1, m.Id = e.Id, m.ID = m.Id, a.push(m); } d.setMonth(d.getMonth() + c), (new Date(d) > n || s > 0 && s <= i) && (g = !1); } } if (-1 != e.RecurrenceData.indexOf("<yearly ")) { x = (x = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<yearly "))).substring(8, x.indexOf("/>") - 1); y = this.formatString(x), c = parseInt(y[y.indexOf("yearFrequency") + 1]), g = !0, d = this.parseDate(e.EventDate, e.fAllDayEvent); var p = parseInt(y[y.indexOf("month") + 1]) - 1; for (O = parseInt(y[y.indexOf("day") + 1]); g;) { if ((I = new Date(d)).setMonth(p), I.setDate(O), new Date(d).getTime() <= I.getTime()) if (i++, new Date(d).getTime() >= t.getTime()) (u = new Date(I)).setSeconds(u.getSeconds() + e.Duration), (m = this.cloneObj(e)).EventDate = new Date(I), m.EndDate = u, m.fRecurrence = !1, m.Id = e.Id, m.ID = m.Id, a.push(m); d.setFullYear(d.getFullYear() + c), (new Date(d) > n || s > 0 && s <= i) && (g = !1); } } if (-1 != e.RecurrenceData.indexOf("<yearlyByDay ")) { var x; x = (x = e.RecurrenceData.substring(e.RecurrenceData.indexOf("<yearlyByDay "))).substring(13, x.indexOf("/>") - 1); for (y = this.formatString(x), c = parseInt(y[y.indexOf("yearFrequency") + 1]), g = !0, d = this.parseDate(e.EventDate, e.fAllDayEvent), p = parseInt(y[y.indexOf("month") + 1]) - 1, v = y[y.indexOf("weekdayOfMonth") + 1], O = 0, w = 0; w < r.length; w++)-1 != y.indexOf(r[w]) && "true" == y[y.indexOf(r[w]) + 1].toLowerCase() && (O = w); for (; g;) { var I; if ((I = new Date(d)).setMonth(p), new Date(d).getTime() <= I.getTime() && (i++, new Date(d).getTime() >= t.getTime())) { I.setDate(1); var m, R = I.getDay(); if (O < R ? I.setDate(I.getDate() + (7 - R + O)) : I.setDate(I.getDate() + (O - R)), "last" == v) for (E = new Date(I); E.getMonth() == p;)I = new Date(E), E.setDate(E.getDate() + 7); else I.setDate(I.getDate() + 7 * D.indexOf(v)); if (I.getMonth() == p) (u = new Date(I)).setSeconds(u.getSeconds() + e.Duration), (m = this.cloneObj(e)).EventDate = new Date(I), m.EndDate = u, m.fRecurrence = !1, m.Id = e.Id, m.ID = m.Id, a.push(m); } d.setFullYear(d.getFullYear() + c), d.setMonth(p), d.setDate(1), (new Date(d) > n || s > 0 && s <= i) && (g = !1); } } return a; } return e.EventDate = new Date(this.parseDate(e.EventDate, e.fAllDayEvent)), e.EndDate = new Date(this.parseDate(e.EndDate, e.fAllDayEvent)), t && n ? new Date(t) <= e.EventDate && new Date(n) >= e.EndDate ? [e] : [] : [e]; } function cloneObj(e) { var t; if (null == e || "object" != typeof e) return e; if (e instanceof Date) return (t = new Date).setTime(e.getTime()), t; if (e instanceof Array) { t = []; for (var n = 0, a = e.length; n < a; n++)t[n] = this.cloneObj(e[n]); return t; } if (e instanceof Object) { for (var r in t = {}, e) e.hasOwnProperty(r) && (t[r] = this.cloneObj(e[r])); return t; } throw new Error("Unable to copy obj! Its type isn't supported."); } // --- User Settings Start --- // Change number of days ahead to show: var numberOfDays = 20; // Enable or disable Daylight Saving Time functionality here (change to true/false) // If enableDayLightSaving is set to true and we're inside the configured DST period, then the time will be adjusted accordingly var enableDayLightSaving = true; // How many hours to add when DST is active? (usually +1) var dstHours = +1; // Set the period that DST starts and ends here // Note that there's no need to set the year // Start DST: 13 Mar, 02:00 — 1 hour forward var dstStartDate = new Date('Mach 13, 2000 02:00:00'); // End DST: 06 Nov, 02:00 — 1 hour backward var dstEndDate = new Date('November 06, 2000 02:00:00'); // Add an offset in hours to all the events var generalTimeOffset = 0; // --- User Settings End --- var todayDate = new Date(); todayDate.setHours(0, 0, 0, 0); var deadlineDate = new Date(todayDate); deadlineDate.setDate(todayDate.getDate() + numberOfDays); var items = data.d.results; return handleEvents(items, numberOfDays); function handleEvents(items, amountOfDays) { var _ = shortpoint.base.libs._; var $ = shortpoint.$; var DELETED_RECURRENCE_ITEM = 3; var MODIFIED_RECCURENCE_ITEM = 4; var exceptionalEvents = []; var resultEvents = []; items.forEach(function (event) { // Filter the events to get the regular and exceptional events arrays var isExceptionalItem = event.EventType == DELETED_RECURRENCE_ITEM || event.EventType == MODIFIED_RECCURENCE_ITEM; if (isExceptionalItem) { event.EventDate = new Date(event.EventDate); event.EndDate = new Date(event.EndDate); exceptionalEvents.push(event); } }); var parsedEvents = spEventsParser.parseEvents(items, null, deadlineDate); // Filtering out useless events to not loop over them later // 1. Occurances of a recurring event that was created in the past should be filtered out. // 2. Multi-day events that started in the past should be kept. var parsedEvents2 = _.filter(parsedEvents, function (event) { return todayDate < event.EventDate || (event.EventDate < todayDate && event.Duration > 86400); //86400 is 24h in seconds }); // If deleted or modified then we need to remove it from the itemsWithRecurrency array that was generated in spEventsParser.parseEvents parsedEvents2.forEach(function (event) { // Find all exceptions that match this recurring item's ID var exceptions = exceptionalEvents.filter(function (exceptionEvent) { if (exceptionEvent.MasterSeriesItemID == event.ID && exceptionEvent.EventDate.getFullYear() == event.EventDate.getFullYear() && exceptionEvent.EventDate.getMonth() == event.EventDate.getMonth() && exceptionEvent.EventDate.getDate() == event.EventDate.getDate() ) { return true; } return false; }); // If there are any exceptions for this event, then we push the modified, and not push the deleted ones if (exceptions.length) { var exceptionEvent = exceptions[0]; // take the exceptional event that we found (should be only 1 for each event in itemsWithRecurrency) // If the exceptional event is of type "deleted" then it won't be added to the list if (exceptionEvent.EventType == MODIFIED_RECCURENCE_ITEM) { // If it's a modified event then it will be added instead of the original. exceptionEvent.EventDate = spEventsParser.parseDate(exceptionEvent.EventDate, exceptionEvent.fAllDayEvent); exceptionEvent.EndDate = spEventsParser.parseDate(exceptionEvent.EndDate, exceptionEvent.fAllDayEvent); resultEvents.push(exceptionEvent); } } else { // Otherwise if we didn't find an exceptions for this event then we just push it. (wasn't modified or deleted) resultEvents.push(event); } }); resultEvents.forEach(function (event) { // #region Trim events that span multiple days so that they don't span longer than the number of days specified // (ex: event that starts few days ago and spans for 2 months will be trimmed to the number of days specified) event.OriginalEventDate = event.EventDate; // save original start date if (event.EventDate < todayDate && todayDate <= event.EndDate) { event.EventDate = todayDate; } event.OriginalEndDate = event.EndDate; // save original end date if (event.EventDate <= deadlineDate && event.EndDate > deadlineDate) { event.EndDate = deadlineDate; } // #endregion // #region Apply changes based on DST configuration var localTime = event.EventDate.getTime(); var localEndTime = event.EndDate.getTime(); var regionTimeoffset = dstHours * 60000; var applyDst = false; if (enableDayLightSaving && // Check if today is after DST start date dstStartDate.getMonth() < todayDate.getMonth() && dstStartDate.getDate() < todayDate.getDate() && dstStartDate.getHours() < todayDate.getHours() && dstStartDate.getMinutes() < todayDate.getMinutes() && // Check if today is before DST end date todayDate.getMonth() < dstEndDate.getMonth() && todayDate.getDate() < dstEndDate.getDate() && todayDate.getHours() < dstEndDate.getHours() && todayDate.getMinutes() < dstEndDate.getMinutes() ) { applyDst = true; } if (applyDst) { event.EventDate.setTime(localTime + regionTimeoffset); event.EndDate.setTime(localEndTime + regionTimeoffset); } // #endregion Apply changes based on DST configuration // #region Apply general time offset event.EventDate.setTime(event.EventDate.getTime() + (generalTimeOffset * 60000)); event.EndDate.setTime(event.EndDate.getTime() + (generalTimeOffset * 60000)); // #endregion Apply general time offset }); resultEvents = _.sortBy(resultEvents, function (item) { return item.EventDate; }); return resultEvents; }
There are some user setting variables in this script, you can edit them as you like.
Click on Connect
Step 4: Map Columns
In the Items tab, map the columns the way you want:
Display events form in a pop-up (Optional):
Map the url to the display form of the event and then add #Id in the Link field and select lightbox in Linking options
<https://your-site>/Lists/<Events List Title>/DispForm.aspx?ID=#DisplayId
<https://your-site>: Replace with your site URL (for example https://contoso.sharepoint.com)
<Events List Title>: Replace with title of your events list (for example Events)
Example URL: https://contoso.sharepoint.com/Lists/Events/DispForm.aspx?ID=
Click Insert + and you are done!
Now you can see the Events ShortPoint Element with the occurrence(s)!