This guide explains how to create a Power Automate workflow which can enable repeating events on a SharePoint calendar.
The Copy Event Workflow includes these features:
The Delete Series Workflow includes these features:
It is recommended to watch the video before building your workflows.
Preview of calendar view with Copy Event option added to UI:
You will be creating a workflow that can be used at any time by selecting a calendar event and triggering the "Copy Event" workflow that we will create.
Be sure to adjust the run only users permissions on your workflow to allow other users the ability to trigger the workflow from the SharePoint interface.
You should begin by creating a new SharePoint list then add two date fields to your list "Start" and "End" with the time option enabled. Finally, create a new Calendar View referencing the Start and End fields.
Be sure to create at least a couple of dummy records for testing purposes.
Author's note: One of the most challenging aspects of this workflow is handling time changes for Daylight Savings Time. In general, copying events is straightforward, but handling Daylight Savings Time is not. Without adjusting for this, events copied from one part of the year are an hour off in the other part of the year. This workflow detects this change by comparing the difference in hours between the source event start time and UTC and compares that to the newly copied event. The copied event is adjusted accordingly. This works because UTC does not change regardless of Daylight Savings Time. It's a tricky concept, but this adjustment is required to avoid the problem of events being off one hour in a repeating series.
Begin by creating a new Flow using the For a Selected Item trigger condition.
Add a new automated cloud flow:
Click "Skip" at the first screen:
Click on the Flow trigger condition then search for "For a Selected Item" and select it:
Now we can begin building our Flow. Select your SharePoint calendar site and list, then enter the input parameters exactly as shown below. Note that the input parameters should be set as required.
Initialize a new integer variable "loopCounter" as shown. This will be used in our loop below:
Add a Get Item block to retrieve all the properties of the selected item:
Add a compose block to calculate the number of hours difference between the local time zone and UTC.
Look up your time zone reference here.
Code snippet:
div(sub(ticks(outputs('Get_item')?['body/Start']),ticks(convertTimeZone(outputs('Get_item')?['body/Start'],'UTC','Eastern Standard Time','u'))),36000000000)
Next add a Do Until loop using the "loopCounter" variable and the "Count" input parameter as shown:
Add a first action within the loop "Increment Variable" to increment the "loopCounter" variable as shown:
Next add a Add to time block to add time to the Start date time as shown. Use the calculation provided. Note that this factors in an "Interval" in case the user wants alternating weeks or months for example.
Code snippet:
mul(variables('loopCounter'),triggerBody()?['number'])
Next add a Add to time block to add time to the End date time as shown. Use the calculation provided. Note that this factors in an "Interval" in case the user wants alternating weeks or months for example.
Code snippet:
mul(variables('loopCounter'),triggerBody()?['number'])
Add a compose block to calculate the number of hours difference between the local time zone and UTC FOR THIS EVENT.
Code snippet:
div(sub(ticks(body('Add_to_time_Start')),ticks(convertTimeZone(body('Add_to_time_Start'),'UTC','Eastern Standard Time','u'))),36000000000)
Now we can get the difference between the hours offset of the source event and the new event. This will be used to adjust if there was a daylight saving time difference when comparing the source event and the new event:
Code snippet:
sub(outputs('Compose_ThisUTCDifference'),outputs('Compose_UTCDifference'))
The difference will be used to offset the new event start time:
And also the difference will be used to offset the new event end time:
Finally we can create the new calendar event:
This flow begins like the last using the For a selected item trigger.
In the workflow start by getting the properties of the selected item:
Use the Get items function with a filter to match the Title field for the event:
Create an apply to each loop:
Add a condition using the formulas provided to match the start time of the event:
Code snippets (substitute in your own time zone reference):
convertFromUtc(outputs('Get_item')?['body/Start'],'Eastern Standard Time','H:mm')
convertFromUtc(items('Apply_to_each')?['Start'],'Eastern Standard Time','H:mm')
Finally you can use the delete item action (inside the True branch):