diff --git a/samples/sharepoint-calendar-event-sync/README.md b/samples/sharepoint-calendar-event-sync/README.md new file mode 100644 index 00000000..09f21932 --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/README.md @@ -0,0 +1,159 @@ +# SharePoint Calendar Event Sync + +## Summary + +This Power Platform sample demonstrates how to automatically sync Outlook/Teams calendar events to a SharePoint list using Power Automate. + +The flow retrieves events from a specified calendar, checks for duplicates using the event iCalUId (Meeting ID), and creates new SharePoint list items with details such as subject, organizer, attendees, location, start/end time, and description. + +This solution is provided as a proof-of-concept (POC) for customization or extension. + +![Preview - Flow](./assets/screenshot.png) + +## Applies to + +![Power Automate](https://img.shields.io/badge/Power%20Automate-Yes-green "Yes") + +## Compatibility + +![Experimental Features](https://img.shields.io/badge/Experimental%20Features-No-red.svg "Does not on experimental features") + +## Features + +- ✅ Sync Outlook/Teams events to SharePoint automatically +- ✅ Prevent duplicate entries using Meeting ID +- ✅ Map all key event details including attendees, organizer, and location +- ✅ Handles HTML content cleanup in event descriptions +- ✅ Configurable concurrency (up to 20 parallel executions) + +## Prerequisites + +- Access to a SharePoint Online site with the target list +- Permissions to read calendar events from Outlook or Teams +- Power Automate flow owner must have access to both SharePoint and Microsoft 365 (Outlook/Teams) connectors + +## Solution Components + +### Data Sources +- SharePoint +- Microsoft Outlook / Teams Calendar + +### Flow +- **Calendar Event Sync** - Main automation flow + +## Installation + +### Step 1: Create Supporting SharePoint List + +Create a new list named **Calendar Events** in your SharePoint site with the following columns: + +| Internal Name | Display Name | Type | Notes | +|---------------|--------------|------|-------| +| Title | Title | Single line of text | Use event subject | +| Organizer1 | Organizer1 | Single line of text | Event organizer | +| Attendees | Attendees | Multiple lines of text | Required + optional attendees | +| StartTime | Start Time | Date and Time | Start time of the event | +| EndTime | End Time | Date and Time | End time of the event | +| Location | Location | Single line of text | Event location | +| Body | Description | Multiple lines of text | Event body / description | +| MeetingID | Meeting ID | Single line of text | iCalUId to prevent duplicates | + + +### Step 2: Import Power Platform Solution + +1. Download the **managed** solution `.zip` from the solution folder +2. In [Power Apps Maker Portal](https://make.powerapps.com), choose your environment +3. Navigate to **Solutions** > **Import solution** > **Browse** +4. Select the downloaded solution file +5. Connect the SharePoint and Outlook connectors when prompted +6. Click **Import** +7. Share the flow with any additional users who may need to view or edit it + +### Alternative: Using Source Code + +You can also pack the source code using the Power Apps CLI: + +```bash +pac solution pack --folder --zipfile --processCanvasApps +``` + +- Replace `` with the local path to the sourcecode folder +- Replace `` with the path of the solution .zip + +Then import the solution as described above. + +## Flow Overview + +### Process Flow +1. **Get Calendar Events** – Retrieves events from the selected Outlook/Teams calendar between a start and end date +2. **For Each Event** – Loops through each event retrieved +3. **Check for Duplicates** – Uses a SharePoint Get items action to see if the event's iCalUId (Meeting ID) already exists +4. **Create SharePoint Item** – If the event is not found, creates a new item in the SharePoint list + +### Field Mapping + +| SharePoint Field | Mapped Flow Value | +|------------------|-------------------| +| Title | Event subject | +| Organizer1 | Event organizer | +| Attendees | Required + optional attendees | +| StartTime | Event start with timezone | +| EndTime | Event end with timezone | +| Location | Event location object | +| Body | Event body with HTML tags removed/replaced | +| MeetingID | Event iCalUId | + +### Performance +- **Concurrency**: The flow is configured to run up to 20 repetitions in parallel for faster processing + +## Usage + +1. The flow runs on a schedule or manually to retrieve calendar events +2. Events are checked against the SharePoint list to avoid duplicates +3. New events are added automatically to the list with all mapped details +4. Your SharePoint list stays in sync with the selected calendar + +## Configuration + +To customize the solution: +- Modify the calendar source in the flow +- Adjust the date range for event retrieval +- Update field mappings as needed +- Configure the schedule trigger frequency +- Update SharePoint URL: Change the SharePoint URL in the flow from "Sharepointurl (sai_Sharepointurl)": "https://tenant.sharepoint.com/sites/sitename" to match your specific tenant and site name (e.g., "Sharepointurl (sai_Sharepointurl)": "https://tenant.sharepoint.com/sites/sitename") +- Update SharePoint URL: Change the SharePoint URL in the Environment variable from defaultvalue of "Sharepointurl (sai_Sharepointurl)": "https://tenant.sharepoint.com/sites/sitename" + +## Version History + +| Version | Date | Comments | +|---------|------|----------| +| 1.0.0.0 | Aug 30, 2025 | Initial release | + +## Contributors + +- [Bandaru Sai](https://github.com/saiiiiiii) + +## Support + +This sample is provided as-is. If you encounter issues: + +- [Create a new issue](https://github.com/pnp/powerplatform-samples/issues) +- [Ask a question](https://github.com/pnp/powerplatform-samples/discussions) +- [Suggest an improvement](https://github.com/pnp/powerplatform-samples/discussions) + + +## Help + +We do not support samples, but this community is always willing to help, and we want to improve these samples. We use GitHub to track issues, which makes it easy for community members to volunteer their time and help resolve issues. + +If you encounter any issues while using this sample, you can [create a new issue](https://github.com/pnp/powerplatform-samples/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=bug-report.yml&sample=sharepoint-calendar-event-sync&authors=@bandarusai&title=sharepoint-calendar-event-sync%20-%20). + +For questions regarding this sample, [create a new question](https://github.com/pnp/powerplatform-samples/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=question.yml&sample=sharepoint-calendar-event-sync&authors=@bandarusai&title=sharepoint-calendar-event-sync%20-%20). + +Finally, if you have an idea for improvement, [make a suggestion](https://github.com/pnp/powerplatform-samples/issues/new?assignees=&labels=Needs%3A+Triage+%3Amag%3A%2Ctype%3Abug-suspected&template=suggestion.yml&sample=sharepoint-calendar-event-sync&authors=@bandarusai&title=sharepoint-calendar-event-sync%20-%20). + +## Disclaimer + +**THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.** + + \ No newline at end of file diff --git a/samples/sharepoint-calendar-event-sync/assets/sample.json b/samples/sharepoint-calendar-event-sync/assets/sample.json new file mode 100644 index 00000000..529b0120 --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/assets/sample.json @@ -0,0 +1,55 @@ +[ + { + "$schema": "https://developer.microsoft.com/en-us/json-schemas/pnp/samples/v1.0/metadata-schema.json", + "name": "pnp-powerplatform-samples-sharepoint-calendar-event-sync", + "version": "1.0.0.0", + "source": "pnp", + "creationDateTime": "2025-08-31T00:00:00.000Z", + "updateDateTime": "2025-08-31T00:00:00.000Z", + "title": "Sharepoint Calendar Event Sync", + "shortDescription": "This is a proof of concept Power Platform solution for Sync Outlook Events to a SharePoint list using Power Automate.", + "longDescription": [ + "This is a proof of concept Power Platform solution for how to automatically Sync Outlook/Teams calendar events to a SharePoint list using Power Automate." + ], + "url": "https://github.com/pnp/powerplatform-samples/tree/main/samples/sharepoint-calendar-event-sync", + "products": [ + "Power Automate", + "Power Platform" + ], + "tags": [ + "SharePoint", + "Power Automate" + ], + "categories": [ + "POWERAUTOMATE" + ], + "metadata": [ + { + "key": "POWERAPPS-MANIFEST-VERSION", + "value": "0.20" + } + ], + "thumbnails": [ + { + "type": "image", + "order": 100, + "url": "https://github.com/pnp/powerplatform-samples/blob/main/samples/sharepoint-calendar-event-sync/assets/screenshot.png?raw=true", + "alt": "Preview" + } + ], + "authors": [ + { + "gitHubAccount": "saiiiiiii", + "pictureUrl": "https://github.com/saiiiiiii.png", + "name": "Sai Bandaru" + } + ], + "references": [ + { + "name": "Create a cloud flow in Power Automate", + "description": "Create a cloud flow in Power Automate", + "url": "https://learn.microsoft.com/en-us/power-automate/get-started-logic-flow?tabs=classic-designer" + } + ] + } +] diff --git a/samples/sharepoint-calendar-event-sync/assets/screenshot.png b/samples/sharepoint-calendar-event-sync/assets/screenshot.png new file mode 100644 index 00000000..6354c426 Binary files /dev/null and b/samples/sharepoint-calendar-event-sync/assets/screenshot.png differ diff --git a/samples/sharepoint-calendar-event-sync/solution/SharePointCalendarEventSync_1_0_0_1_managed.zip.zip b/samples/sharepoint-calendar-event-sync/solution/SharePointCalendarEventSync_1_0_0_1_managed.zip.zip new file mode 100644 index 00000000..9fbf337f Binary files /dev/null and b/samples/sharepoint-calendar-event-sync/solution/SharePointCalendarEventSync_1_0_0_1_managed.zip.zip differ diff --git a/samples/sharepoint-calendar-event-sync/sourcecode/src/Other/customizations.xml b/samples/sharepoint-calendar-event-sync/sourcecode/src/Other/customizations.xml new file mode 100644 index 00000000..a483563f --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/sourcecode/src/Other/customizations.xml @@ -0,0 +1,43 @@ + + + + + + /Workflows/SharePointCalendarEventSync-A1F0FBD5-3A86-F011-B4CC-000D3A35CE29.json + 1 + 0 + 5 + 0 + 4 + 0 + 0 + 0 + 0 + 0 + 1 + 2 + 1 + 1 + 1.0.0.0 + 1 + 0 + 1 + 0 + none + + + + + + + + + + + + + + + 1033 + + \ No newline at end of file diff --git a/samples/sharepoint-calendar-event-sync/sourcecode/src/Other/solution.xml b/samples/sharepoint-calendar-event-sync/sourcecode/src/Other/solution.xml new file mode 100644 index 00000000..95f838ae --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/sourcecode/src/Other/solution.xml @@ -0,0 +1,93 @@ + + + SharePointCalendarEventSync + + + + + 1.0.0.1 + 1 + + sai + + + + + + + sai + 91851 + +
+ 1 + 1 + + + + + + + + + + + + + + + + 1 + + + + + + + + +
+
+ 2 + 1 + + + + + + + + + + + + + + + + 1 + + + + + + + + +
+
+
+ + + + + + + + + + + + + +
+
\ No newline at end of file diff --git a/samples/sharepoint-calendar-event-sync/sourcecode/src/Workflows/SharePointCalendarEventSync-A1F0FBD5-3A86-F011-B4CC-000D3A35CE29.json b/samples/sharepoint-calendar-event-sync/sourcecode/src/Workflows/SharePointCalendarEventSync-A1F0FBD5-3A86-F011-B4CC-000D3A35CE29.json new file mode 100644 index 00000000..a65c130b --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/sourcecode/src/Workflows/SharePointCalendarEventSync-A1F0FBD5-3A86-F011-B4CC-000D3A35CE29.json @@ -0,0 +1,180 @@ +{ + "properties": { + "connectionReferences": { + "shared_office365": { + "runtimeSource": "invoker", + "connection": { + "connectionReferenceLogicalName": "sai_sharedoffice365_959bd" + }, + "api": { + "name": "shared_office365" + } + }, + "shared_sharepointonline": { + "runtimeSource": "invoker", + "connection": { + "connectionReferenceLogicalName": "sai_sharedsharepointonline_6c509" + }, + "api": { + "name": "shared_sharepointonline" + } + } + }, + "definition": { + "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", + "contentVersion": "1.0.0.0", + "parameters": { + "$authentication": { + "defaultValue": {}, + "type": "SecureObject" + }, + "$connections": { + "defaultValue": {}, + "type": "Object" + }, + "Sharepointurl (sai_Sharepointurl)": { + "defaultValue": "https://tenant.sharepoint.com/sites/saitesting2", + "type": "String", + "metadata": { + "schemaName": "sai_Sharepointurl" + } + }, + "Outlook Meetings (sai_OutlookMeetings)": { + "defaultValue": "Outlook Meetings", + "type": "String", + "metadata": { + "schemaName": "sai_OutlookMeetings" + } + } + }, + "triggers": { + "manual": { + "metadata": { + "operationMetadataId": "a94ec0ef-9c6a-4502-81aa-c791472c8a4d" + }, + "type": "Request", + "kind": "Button", + "inputs": { + "schema": { + "type": "object", + "properties": {}, + "required": [] + } + } + } + }, + "actions": { + "Get_calendar_view_of_events_(V3)": { + "runAfter": {}, + "metadata": { + "operationMetadataId": "f7539677-945d-4c60-bd3a-a63920fa266c" + }, + "type": "OpenApiConnection", + "inputs": { + "parameters": { + "calendarId": "AQMkAGQ4YmNlMzRlLWE5ZTQtNGQwZC04ZTM5LWI5MmQ1MmU0MzEzZQBGAAADoidONSuajE27-_wcYG8d7AcAAYdxNrC1AkK_bLGB0_90vgAAAgEGAAAAAYdxNrC1AkK_bLGB0_90vgAAAniJAAAA", + "startDateTimeUtc": "2025-01-01T00:00:00Z", + "endDateTimeUtc": "@utcNow()" + }, + "host": { + "apiId": "/providers/Microsoft.PowerApps/apis/shared_office365", + "operationId": "GetEventsCalendarViewV3", + "connectionName": "shared_office365" + } + } + }, + "Apply_to_each": { + "foreach": "@outputs('Get_calendar_view_of_events_(V3)')?['body/value']", + "actions": { + "Get_items": { + "metadata": { + "operationMetadataId": "d5095882-8eb7-4c0f-8a8a-c07f2e5dcb88" + }, + "type": "OpenApiConnection", + "inputs": { + "parameters": { + "dataset": "@parameters('Sharepointurl (sai_Sharepointurl)')", + "table": "@parameters('Outlook Meetings (sai_OutlookMeetings)')", + "$filter": "MeetingID eq '@{items('Apply_to_each')?['iCalUId']}'" + }, + "host": { + "apiId": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline", + "operationId": "GetItems", + "connectionName": "shared_sharepointonline" + } + } + }, + "Condition": { + "actions": { + "Create_item": { + "metadata": { + "operationMetadataId": "65427292-572a-4fd5-a385-3f10325d90b4" + }, + "type": "OpenApiConnection", + "inputs": { + "parameters": { + "dataset": "@parameters('Sharepointurl (sai_Sharepointurl)')", + "table": "@parameters('Outlook Meetings (sai_OutlookMeetings)')", + "view": "840f4894-ffb1-41fe-b65d-3f8b4a038e61", + "item/Title": "@items('Apply_to_each')?['subject']", + "item/Attendees": "@{items('Apply_to_each')?['requiredAttendees']}@{items('Apply_to_each')?['optionalAttendees']}", + "item/StartTime": "@items('Apply_to_each')?['startWithTimeZone']", + "item/EndTime": "@items('Apply_to_each')?['endWithTimeZone']", + "item/Location": "@items('Apply_to_each')?['location']", + "item/Body": "@replace(replace(replace(replace(items('Apply_to_each')?['body'],'
','\\n'),'
','\\n'),'

','\\n'),'

','')", + "item/MeetingID": "@items('Apply_to_each')?['iCalUId']", + "item/Organizer1": "@items('Apply_to_each')?['organizer']" + }, + "host": { + "apiId": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline", + "operationId": "PostItem", + "connectionName": "shared_sharepointonline" + } + } + } + }, + "runAfter": { + "Get_items": [ + "Succeeded" + ] + }, + "else": { + "actions": {} + }, + "expression": { + "and": [ + { + "equals": [ + "@length(body('Get_items')?['value'])", + 0 + ] + } + ] + }, + "metadata": { + "operationMetadataId": "74980576-0e28-4578-a76e-d9fa34c3fea6" + }, + "type": "If" + } + }, + "runAfter": { + "Get_calendar_view_of_events_(V3)": [ + "Succeeded" + ] + }, + "metadata": { + "operationMetadataId": "fe9c2204-a14f-46eb-918c-98eeb122f794" + }, + "type": "Foreach", + "runtimeConfiguration": { + "concurrency": { + "repetitions": 20 + } + } + } + } + }, + "templateName": null + }, + "schemaVersion": "1.0.0.0" +} \ No newline at end of file diff --git a/samples/sharepoint-calendar-event-sync/sourcecode/src/environmentvariabledefinitions/sai_OutlookMeetings/environmentvariabledefinition.xml b/samples/sharepoint-calendar-event-sync/sourcecode/src/environmentvariabledefinitions/sai_OutlookMeetings/environmentvariabledefinition.xml new file mode 100644 index 00000000..38ba080e --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/sourcecode/src/environmentvariabledefinitions/sai_OutlookMeetings/environmentvariabledefinition.xml @@ -0,0 +1,11 @@ + + Outlook Meetings + + + 1.0.0.0 + 1 + 0 + 0 + 100000000 + \ No newline at end of file diff --git a/samples/sharepoint-calendar-event-sync/sourcecode/src/environmentvariabledefinitions/sai_Sharepointurl/environmentvariabledefinition.xml b/samples/sharepoint-calendar-event-sync/sourcecode/src/environmentvariabledefinitions/sai_Sharepointurl/environmentvariabledefinition.xml new file mode 100644 index 00000000..c0274d3c --- /dev/null +++ b/samples/sharepoint-calendar-event-sync/sourcecode/src/environmentvariabledefinitions/sai_Sharepointurl/environmentvariabledefinition.xml @@ -0,0 +1,11 @@ + + https://tenant.sharepoint.com/sites/saitesting2 + + + 1.0.0.0 + 1 + 0 + 0 + 100000000 + \ No newline at end of file