Examples/PlannerImportExport/Export-planner-to-xlsx.ps1
#requires -modules Microsoft.Graph.PlusPlus, importExcel <# .synopsis Export a team planner #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification="False positives when initializing variable in begin block")] Param ( #The path of the Excel file to create $excelPath = '.\Planner-Export.xlsx', #The team which owns the planner. The signed in user must be a member of the team. Being an owner but not a member will fail $TeamName = 'Consultants', #The name of the plan to export $PlanName = 'Team Planner' ) #need to be a member of the team, not just an owner ! $teamplanner = Get-GraphTeam $TeamName -Plans | Where-Object title -eq $PlanName # my team's planner named 'team planner' $teamMembers = Get-GraphTeam $TeamName -Members $teamMembers | ForEach-Object -begin {$MemberHash = @{}} -Process {$memberhash[$_.id] = $_.mail} #region export Plan buckets and team members to "Values" workseet in the workbook. $excelPackage = Get-GraphPlan -Plan $teamplanner -buckets | Select-Object @{n="BucketName"; e={$_.name}},PlanTitle,ID | Export-excel -path $excelPath -worksheetname Values -ClearSheet -BoldTopRow -AutoSize -PassThru $excelPackage = $teamMembers | Select-Object @{n='User';e={$_.displayName}},Jobtitle,mail,ID | Export-Excel -ExcelPackage $excelPackage -worksheetname Values -StartColumn 12 -BoldTopRow -AutoSize -PassThru #Hide IDs: we can spot new team members if they don't have an ID. and if a bucket is renamed in the spreadsheet, we can update it if we have the ID Set-Excelrange -Range $excelPackage.Workbook.Worksheets['Values'].Column(15) -Hidden Set-Excelrange -Range $excelPackage.Workbook.Worksheets['Values'].Column(3) -Hidden #endregion #region export the plan to a "Plan" worksheet in the workbook #Export the tasks, for intitially name the category columns 'category1' to 'category6' $excelPackage = Get-GraphPlan -Plan $teamplanner -FullTasks | Sort-Object orderHint | Select-Object -Property @{n='Task Title' ; e={ $_.title }}, @{n='Bucket' ; e={ $_.BucketName }}, @{n='Start Date' ; e={ [datetime]$_.StartDateTime }}, @{n='Due Date' ; e={ [datetime]$_.dueDatetime }}, @{n='%Complate' ; e={ $_.percentComplete }}, @{n='AssignTo' ; e={ ($_.assignments.psobject.properties.name | ForEach-Object {$MemberHash[$_]} )-join "; " }}, @{n="Checklist" ; e={ ($_.checklist.psobject.Properties.value | Sort-Object orderHint | Select-Object -expand title) -join "; "} }, @{n='Description'; e={ $_.description }}, @{n="Links" ; e={ ($_.references.psobject.Properties.name -replace "%2E","." -replace "%3A",":" -replace "%25","%") -join "; "}}, @{n="Category1" ; e={if($_.appliedCategories.Category1) {'Yes'} else {$null} } }, @{n="Category2" ; e={if($_.appliedCategories.Category2) {'Yes'} else {$null} } }, @{n="Category3" ; e={if($_.appliedCategories.Category3) {'Yes'} else {$null} } }, @{n="Category4" ; e={if($_.appliedCategories.Category4) {'Yes'} else {$null} } }, @{n="Category5" ; e={if($_.appliedCategories.Category5) {'Yes'} else {$null} } } , @{n="Category6" ; e={if($_.appliedCategories.Category6) {'Yes'} else {$null} } } , ID | Export-Excel -ExcelPackage $excelPackage -AutoFilter -AutoSize -FreezeTopRowFirstColumn -BoldTopRow -WorksheetName Plan -ClearSheet -Activate -PassThru #Now give the category columns the right names by exporting catgegories to the right place in the plan sheet $excelPackage = Get-GraphPlan $teamplanner -Details | Select-Object -ExpandProperty categorydescriptions | Export-Excel -ExcelPackage $excelPackage -WorksheetName Plan -noheader -StartColumn 10 -BoldTopRow -AutoSize -PassThru #Categories in columns j to o $planSheet = $excelPackage.Workbook.Worksheets['Plan'] #Hide the IDs column: a new task won't have an ID and we can find tasks to update using the ID; format dates as short date Set-ExcelRange -Range $plansheet.Column(16) -Hidden Set-ExcelRange -Range $planSheet.cells['C:D'] -Width 11 -NumberFormat 'Short Date' Set-ExcelRange -Range $planSheet.cells -VerticalAlignment Center #if name, description and/or checklist are too wide, make them narrower if ($planSheet.Column(1).Width -gt 35) { Set-ExcelRange -Range $planSheet.cells['A:A'] -Width 35 -WrapText #Title } if ($planSheet.Column(7).Width -gt 20) { Set-ExcelRange -Range $planSheet.cells['G:G'] -Width 20 -WrapText #Check list } if ($planSheet.Column(8).Width -gt 20) { Set-ExcelRange -Range $planSheet.cells['H:H'] -Width 20 -WrapText #Description } if ($planSheet.Column(9).Width -gt 35) { $linksRange = "I2:I" + $PlanSheet.Dimension.end.row Set-ExcelRange -Range $planSheet.Cells[$linksRange] -FontSize 8 Set-ExcelRange -Range $planSheet.cells['I:I'] -Width 35 -WrapText #Links } #Put a data bar on the percent complete; make sure it goes 0-100 not min value to max value $PercentRange = "E2:E" + $planSheet.Dimension.End.Row $databar = Add-ConditionalFormatting -WorkSheet $planSheet -Address $PercentRange -DataBarColor LightBlue -PassThru $databar.LowValue.type = [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingValueObjectType]::Num $databar.HighValue.type = [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingValueObjectType]::Num $databar.LowValue.Value = 0 $databar.HighValue.Value = 100 #endregion #Create Validation rules. Bucket Name and user must come from the values page, 6 Categories must be Yes or blank, Percentage is an integer from 0 to 100 if (-not (Get-Command -Name Add-ExcelDataValidationRule -ErrorAction SilentlyContinue ) ) { Write-Warning -Message 'A newer version of the ImportExcel Module is needed to add validation rules' } else { $VParams = @{WorkSheet = $PlanSheet; ShowErrorMessage=$true; ErrorStyle='stop'; ErrorTitle='Invalid Data' } Add-ExcelDataValidationRule @VParams -Range 'B2:B1001' -ValidationType List -Formula 'values!$a$2:$a$1000' -ErrorBody "You must select an item from the list.`r`nYou can add to the list on the values page" #Bucket Add-ExcelDataValidationRule @VParams -Range 'F2:F1001' -ValidationType List -Formula 'values!$M$2:$M$1000' -ErrorBody 'You must select an item from the list' # Assign to Add-ExcelDataValidationRule @VParams -Range 'J2:O1001' -ValidationType List -ValueSet @('yes','YES','Yes') -ErrorBody "Select Yes or leave blank for no" # Categories Add-ExcelDataValidationRule @VParams -Range 'E2:E1001' -ValidationType Integer -Operator between -Value 0 -Value2 100 -ErrorBody 'Percentage must be a whole number between 0 and 100' # Percent complete } Close-ExcelPackage -ExcelPackage $excelPackage -Show |