Skip to content

Instantly share code, notes, and snippets.

@alirobe
Last active October 30, 2022 20:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save alirobe/4187b0f073dc2eba5207f312a01ddab6 to your computer and use it in GitHub Desktop.
Save alirobe/4187b0f073dc2eba5207f312a01ddab6 to your computer and use it in GitHub Desktop.
Copy list contents between lists in SharePoint using PnP
# authored @alirobe for @sopewebtech 2022-06-17
# pnp-list-copy.ps1 : https://gist.githubusercontent.com/alirobe/4187b0f073dc2eba5207f312a01ddab6/
# this copies list values from source to target
# before using this script, create a new list 'from existing list' in the same site
# then, plug values in below and run. should work for most field types. any issues let me know.
# todo: add batching, add field types
# licensed under GPL V2
$Site = "https://notproduction.sharepoint.com/sites/not-sproket-4/"
$SourceListName = "Source"
$TargetListName = "Source V2"
###
Connect-PnPOnline $Site -UseWebLogin
$SourceList = Get-PnPList $SourceListName -Includes Fields
$TargetList = Get-PnPList $TargetListName
if($TargetList -eq $null) {
# If target list does not exist, create
$CreatedList = Copy-PnPList -Title $TargetListName -Identity $SourceList
$TargetList = Get-PnPList -Id $CreatedList.Id
}
$SourceItems = Get-PnPListItem -List $SourceList
$Fields = Get-PnPField -List $SourceList | Where-Object { $_.ReadOnlyField -eq $false -and $_.FieldName -notlike "*_0" -and $_.InternalName -ne "MetaInfo" -and $_.InternalName -ne "ContentType" }
$BasicFields = $Fields | Where-Object { $_.TypeAsString -notlike "Lookup*" -and $_.TypeAsString -notlike "User*" -and $_.TypeAsString -notlike "Taxonomy*" -and $_.TypeAsString -ne "Attachments" }
$LookupFields = $Fields | Where-Object { $_.TypeAsString -like "Lookup*" }
$UserFields = $Fields | Where-Object { $_.TypeAsString -like "User*" }
$TaxonomyFields = $Fields | Where-Object { $_.TypeAsString -like "TaxonomyFieldType*" }
# to add more field types + multis, see https://pnp.github.io/powershell/cmdlets/Add-PnPListItem.html
# attachments, external data links, comments not supported
$CopiedValues = @()
foreach ($SourceItem in $SourceItems) {
$TargetValues = @{}
foreach ($Field in $BasicFields) {
$TargetValues[$Field.InternalName] = $SourceItem.FieldValues[$Field.InternalName]
}
foreach ($Field in $LookupFields) {
$Values = @()
$SourceItem.FieldValues[$Field.InternalName] | ForEach-Object { $Values += $_.LookupId }
$ValuesStr = $Values -join ","
if ($ValuesStr -ne "") {
$TargetValues[$Field.InternalName] = $ValuesStr
}
}
foreach ($Field in $UserFields) {
$Values = @()
$SourceItem.FieldValues[$Field.InternalName] | ForEach-Object { $Values += $_.Email }
if ($Values.Length -eq 1) {
$TargetValues[$Field.InternalName] = $Values[0]
}
elseif ($Values.Length -gt 1) {
$TargetValues[$Field.InternalName] = $Values
}
}
foreach ($Field in $TaxonomyFields) {
$Values = @()
$SourceItem.FieldValues[$Field.InternalName] | ForEach-Object { $Values += $_.TermGuid }
if ($Values.Length -eq 1) {
$TargetValues[$Field.InternalName] = $Values[0]
}
elseif ($Values.Length -gt 1) {
$TargetValues[$Field.InternalName] = $Values
}
}
Add-PnPListItem -List $TargetList -Values $TargetValues
$CopiedValues += $TargetValues
}
Write-Host "Done. $($CopiedValues.Count) items copied. $((Get-PnPListItem -List $TargetList).Count) items in target list."
@alirobe
Copy link
Author

alirobe commented Jun 17, 2022

Most likely this isn't perfect, if you fix something in it, please post it back here as a fork or comment and i'll try to keep this up-to-date.
Please take the time to star/fork if you use it.

@ToddKlindt
Copy link

Could you add a bit at the beginning that uses copy-pnplist to create the destination list if it doesn't exist?

@alirobe
Copy link
Author

alirobe commented Sep 12, 2022

@ToddKlindt done :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment