Duplicate Microsoft Planner Plans

One of the most requested features on the UserVoice forum for Microsoft Planner is the ability to create a Microsoft Planner Templates and make new plans from it. Microsoft is working on this feature, but the ETA is still unknown. I got the same request and started working on a PowerShell script that allows you to duplicate plans. At the end of this article you will find the complete script, but first I will walk you through the steps.

We are going to use PowerShell and Microsoft Graph API to duplicate the plan. I use a custom connector to connect with Graph. If you haven’t used Graph with PowerShell before, make sure you read this step-by-step guide first Microsoft Graph with PowerShell here.

What is required to duplicate a plan

To duplicate a Microsoft Planner Plan we need to go through a lot of steps:

  • Get the Template Plan and New Plan id
  • Copy the template plan categories (for the labels)
  • Get all the buckets
  • Get all the task for each bucket
  • Adding the new buckets in the right order
  • Adding the task to each bucket in the right order
  • Add the descriptions for each task
  • Add checklists if they exist

I will go through every step so you can modify it to your own needs.

Creating Microsoft Planner Templates

I assume you have already connected to Microsoft Graph. If not make sure you read the step-by-step guide mentioned earlier. One thing you will see a lot in the steps below is the if-match header. Everythime a plan, bucket or task is created or updated, the etag token is changed. So before we can update something or add tasks to a bucket, we need to get the latest etag value.

Get the plan id’s

We need to template plan and the new plan id before we can do anything. The new plan can be created manually, with PowerShell or come with a new Office 365 group. I won’t go into detail how you can create the plan.

There are two ways to get a plan id, the most simple way to copy it from the address bar. Just open a plan and look at the address bar. At the end of the URL you will find the planId:

https://tasks.office.com/~/Planner/#/plantaskboard?groupId=e54430ef-ABCD-43a6-1234-4c2f9d0987c3&planId=123ABCnzhHdE6zfvZkZIXpYAFPB_

Another option would be to use PowerShell to get the Unified Group by name and lookup the Group ID. Make sure you connect to Exchange Online first.

With the GroupID we can request all the available plans for this group:

Copy the plan categories

We got both plan id’s, the first thing we are going to do is copying the categories or also know as labels from the template plan. First, we get the template plan details:

And we need the eTag value from the new plan, so we request the details from the new plan as well:

If you look in the $planDetails.categoryDescriptions you will see a JSON object with all the labels.  We are going to update our new plan with those category descriptions. First, we create the headers with the correct if-match header and make a JSON body. Then with a PATCH method, we can update the new plan.

If you look at your new plan, you will now see that all the labels have the correct description.

Get all the buckets and tasks

The tasks are not listed under a bucket but are part of the plan. So you can’t just get the task for one bucket, but you will have to request all the task for the plan.

Creating buckets in the new plan

The buckets and task are sorted based on the orderHint value. This isn’t a logic integer or alphabetic value, but it’s a string based on the previous and next object. If you get all the buckets and start adding them to a new plan, you will notice that they are added in reverse order. Same goes for the tasks. Now you can’t simply use the orderHint from the template plan, because the orderHint is calculated by the service.

So if we add a new bucket or task, we need to check the orderHint that the service created and use that value to add the next bucket after it. The official documentation explains pretty well how the orderHint works. If you want to add a task behind the previously added task, you only need to add a space and exclamation mark to it  !.

To add the buckets in the right order, we store the orderHint from the last created bucket so we can add the next one to the right of it.

Creating the tasks for each bucket

Inside the foreach from the buckets we are also going to add the tasks. We have already requested all the tasks from the template plan, now we only need to get the tasks that belong to this bucket. To solve the ordering issue, we can sort the task in a descending order so they are added in the right order.

Adding the details to the task

The details from a task must be added through a patch method. To update the newly created task, we need the eTag value from it. If we create a task and immediately request the details from it you might get an error that the object doesn’t exist. So to prevent this I added a little delay in the script after we created a new task.

We also need the description from the original task from the template plan:

First, we get the etag value from the new task so we can create the necessary headers. We set the previewType and description which we get from the original task. The previewType determines what is displayed in the plan board. It can be the description of the task, reference of a checklist.

Adding the checklist Items

The last part of the script is adding the checklist. This one is the most complicated one to recreate. First, we check if the original task has a checklist. Then if we have a checklist, we can start copying this one to our new task.

A checklist item needs a unique client-side generated GUID, which we can create in PowerShell with the following cmd:

Next, we create a JSON object with all the checklist Items and add them with a PATCH method to the task:

Wrapping up

There are a few things I didn’t cover in this post, we created the labels in the beginning but didn’t apply them to the newly created tasks. If you want to this, check out the documentation on plannerAppliedCategories. You need to update a newly created task to add them.

Also, I didn’t copy any external references or users that are assigned to a task. For my case, this wasn’t necessary, but with this guide, you will have a good starting point to add those details also.

The complete script for using Microsoft Planner Templates can be download here at the TechNet Gallery. If you have any question, you can always reach out to me. You can also hire me to make you customized script or to help you with the implementation.

Thanks to Laura Kokkarinen for explaining the bucket and task sorting