06th May 2020

Migrate List Items between SharePoint Online lists

Here is a quick Powershell script that will allow you to migrate list items between SharePoint lists. either within the same tenant or another tenant.

The code will also allow you to create the new site based on the existing (Communication site).

The code uses the PNP Powershell Engine which can be found here:
https://docs.microsoft.com/en-us/powershell/sharepoint/sharepoint-pnp/sharepoint-pnp-cmdlets?view=sharepoint-ps

Just set the initial booleans as required

$CreateNewSite = Do you want a new site to be created
$ApplyTemplate = Do you want the current site to be replicated to the new site
$CopyData = Do you want to copy all list items
$clearCurrentData = Do you want to delete all existing list items (IN THE NEW SITE ONLY)

$CreateNewSite = $false;
$ApplyTemplate = $false;
$CopyData = $true;
$clearCurrentData = $true;

Then update the required information for new site, current site and the data to be cloned, you will need to name the list and the specific fields for each list as in the example below:

# $CurrentSiteURL = Read-host("Enter Site to Clone URL")
$CurrentSiteURL = 'https://fluidsharepointdev01.sharepoint.com/sites/DDOverlay'

# $NewSiteURL = Read-Host("Enter New Site URL")
#$NewSiteTitle = Read-Host("Enter New Site Title")
$NewSiteURl = 'https://fluidsharepointdev01.sharepoint.com/sites/DDOverlay_Test'
$NewSiteTitle = 'DDOverlay Test'

#Data to be migrated
$listsToCloneData = "DB_Characters", "DB_Creatures", "DB_Images", "DB_CustomCreatures", "DB_NPC"
$FieldsToCloneData = @{
    "DB_Characters" = @("Title", "CharacterName", "MaxHP", "CurrentHP", "AC", "CharacterLevel", "Active", "ImageID");
    "DB_Creatures" = @("Title", "ImageID");
    "DB_Images" = @("Title", "Vase64Image");
    "DB_CustomCreatures" = @("Title", "hit_points", "armor_class", "size", "creaturetype", "alignment", "speed", "strength", 
    "dexterity", "constitution", "intelligence", "wisdom", "charisma", "actions", "special_abilities", "ImageID");
    "DB_NPC" = @("Title", "NPCName", "NPCDescription", "ImageID", "IndexString")
}
$DataHashTable = @{ };

Full Script below

# Set Actions
$CreateNewSite = $false;
$ApplyTemplate = $false;
$CopyData = $true;
$clearCurrentData = $true;

# $CurrentSiteURL = Read-host("Enter Site to Clone URL")
$CurrentSiteURL = '<SiteURL>'

# $NewSiteURL = Read-Host("Enter New Site URL")
#$NewSiteTitle = Read-Host("Enter New Site Title")
$NewSiteURl = '<SiteURL>'
$NewSiteTitle = '<Site Title>'

#Data to be migrated
$listsToCloneData = <ListName1>, <ListName2>, <ListName...>
$FieldsToCloneData = @{
    <ListName1> = @("Title", <fieldName1>, <fieldName2>, <fieldName...>);
    <ListName2> = @("Title", <fieldName1>, <fieldName2>, <fieldName...>);
    <ListName...> = @("Title", <fieldName1>, <fieldName2>, <fieldName...>);
}
$DataHashTable = @{ };

# intitiate Hashtable for lists and items
foreach ($l in $listsToCloneData) {
    $DataHashTable.Add($l, $null);
}

# Connect to current site
Connect-PnPOnline $CurrentSiteURL -UseWebLogin

# Get Template if required
if ($ApplyTemplate) {
    Get-PnPProvisioningTemplate -Out 'ClonedSite.xml'
}

# Get list Data if required
if ($CopyData) {
    foreach ($l in $listsToCloneData) {
        $DataHashTable[$l] = Get-PnPListItem -List $l
    }
}

# If Create new site required, create new site
if ($CreateNewSite) {
    New-PnPSite -Type CommunicationSite -Title $NewSiteTitle -URL $NewSiteURl
}


# Connect to new site
Connect-PnPOnline $NewSiteURl -UseWebLogin

# Apply tempalte if required (Lists navigation etc)
if ($ApplyTemplate) {
    Apply-PnPProvisioningTemplate -Path 'ClonedSite.xml'
}

# Copy in list items
if ($CopyData) {
    # Loop each list
    foreach ($l in $listsToCloneData) {

        # if required clear all list items for the current list
        if($clearCurrentData) {
            $currentListItems = Get-PnPListItem -list $l
            foreach ($i in $currentListItems) {
                Remove-PnPListItem -List $l -Identity $i -Force
            }
        }

        # loop through each item and create in the required list
        foreach ($item in $DataHashTable[$l]) {
            
            # Create a hash table of the required fields to pass to the add-item
            $fieldsHashTable = @{}

            # Enumerate (hashtable) all fields on the item
            foreach ($f in $item.FieldValues.GetEnumerator()) {
                #Check if the field is required (set in Data to be migrated above)
                if ($FieldsToCloneData[$l].Contains($f.key)) {
                    # Create a key if it doesnt exist
                    if (!$fieldsHashTable.ContainsKey($f.Key)) {
                        $fieldsHashTable.Add($f.Key, $null)
                    }
                    # Add the field and value to the item to be created hash table
                    $fieldsHashTable[$f.key] = $f.Value
                }
            }
            # Create the list item
            Add-PnPListItem -list $l -Values $fieldsHashTable;
        }
    }
}