{"id":7356,"date":"2023-08-06T18:49:50","date_gmt":"2023-08-06T17:49:50","guid":{"rendered":"https:\/\/rakhesh.com\/?p=7356"},"modified":"2023-08-06T18:51:27","modified_gmt":"2023-08-06T17:51:27","slug":"fun-with-pnp-powershell","status":"publish","type":"post","link":"https:\/\/rakhesh.com\/azure\/fun-with-pnp-powershell\/","title":{"rendered":"Fun with PnP PowerShell"},"content":{"rendered":"

I had to do something with SharePoint lists today and had some fun with PnP PowerShell in the process. Here’s what I had to do. (What follows is a made up example).<\/p>\n

I have a bunch of lists that contain the prices of an item per country. For instance, there’s 6 lists for 6 items.<\/p>\n

\"\"<\/p>\n

Here’s what one of the lists looks like:<\/p>\n

\"\"<\/p>\n

All 6 lists have the same contries, and the price of the item in that country.<\/p>\n

What I wanted to do was have country specific lists that showed the price of the 6 items for that country. Initially I thought I might be able to do a lookup or something between lists, but that doesn’t work. Instead I decided to create new lists that are populated via PnP PowerShell.<\/p>\n

To begin with, let’s get the names of the items and the countries. I do the first by finding all lists with “Item xx Prices” as the name. And for the latter I simply read all the Title field values from one of these lists.<\/p>\n

$itemNames = (Get-PnpList | Where-Object { $_.Title -match \"^Item.*Prices$\" }).Title\r\n\r\n$countryNames = (Get-PnPListItem -List \"Item 1 Prices\").FieldValues.Title<\/pre>\n

Then I’d want to process each country. Check if there’s a list with that country name already, and if not create it. Then check if the list (new or existing) has a field called Price, and if not create it. And lastly go through each of the item lists, find the price of the item for that country, and add these as rows to the newly created list.<\/p>\n

I did it this way (the snippet includes the two lookups I showed above too).<\/p>\n

$itemNames = (Get-PnpList | Where-Object { $_.Title -match \"^Item.*Prices$\" }).Title\r\n\r\n$countryNames = (Get-PnPListItem -List \"Item 1 Prices\").FieldValues.Title\r\n\r\nforeach ($country in $countryNames) {\r\n    $newListName = \"Country: $country\"\r\n\r\n    Write-Progress \"Processing $newListName\"\r\n\r\n    try {\r\n        Get-PnPList -Identity \"$newListName\" -ErrorAction Stop | Out-Null\r\n        Write-Progress \"List exists $newListName\"\r\n    } catch {\r\n        if ($_.Exception.Message -match \"does not exist at site\") {\r\n            Write-Progress \"Creating new list $newListName\"\r\n            try {\r\n                New-PnPList -Title \"$newListName\" -Template GenericList -ErrorAction Stop | Out-Null\r\n                Write-Progress \"Created new list $newListName\"\r\n                Start-Sleep -Seconds 5\r\n            } catch {\r\n                Write-Warning \"Something went wrong. Skipping.\"\r\n                continue\r\n            }\r\n        }\r\n    }\r\n\r\n    $newfield = \"Price\"\r\n    if ((Get-PnPField -List \"$newListName\").Title -notcontains \"$newfield\") {\r\n        Write-Progress -Id 1 \"Adding the $newfield field\"\r\n        try {\r\n            Add-PnPField -List \"$newListName\" -DisplayName \"$newfield\" -InternalName \"$newfield\" -Type \"Note\" -AddToDefaultView -ErrorAction Stop | Out-Null\r\n        } catch {\r\n            Write-Warning \"Error adding the $newfield field. Skipping.\"\r\n            continue\r\n        }\r\n    }\r\n\r\n    foreach ($item in $itemNames) {\r\n        Write-Progress  -Id 1 \"Processing item $item\"\r\n        # find the field used for that country \r\n        try {\r\n            $result = Get-PnPListItem -List \"$item\" -ErrorAction Stop | Where-Object { $_.FieldValues.Title -eq \"$country\" } \r\n        } catch {\r\n            Write-Warning \"Error getting field. Skipping.\"\r\n            continue\r\n        }\r\n\r\n        $values = @{\r\n            \"Title\" = \"$item\"\r\n            \"Price\" = if ($result.FieldValues.Keys -contains \"Price\") { $result.FieldValues.Price }\r\n        }\r\n\r\n        # The query is a CAML query - https:\/\/pnp.github.io\/powershell\/cmdlets\/Get-PnPListItem.html#example-6        \r\n        try {\r\n            Write-Progress -Id 2 \"Looking up item $item in list $newListName\"\r\n            $listItem = Get-PnpListItem -List \"$newListName\" -ErrorAction Stop `\r\n                -Query \"<View><Query><Where><Eq><FieldRef Name='Title'\/><Value Type='Text'>$item<\/Value><\/Eq><\/Where><\/Query><\/View>\"\r\n\r\n        } catch {\r\n            Write-Warning \"Error getting existing item. Skipping.\"\r\n            continue\r\n        }\r\n\r\n        if ($listItem) {\r\n            Write-Progress -Id 2 \"Updating existing item\"\r\n            try {\r\n                Set-PnPListItem -List \"$newListName\" -Values $values -Identity $listItem -ErrorAction Stop | Out-Null\r\n            } catch {\r\n                Write-Warning \"Error updating $field in $newListName\"\r\n            }\r\n        } else {\r\n            Write-Progress -Id 2 \"Creating new item\"\r\n            try {\r\n                Add-PnPListItem -List \"$newListName\" -Values $values -ErrorAction Stop | Out-Null\r\n            } catch {\r\n                Write-Warning \"Error adding $field to $newListName\"\r\n            }\r\n        }\r\n    }\r\n}<\/pre>\n

Now I can have this running periodically (I suppose I could look into triggering this whenever there’s a change to the item lists<\/a>) and have the country lists up to date. Nice, huh! \ud83d\ude0a<\/p>\n

Here’s an example country list:<\/p>\n

\"\"<\/p>\n

And here’s all the automatically created lists, with 6 items each:<\/p>\n

\"\"<\/p>\n","protected":false},"excerpt":{"rendered":"

I had to do something with SharePoint lists today and had some fun with PnP PowerShell in the process. Here’s what I had to do. (What follows is a made up example). I have a bunch of lists that contain the prices of an item per country. For instance, there’s 6 lists for 6 items. … Continue reading Fun with PnP PowerShell<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false}}},"categories":[887],"tags":[1017],"jetpack_publicize_connections":[],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/posts\/7356"}],"collection":[{"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/comments?post=7356"}],"version-history":[{"count":3,"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/posts\/7356\/revisions"}],"predecessor-version":[{"id":7363,"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/posts\/7356\/revisions\/7363"}],"wp:attachment":[{"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/media?parent=7356"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/categories?post=7356"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rakhesh.com\/wp-json\/wp\/v2\/tags?post=7356"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}