Entra / Microsoft 365 · Exchange Online
Report calendar items
Generate a report of calendar items for a mailbox.
Connect & set up
Run these once per session. All scopes are read-only unless the script makes changes.
Connect-MgGraph -NoWelcome -Scopes Calendars.ReadBasic, User.ReadBasic.All
Run it
The main script. Copy it, or download the .ps1 and run it from your console.
param([int] $LookbackDays = 180,[string] $StartDate = (Get-Date).AddDays(-$LookbackDays),[string] $EndDate = (Get-Date).AddDays(1))Connect-MgGraph -NoWelcome -Scopes Calendars.ReadBasic, User.ReadBasic.All$Start = Get-Date($StartDate) -format s$End = Get-Date($EndDate) -format s$User = Get-MgUser -UserId (Get-MgContext).AccountWrite-Host ("Fetching calendar information from {0} to {1}..." -f $StartDate, $EndDate)[array]$Data = Get-MgUserCalendarView -StartDate $Start -EndDateTime $End -UserId $User.Id -AllIf ($Data) {Write-Host ("Found {0} calendar items" -f $Data.Count)} Else {Write-Host "No calendar items found."Break}# Find meetings arranged by the user[array]$Meetings = $Data | Where-Object {$_.Attendees.count -gt 1 -and $_.Organizer.emailaddress.Name -eq $User.displayName}Write-Host ("{0} meetings found arranged by {1}" -f $Meetings.Count, $User.displayName)$CalendarInfo = [System.Collections.Generic.List[Object]]::new()ForEach ($event in $Meetings) {[datetime]$MeetingStart = Get-Date($Event.start.datetime)[datetime]$MeetingEnd = Get-Date($Event.end.datetime)# Calculate meeting duration in minutes. If it's an all-day event, use 480 minutesIf ($Event.IsAllDay -eq $False) {$Duration = ($MeetingEnd - $MeetingStart).TotalMinutes} Else {$Duration = 480}$OnlineMeetingProvider = $null[array]$AllAttendees = ($Event.Attendees | Where-Object {$_.Type -ne "resource"} )[array]$RequiredAttendees = ($Event.Attendees | Where-Object {$_.Type -eq "required"})[array]$OptionalAttendees = ($Event.Attendees | Where-Object {$_.Type -eq "optional"})# Create output line - add one to the total attendees to account for the organizerIf ($Event.onlineMeetingProvider -ne "unknown") {$OnlineMeetingProvider = $Event.onlineMeetingProvider}$DataLine = [PSCustomObject] @{Type = $Event.typeOrganizer = $Event.organizer.emailaddress.nameOrganizerEmail = $Event.organizer.emailaddress.addressCreated = Get-Date($Event.createdDateTime) -format 'dd-MMM-yyyy HH:mm'Modified = Get-Date($Event.lastModifiedDateTime) -format 'dd-MMM-yyyy HH:mm'TimeZone = $Event.originalStartTimeZoneSubject = $Event.SubjectAllDay = $Event.IsAllDayOnline = $Event.isOnlineMeetingOnlineProvider = $OnlineMeetingProviderStart = Get-Date($MeetingStart) -format 'dd-MMM-yyyy HH:mm'End = Get-Date($MeetingEnd) -format 'dd-MMM-yyyy HH:mm'Day = (Get-Date($MeetingStart)).DayOfWeekDuration = $DurationLocation = $event.location.displaynameRequiredAttendees = $RequiredAttendees.emailaddress.name -join ", "OptionalAttendees = $OptionalAttendees.emailaddress.name -join ", "TotalAttendees = $AllAttendees.CountRequired = $RequiredAttendees.CountOptional = $OptionalAttendees.CountTotalAtEvent = $AllAttendees.Count + 1}$CalendarInfo.Add($DataLine)}$CalendarInfo = $CalendarInfo | Sort-Object {$_.Start -as [datetime]}$CalendarInfo | Select-Object Start, End, Subject, Organizer, RequiredAttendees, OnlineProvider | Out-GridView -Title ("Calendar items for {0}" -f $User.displayName)Write-Host "Generating report..."If (Get-Module ImportExcel -ListAvailable) {$ExcelGenerated = $TrueImport-Module ImportExcel -ErrorAction SilentlyContinue$ExcelOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Calendar Items.xlsx"If (Test-Path $ExcelOutputFile) {Remove-Item $ExcelOutputFile -ErrorAction SilentlyContinue}$CalendarInfo | Export-Excel -Path $ExcelOutputFile -WorksheetName "Calendar Items" `-Title ("Calendar Items {0}" -f (Get-Date -format 'dd-MMM-yyyy')) -TitleBold -TableName "CalendarItems"} Else {$CSVOutputFile = ((New-Object -ComObject Shell.Application).Namespace('shell:Downloads').Self.Path) + "\Calendar Items.CSV"$CalendarInfo | Export-Csv -Path $CSVOutputFile -NoTypeInformation -Encoding Utf8}If ($ExcelGenerated) {Write-Host ("An Excel report of calendar items is available in {0}" -f $ExcelOutputFile)} Else {Write-Host ("A CSV report of calendar items is available in {0}" -f $CSVOutputFile)}Write-Host "All done..."
Parameters
ParameterDefaultNotes
-LookbackDays180Number of days back to include calendar items in the report.-StartDate(Get-Date).AddDays(-180)Start of the calendar reporting window.-EndDate(Get-Date).AddDays(1)End of the calendar reporting window.Attribution
Author
Office365itpros