Con
PnP.Powershell è possibile aggiornare un campo
people multiutente di
SharePoint Online con il comando
Set-PnPListItem$tenantName = "XXXX"
$siteUrl = "https://$tenantName.sharepoint.com/sites/mioSito"
Connect-PnPOnline -url $siteUrl -Interactive
#Connect-PnPOnline -url $siteUrl -ClientId $clientId -ClientSecret $clientSecret -WarningAction Ignore
# leggo la lista da aggionare tramite la sua url
$list = Get-PnPList -Identity "Lists/ProvaPeople"
# leggo un item tramite il suo id
$item = Get-PnPListItem -List $list -Id 1
# definisco un Array con gli utenti
$users = @(
"LeeG@$tenantName.onmicrosoft.com",
"AlexW@$tenantName.onmicrosoft.com",
"JohannaL@$tenantName.onmicrosoft.com"
)
# hash table con i campi / valori da aggiornare
$fieldValues = @{"Title" = "Prova $(Get-Date)"; "Users" = $users }
# scrivo i valori nei campi
Set-PnPListItem -List $list -Identity 1 -Values $fieldValues
come si vede per aggiornare un campo
people multiutente è sufficiente passare un array e tutto funziona correttamente
Non ordinatoma in alcuni casi...
Casi particolari
Ci sono dei casi particolari in cui l'aggiornamento non va a buon fine, ad esempio se si ordina (
Sort-Object) l'array
$userValues = $users | sort-object # se faccio il sort da errore in salvataggio
$fieldValues = @{"Title" = "Prova $(Get-Date)"; "Users" = $userValues}
Set-PnPListItem -List $list -Identity 1 -Values $fieldValues
in questo caso, a
parità di utenti, viene ritornato questo
errore
Set-PnPListItem : The specified user could not be found.
In C:\...\PowerShell\ProveSharePointOnline\Update-PeopleMulti.ps1:58 car:1
+ Set-PnPListItem -List $list -Identity 1 -Values $values
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : WriteError: (:) [Set-PnPListItem], ServerException
+ FullyQualifiedErrorId : EXCEPTION,PnP.PowerShell.Commands.Lists.SetListItem
in pratica il comando
sort-object introduce l'errore.
Andando a verificare il tipo di dato ritornato, entrambe le variabili
$users e
$userValues ritornano
object[] e i valori contenuti sono sempre
StringPS> $users.GetType().Name
Object[]
PS> $users.Length
3
PS> $users[0].GetType().Name
String
PS> $users[1].GetType().Name
String
PS> $users[2].GetType().Name
String
PS> $users[3].GetType().Name
Impossibile chiamare un metodo su un`'espressione con valore null.
PS> $userValues.GetType().Name
Object[]
PS> $userValues.Length
3
PS> $userValues[0].GetType().Name
String
PS> $userValues[1].GetType().Name
String
PS> $userValues[2].GetType().Name
String
PS> $userValues[3].GetType().Name
Impossibile chiamare un metodo su un`'espressione con valore null.
i due oggetti
sembrano uguali, ma in realtà non lo sono, il comportamento è inspiegabile.
Lo stesso
errore lo si ottiene anche con la
Where-Object$userValues = $user | Where-Object { $_ -like "a*"} # se filtro da errore in salvataggio
Soluzione
Al momento non ho trovato una soluzione ma solo delle alternative
Alternativa 1
Controllano il codice del comando
Set-PnPListItem si vede che, in caso di un array di stringhe, cerca di risolvere il nome facendo l
'EnsureUser e poi per scrivere usa l
'Id dell'utente (LookupId).
A questo punto si può fare prima l
'EnsureUser e passare un array di interi in modo da avere un comportamento stabile e prevedibile
# ottengo il client context
$ctx = Get-PnPContext
# Array per contenere gli Id degli utenti
$userIds = @()
# ciclo sugli oggetti ordinati
$users | sort-object | foreach-Object {
$web = $ctx.Web
$user = $web.EnsureUser($_)
$ctx.Load($user);
try {
$ctx.ExecuteQuery();
# aggiungo l'id utente
$userIds += $user.Id
} catch {
$ErrorMessage = $_.Exception.Message
Write-Output $ErrorMessage
}
}
# passo l'array di Id
$fieldValues = @{"Title" = "Prova $(Get-Date)"; "Users" = $userIds }
Set-PnPListItem -List $list -Identity 1 -Values $fieldValues
OrdinatoQuesto metodo è il preferibile in quanto controlla anche l'esistenza degli utenti e non passa (catch) quelli inesistenti.
Se nell'array c'è anche un solo utente non valido, tutto l'update fallisce.
Alternativa 2
In caso di sort si può usare il metodo
[System.Array]::Sort($users) mentre per simulare la where una
if in un
foreach$userValues = @()
# ordino l'array
[System.Array]::Sort($users) # se uso direttamente l'array riordinato ottengo un errore in fase di salvataggio
foreach ($item in $users) {
# eventuale filtro per simulare una where
if(1 -eq 1) {
# aggiungo le stringhe all'array
$userValues += $item
}
}
$fieldValues = @{"Title" = "Prova $(Get-Date)"; "Users" = $userValues}
Set-PnPListItem -List $list -Identity 1 -Values $fieldValues
Respetto al caso 1, se c'è una stringa relativa ad un utente non esistente, l'update fallisce.