-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added new features for Adding Teams and Channels
- Loading branch information
Showing
4 changed files
with
124 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
function Verify-CT365TeamsCreation { | ||
param( | ||
[string]$teamName, | ||
[int]$retryCount = 5, | ||
[int]$delayInSeconds = 10 | ||
) | ||
|
||
for ($i = 0; $i -lt $retryCount; $i++) { | ||
$existingTeam = Get-PnPTeamsTeam | Where-Object { $_.DisplayName -eq $teamName } | ||
if ($existingTeam) { | ||
return $true | ||
} | ||
Start-Sleep -Seconds $delayInSeconds | ||
} | ||
return $false | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,36 @@ | ||
<# | ||
.SYNOPSIS | ||
Creates new Microsoft 365 Teams and channels based on data from an Excel file. | ||
Creates new Microsoft Teams and associated channels based on data from an Excel file. | ||
.DESCRIPTION | ||
The New-CT365Teams function connects to SharePoint Online and creates new Microsoft 365 Teams and channels using the PnP PowerShell Module. | ||
The teams and channels are defined in an Excel file provided by the user. | ||
The New-CT365Teams function connects to Microsoft Teams via PnP PowerShell, reads team and channel information from an Excel file, and creates new Teams and channels as specified. It supports retry logic for team and channel creation and allows specifying a default owner. The function requires the PnP.PowerShell, ImportExcel, and PSFramework modules. | ||
.PARAMETER FilePath | ||
Specifies the path to the Excel file that contains the teams and channels information. | ||
The Excel file should contain a worksheet named "Teams". | ||
This parameter is mandatory and can be passed through the pipeline. | ||
Specifies the path to the Excel file containing the Teams and channel data. The file must be in .xlsx format. | ||
.PARAMETER AdminUrl | ||
Specifies the SharePoint Online admin URL. | ||
If not provided, the function will attempt to connect to SharePoint Online interactively. | ||
Specifies the SharePoint admin URL for the tenant. The URL must match the format 'tenant.sharepoint.com'. | ||
.PARAMETER ChannelColumns | ||
Specifies the columns in the Excel file that contain the channel names. | ||
By default, it looks for columns named "Channel1Name" and "Channel2Name". | ||
You can specify other column names if your Excel file is structured differently. | ||
.PARAMETER DefaultOwnerUPN | ||
Specifies the default owner's User Principal Name (UPN) for the Teams and channels. | ||
.EXAMPLE | ||
New-CT365Teams -FilePath "C:\path\to\teams.xlsx" -AdminUrl "https://contoso-admin.sharepoint.com" | ||
PS> New-CT365Teams -FilePath "C:\TeamsData.xlsx" -AdminUrl "contoso.sharepoint.com" -DefaultOwnerUPN "admin@contoso.com" | ||
This example connects to the specified SharePoint Online admin URL, reads the teams and channels from the provided Excel file, and then creates the teams and channels in Microsoft 365. | ||
.EXAMPLE | ||
$filePath = "C:\path\to\teams.xlsx" | ||
$filePath | New-CT365Teams | ||
This example uses pipeline input to provide the file path to the New-365Teams function. | ||
This example creates Teams and channels based on the data in 'C:\TeamsData.xlsx', using '[email protected]' as the default owner if none is specified in the Excel file. | ||
.NOTES | ||
Please submit any feedback and/or recommendations | ||
Prerequisite : PnP.PowerShell, ImportExcel, PSFramework, Microsoft.Identity.Client modules should be installed. | ||
- Requires the PnP.PowerShell, ImportExcel, and PSFramework modules. | ||
- The Excel file should have a worksheet named 'teams' with appropriate columns for team and channel data. | ||
- The function includes error handling and logging using PSFramework. | ||
#> | ||
function New-CT365Teams { | ||
[CmdletBinding()] | ||
param ( | ||
# Validate the Excel file path. | ||
param( | ||
[Parameter(Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)] | ||
[ValidateScript({ | ||
switch ($psitem){ | ||
{-not([System.IO.File]::Exists($psitem))}{ | ||
throw "Invalid file path: '$PSitem'." | ||
} | ||
{-not(([System.IO.Path]::GetExtension($psitem)) -match "(.xlsx)")}{ | ||
"Invalid file format: '$PSitem'. Use .xlsx" | ||
} | ||
|
@@ -56,116 +41,119 @@ function New-CT365Teams { | |
})] | ||
[string]$FilePath, | ||
|
||
[Parameter(Mandatory=$false)] | ||
[Parameter(Mandatory)] | ||
[ValidateScript({ | ||
if ($_ -match '^[a-zA-Z0-9]+\.sharepoint\.[a-zA-Z0-9]+$') { | ||
$true | ||
} else { | ||
throw "The URL $_ does not match the required format." | ||
} | ||
})] | ||
if ($_ -match '^[a-zA-Z0-9]+\.sharepoint\.[a-zA-Z0-9]+$') { | ||
$true | ||
} | ||
else { | ||
throw "The URL $_ does not match the required format." | ||
} | ||
})] | ||
[string]$AdminUrl, | ||
[Parameter(Mandatory=$false)] | ||
[string[]]$ChannelColumns = @("Channel1Name", "Channel2Name") | ||
|
||
[Parameter(Mandatory)] | ||
[string]$DefaultOwnerUPN | ||
) | ||
|
||
begin { | ||
# Import required modules. | ||
$ModulesToImport = "ImportExcel","PnP.PowerShell","PSFramework","Microsoft.Identity.Client" | ||
Import-Module $ModulesToImport | ||
|
||
# Check and import required modules | ||
$requiredModules = @('PnP.PowerShell', 'ImportExcel', 'PSFramework') | ||
foreach ($module in $requiredModules) { | ||
try { | ||
# Connect to SharePoint Online. | ||
$connectPnPOnlineSplat = @{ | ||
Url = $AdminUrl | ||
Interactive = $true | ||
ErrorAction = 'Stop' | ||
if (-not (Get-Module -ListAvailable -Name $module)) { | ||
throw "Module $module is not installed." | ||
} | ||
Connect-PnPOnline @connectPnPOnlineSplat | ||
} | ||
catch { | ||
# Log an error and exit if the connection fails. | ||
Write-PSFMessage -Message "Failed to connect to SharePoint Online" -Level Error | ||
return | ||
} | ||
|
||
try { | ||
# Import site data from Excel. | ||
$SiteData = Import-Excel -Path $FilePath -WorksheetName "Teams" | ||
} | ||
catch { | ||
# Log an error and exit if importing site data fails. | ||
Write-PSFMessage -Message "Failed to import SharePoint Site data from Excel file." -Level Error | ||
Import-Module $module | ||
} catch { | ||
Write-PSFMessage -Level Warning -Message "[$(Get-Date -Format 'u')] $_.Exception.Message" | ||
return | ||
} | ||
} | ||
|
||
process { | ||
foreach ($team in $SiteData) { | ||
Write-PSFMessage -Message "Processing team: $($team.TeamName)" -Level Host | ||
|
||
$existingTeam = Get-PnPTeamsTeam | Where-Object { $_.DisplayName -eq $team.TeamName } | ||
|
||
# If the team does not exist, create it. | ||
if (-not $existingTeam) { | ||
try { | ||
Connect-PnPOnline -Url $AdminUrl -Interactive | ||
} catch { | ||
Write-PSFMessage -Level Error -Message "[$(Get-Date -Format 'u')] Failed to connect to PnP Online: $($_.Exception.Message)" | ||
return | ||
} | ||
|
||
try { | ||
$teamsData = Import-Excel -Path $FilePath -WorksheetName "teams" | ||
$existingTeams = Get-PnPTeamsTeam | ||
} catch { | ||
Write-PSFMessage -Level Error -Message "[$(Get-Date -Format 'u')] Failed to import data from Excel or retrieve existing teams: $($_.Exception.Message)" | ||
return | ||
} | ||
|
||
foreach ($teamRow in $teamsData) { | ||
try { | ||
$teamOwnerUPN = if ($teamRow.TeamOwnerUPN) { $teamRow.TeamOwnerUPN } else { $DefaultOwnerUPN } | ||
$existingTeam = $existingTeams | Where-Object { $_.DisplayName -eq $teamRow.TeamName } | ||
|
||
if ($existingTeam) { | ||
Write-PSFMessage -Level Host -Message "[$(Get-Date -Format 'u')] Team $($teamRow.TeamName) already exists. Skipping creation." | ||
continue | ||
} | ||
|
||
$retryCount = 0 | ||
$teamCreationSuccess = $false | ||
do { | ||
try { | ||
$newPnPTeamsTeamSplat = @{ | ||
DisplayName = $team.TeamName | ||
Description = $team.TeamDescription | ||
Visibility = 'Private' | ||
ErrorAction = 'Stop' | ||
$teamId = New-PnPTeamsTeam -DisplayName $teamRow.TeamName -Description $teamRow.TeamDescription -Visibility $teamRow.TeamType -Owners $teamOwnerUPN | ||
if (Verify-CT365TeamsCreation -teamName $teamRow.TeamName) { | ||
Write-PSFMessage -Level Host -Message "[$(Get-Date -Format 'u')] Verified creation of Team: $($teamRow.TeamName)" | ||
$teamCreationSuccess = $true | ||
break | ||
} else { | ||
Write-PSFMessage -Level Warning -Message "[$(Get-Date -Format 'u')] Team $($teamRow.TeamName) creation reported but not verified. Retrying..." | ||
} | ||
|
||
New-PnPTeamsTeam @newPnPTeamsTeamSplat | ||
Write-PSFMessage -Message "Successfully created Team: $($team.TeamName)" -Level Host | ||
} catch { | ||
Write-PSFMessage -Level Warning -Message "[$(Get-Date -Format 'u')] Attempt $retryCount to create team $($teamRow.TeamName) failed: $($_.Exception.Message)" | ||
} | ||
catch { | ||
Write-PSFMessage -Message "Failed to create team $($team.TeamName): $_" -Level Error | ||
continue # Skip to the next team in case of error. | ||
} | ||
} | ||
|
||
# If the team already exists or was just created, log a message. | ||
Write-PSFMessage -Message "Team $($team.TeamName) exists or was just created. Proceeding to create channels..." -Level Host | ||
|
||
# Retry mechanism to fetch team details up to 3 times. | ||
$retryCount = 0 | ||
$maxRetries = 3 | ||
$teamResult = $existingTeam ?? $null | ||
|
||
while ($retryCount -lt $maxRetries -and (-not $teamResult)) { | ||
Start-Sleep -Seconds 15 # Wait before fetching the team details. | ||
$teamResult = Get-PnPTeamsTeam | Where-Object { $_.DisplayName -eq $team.TeamName } | ||
$retryCount++ | ||
} | ||
|
||
# If the team wasn't found after all retry attempts, log a warning and skip to the next team. | ||
if (-not $teamResult) { | ||
Write-PSFMessage -Message "Team $($team.TeamName) was not found after $maxRetries attempts." -Level Warning | ||
Start-Sleep -Seconds 5 | ||
} while ($retryCount -lt 5) | ||
|
||
if (-not $teamCreationSuccess) { | ||
Write-PSFMessage -Level Error -Message "[$(Get-Date -Format 'u')] Failed to create and verify Team: $($teamRow.TeamName) after multiple retries." | ||
continue | ||
} | ||
|
||
# Create channels based on the provided column names. | ||
foreach ($column in $ChannelColumns) { | ||
$channelName = $team.$column | ||
if (-not $channelName) { continue } # Skip to the next channel if the name is not found. | ||
|
||
Write-PSFMessage -Message "Creating channel: $channelName for team: $($team.TeamName)" -Level Host | ||
try { | ||
Add-PnPTeamsChannel -Team $teamresult.GroupId -DisplayName $channelName -Description "Channel named $channelName for $($team.TeamName)" | ||
Write-PSFMessage -Message "Successfully created channel: $channelName for team: $($team.TeamName)" -Level Host | ||
} | ||
catch { | ||
Write-PSFMessage -Message "Failed to create channel $channelName for team $($team.TeamName): $_" -Level Error | ||
|
||
for ($i = 1; $i -le 4; $i++) { | ||
$channelName = $teamRow."Channel${i}Name" | ||
$channelType = $teamRow."Channel${i}Type" | ||
$channelDescription = $teamRow."Channel${i}Description" | ||
$channelOwnerUPN = if ($teamRow."Channel${i}OwnerUPN") { $teamRow."Channel${i}OwnerUPN" } else { $DefaultOwnerUPN } | ||
|
||
if ($channelName -and $channelType) { | ||
$retryCount = 1 | ||
$channelCreationSuccess = $false | ||
do { | ||
try { | ||
Add-PnPTeamsChannel -Team $teamId -DisplayName $channelName -Description $channelDescription -ChannelType $channelType -OwnerUPN $channelOwnerUPN | ||
Write-PSFMessage -Level Host -Message "[$(Get-Date -Format 'u')] Created Channel: $channelName in Team: $($teamRow.TeamName) with Type: $channelType and Description: $channelDescription" | ||
$channelCreationSuccess = $true | ||
break | ||
} catch { | ||
Write-PSFMessage -Level Warning -Message "[$(Get-Date -Format 'u')] Attempt $retryCount to create channel $channelName in Team: $($teamRow.TeamName) failed: $($_.Exception.Message)" | ||
$retryCount++ | ||
Start-Sleep -Seconds 10 | ||
} | ||
} while ($retryCount -lt 5) | ||
|
||
if (-not $channelCreationSuccess) { | ||
Write-PSFMessage -Level Error -Message "[$(Get-Date -Format 'u')] Failed to create Channel: $channelName in Team: $($teamRow.TeamName) after multiple retries." | ||
} | ||
} | ||
} | ||
} catch { | ||
Write-PSFMessage -Level Error -Message "[$(Get-Date -Format 'u')] Error processing team $($teamRow.TeamName): $($_.Exception.Message)" | ||
} | ||
} | ||
|
||
end { | ||
# Disconnect from PnP | ||
try { | ||
Disconnect-PnPOnline | ||
Write-PSFMessage "Teams and Channels creation completed." | ||
} catch { | ||
Write-PSFMessage -Level Error -Message "[$(Get-Date -Format 'u')] Error disconnecting PnP Online: $($_.Exception.Message)" | ||
} | ||
} | ||
} |
Binary file not shown.