I have a script I have been building to copy tasks from one Plan to another. Eventually the purpose of the script will be to copy over old Tasks to a new Plan and delete them in the original Plan but for now I am just working on the copying of tasks.
I have managed to copy task titles, due dates, and percentage complete but have not managed to get other things such as assignee(s), notes, attachments and buckets. I have some output in console when running the task that says for example for task:
"Task Test Task X has assignees:"
"Assignee information not found or incomplete for Test Task X."
"Task Test Task X has no attachments."
"Task Test Task X does not have a bucket."
"Task moved: Test Task X"
# PowerShell script to copy planner tasks from one plan to another
# You will need to connect to Microsoft Graph
# Define your variables
$tenant = "" # Your tenant ID
$clientid = "" # Your registered application client ID
$thumbprint = "" # Thumbprint of your registered application certificate
$sourcePlanId = "" # ID of the source plan from which tasks will be copied
$destinationPlanId = "" # ID of the destination plan where tasks will be copied to
# Connect to Microsoft Graph
Connect-MgGraph -ClientId $clientid -TenantId $tenant -CertificateThumbprint $thumbprint
# Function to retrieve user details by ID
function Get-MgUserById {
param (
[string]$UserId
)
if (-not [string]::IsNullOrWhiteSpace($UserId)) {
return Get-MgUser -UserId $UserId
}
else {
Write-Warning "User ID is empty or null."
return $null
}
}
# Get top 3 tasks from the source plan
$sourceTasks = Get-MgPlannerPlanTask -PlannerPlanId $sourcePlanId -Top 3
# Initialize counter for moved tasks
$movedTasksCount = 0
# Iterate through each task in the source plan
foreach ($task in $sourceTasks) {
# Initialize array to store assignees
$assignees = @()
# Check if task has assignees
if ($task.Assignments) {
Write-Host "Task $($task.Title) has assignees:"
# Retrieve user details for each assignee and add them to the new task JSON
foreach ($assignment in $task.Assignments) {
$userId = $assignment.assignedUser.id
if (-not [string]::IsNullOrEmpty($userId)) {
Write-Host "Assignee User ID: $userId"
Write-Host $assignment | Format-List
$assignees += @{
"assignedDateTime" = $null # Add assignedDateTime if available
"orderHint" = "string" # Provide the order hint value
"assignedBy" = @{
"user" = @{
"id" = $userId
}
}
}
}
else {
Write-Host "Assignee information not found or incomplete for $($task.Title)."
}
}
}
else {
Write-Host "Task $($task.Title) has no assignees."
}
# Get task attachments
$attachments = @()
if ($task.Attachments) {
Write-Host "Task $($task.Title) has attachments:"
foreach ($attachment in $task.Attachments) {
Write-Host "Attachment Name: $($attachment.Name)"
$attachments += @{
"name" = $attachment.Name
"type" = $attachment.ContentType
"url" = $attachment.Url
}
}
}
else {
Write-Host "Task $($task.Title) has no attachments."
}
# Get the bucket ID of the task in the destination plan
$destinationTask = Get-MgPlannerPlanTask -PlannerPlanId $destinationPlanId -Top 1
$bucketId = $destinationTask.BucketId
if (-not [string]::IsNullOrWhiteSpace($bucketId)) {
Write-Host "Task $($task.Title) has a bucket with ID: $bucketId"
}
else {
Write-Host "Task $($task.Title) does not have a bucket."
}
# Create a JSON object representing the task to be added to the destination plan
$newTaskJson = @{
"planId" = $destinationPlanId
"title" = $task.Title
"labels" = $task.Labels # Retain task labels
"percentComplete" = $task.PercentComplete
"priority" = $task.Priority # Retain task priority
"startDateTime" = $task.StartDateTime
"dueDateTime" = $task.DueDateTime
"notes" = $task.Details.Description
"bucketId" = $bucketId # Use the fetched bucket ID
"attachments" = $attachments # Retain task attachments
"assignments" = $assignees # Include assignees
# Add other task details as needed
}
# Make a POST request to create the task in the destination plan
$response = New-MgPlannerTask -Body ($newTaskJson | ConvertTo-Json -Depth 10)
# Check if task was moved successfully
if ($response) {
Write-Host "Task moved: $($task.Title)"
$movedTasksCount++
# Delete the task from the source plan
# Commented out for now
# Remove-MgPlannerTask -PlannerTaskId $task.Id
}
else {
Write-Host "Failed to move task: $($task.Title)"
}
}
# Display total number of tasks moved
Write-Host "Total tasks moved: $movedTasksCount"
I tried running the script and it copies the task over but no assignees, attachments or related bucket that does exist on the source Task in Planner
I am new to PowerShell and Graph so any insights would be appreciated even if just for solving how to copy over the assignee for a task.
Thank you.
A coworker helped me figure out that the Assignees are in a double nested dictionary so I definitely had help on this one but posting answer in case it helps anyone else. I don't have it working yet for attachments or notes associated with a Plan Task.