I am creating a LIST in SharePoint using PowerShell via a CSV file. I am able to create the list as well as add items successfully, although I need to validate that the item (row) that I add to the list does not already exist in the list, prior to updating the list.
In the code I am not able to get $ItemExist correctly. It always returns a Null value. ($MaxItems currently has a value of 2 as there are 2 items in the list "list_DLs").
(I have already checked all other posts on the site for the same issue and did not find a fix)
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $AdminName, $Pass
$Path_SpFiles = "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI"
Add-Type -path "$Path_SpFiles\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -path "$Path_SpFiles\Microsoft.SharePoint.Client.dll"
# ------- Connect to SharePoint Site and fetch List Items ----------------
[Net.ServicePointManager]::SecurityProtocol = 'TLS11','TLS12','ssl3'
$site = "https://xyz.sharepoint.com/sites/mco"
$context = New-Object Microsoft.SharePoint.Client.ClientContext($site)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($AdminName, $Pass)
$context.Credentials = $credentials
$ListName="list_DLs"
$list = $context.Web.Lists.GetByTitle($ListName)
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery(5000)
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()
$MaxItems = $items.count
$SourceFile = "C:\Temp\list_DLs.csv"
$CSVData = Import-CSV -path $SourceFile
foreach ($row in $CSVData)
{
#----------------------------------------------
#Check if the item has previously been added
if ($MaxItems -ne 0)
{
$ItemExist = $items | where{$_.Title -eq $row.PrimarySmtpAddress}
if($ItemExist -ne $null) {Continue}
}
#----------------------------------------------
$ListItemInfo = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
$Item = $list.AddItem($ListItemInfo)
$Item["Title"] = $row.PrimarySmtpAddress
$Item.Update()
$Context.ExecuteQuery()
Break
}
I know that the $items in being returned correctly, because if I run this snippet of code to iterate through the items I am able to see them correctly. I am just not able to get $ItemExist to work correctly
ForEach ($item in $items)
{
$b = $item["Title"]
$b
Break
}
You can use a CAML query to check if the item is already in the list.
CAML query:
$caml="
<View>
<Query>
<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>1</Value></Eq></Where>
</Query>
</View>
"
$ItemExist = Get-PnPListItem -List $targetList -Query $caml
My test result:
Related
I am running the following to get all views for all lists in all subsites of our Sharepoint installation.
$views = #()
foreach ($web in Get-PnPSubWebs) {
foreach ($list in Get-PnPList -Web $web.id) {
foreach ($view in Get-PnPView -list $list.id -web $web.id) {
$views += [pscustomobject]#{Id = $view.Id; StyleId = $view.StyleId}
}
}
}
Which works fine, I am getting all views as expected. But I have not been successful in setting a new style for the views.
I have tried to use $view.ApplyStyle() as is described here: https://social.msdn.microsoft.com/forums/sharepoint/en-US/58068fb4-33ad-46cf-b866-bd86e1cbcafb/update-sharepoint-list-view-style-via-powershell and here: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spview.applystyle.aspx.
I however get the following error:
Method invocation failed because [Microsoft.SharePoint.Client.View] does not contain a method named 'ApplyStyle'.
Next I tried Set-PnPView -Web $web.id -List $list.id -Identity $view.Id -Values #{StyleId=17} per these instructions:
https://learn.microsoft.com/en-us/powershell/module/sharepoint-pnp/set-pnpview?view=sharepoint-ps. That only got me this message:
WARNING: Setting property 'StyleId' to '17' failed with exception 'Property set method not found.'. Value will be ignored.
And as a last resort $view.StyleId = 17 does also not work. Then I get this: 'StyleId' is a ReadOnly property. as expected.
We want to have our lists all be in the shaded style (id:17). We have hundreds of lists and since I'm hoping there is a better way then spending a full day manually changing them all. I have yet to find a way to change the default list view style but all our lists seem to be set to "default" view although there isn't a way to see what the default style is or change it.
All suggestions appreciated.
Update:
This is the complete script that I ended up using for all views in all lists in all subwebs of our main site:
Connect-PnPOnline –Url http://sharepointsite –CurrentCredentials
foreach ($web in Get-PnPSubWebs) {
foreach ($list in Get-PnPList -Web $web.id) {
foreach ($view in Get-PnPView -list $list.id -web $web.id) {
[xml]$Doc = New-Object System.Xml.XmlDocument
$Doc.LoadXml($view.ListViewXml);
$element = $Doc.SelectSingleNode("//View//ViewStyle");
if ($element -eq $null)
{
$element = $Doc.CreateElement("ViewStyle");
$element.SetAttribute("ID", 17);
$Doc.DocumentElement.AppendChild($element);
}
else
{
$element.SetAttribute("ID", 17);
}
Set-PnPView -Web $web.id -List $list.id -Identity $view.Id -Values #{ListViewXml=$Doc.FirstChild.InnerXml}
}
}
}
And then to get all lists for out main web as well I ran this:
Connect-PnPOnline –Url http://sharepointsite –CurrentCredentials
$web = Get-PnPWeb
foreach ($list in Get-PnPList -Web $web.id) {
foreach ($view in Get-PnPView -list $list.id -web $web.id) {
[xml]$Doc = New-Object System.Xml.XmlDocument
$Doc.LoadXml($view.ListViewXml);
$element = $Doc.SelectSingleNode("//View//ViewStyle");
if ($element -eq $null)
{
$element = $Doc.CreateElement("ViewStyle");
$element.SetAttribute("ID", 17);
$Doc.DocumentElement.AppendChild($element);
}
else
{
$element.SetAttribute("ID", 17);
}
Set-PnPView -Web $web.id -List $list.id -Identity $view.Id -Values #{ListViewXml=$Doc.FirstChild.InnerXml}
}
}
Here is my sample test script for your reference(I tested in online, I think it should works for SharePoint 2019 as it's CSOM api).
Add-Type -Path (Resolve-Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll")
Add-Type -Path (Resolve-Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll")
$UserName = "Wendy#tenant.onmicrosoft.com"
$siteURL = "https://tenant.sharepoint.com/sites/lee"
$Password = "password"
[SecureString]$SecurePass = ConvertTo-SecureString $Password -AsPlainText -Force
$Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Username, $SecurePass)
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteURL)
$ctx.credentials = $Credentials
try{
$list = $ctx.web.Lists.GetByTitle("MyList2")
$views = $list.views
$ctx.load($views)
$ctx.executeQuery()
foreach ($v in $views)
{
if ($v.Title -eq "All Items")
{
$ctx.Load($v);
$ctx.ExecuteQuery();
[xml]$Doc = New-Object System.Xml.XmlDocument
$Doc.LoadXml($v.ListViewXml);
$element = $Doc.SelectSingleNode("//View//ViewStyle");
if ($element -eq $null)
{
$element = $Doc.CreateElement("ViewStyle");
$element.SetAttribute("ID", 17);
$Doc.DocumentElement.AppendChild($element);
}
else
{
$element.SetAttribute("ID", 17);
}
$v.ListViewXml = $Doc.FirstChild.InnerXml;
$v.Update();
$ctx.ExecuteQuery();
}
}
}
catch{
write-host "$($_.Exception.Message)" -foregroundcolor red
}
I need to be able to script folder creation from a csv into a SharePoint Online document library with each folder with permission inheritance disabled and for different user to each folder to be added.
The following code can create the folders and disable the inheritance but it seems to try add a group but not a user. How to make it add a user instead?
Thanks.
### Get the user credentials
$credential = Get-Credential
$username = $credential.UserName
$password = $credential.GetNetworkCredential().Password
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
### Input Parameters
$url = 'URL HERE'
$csvfilepath='C:\Scripts\data.csv'
$libname ='BUS61'
### References
# Specified the paths where the dll's are located.
Add-Type -Path 'C:\Scripts\SPOCmdlets\Microsoft.SharePoint.Client.dll'
Add-Type -Path 'C:\Scripts\SPOCmdlets\Microsoft.SharePoint.Client.Runtime.dll'
### CreateFolder with Permissions Function
function CreateFolderWithPermissions()
{
# Connect to SharePoint Online and get ClientContext object.
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext($url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $securePassword)
$clientContext.Credentials = $credentials
Function GetRole
{
[CmdletBinding()]
param
(
[Parameter(Mandatory = $true, Position = 1)]
[Microsoft.SharePoint.Client.RoleType]$rType
)
$web = $clientContext.Web
if ($web -ne $null)
{
$roleDefs = $web.RoleDefinitions
$clientContext.Load($roleDefs)
$clientContext.ExecuteQuery()
$roleDef = $roleDefs | Where-Object { $_.RoleTypeKind -eq $rType }
return $roleDef
}
return $null
}
# Get the SharePoint web
$web = $clientContext.Web;
$clientContext.Load($web)
#Get the groups
$groups = $web.SiteGroups
$clientContext.Load($groups)
$clientContext.ExecuteQuery()
#Read CSV File and iterate
$csv = Import-CSV $csvfilepath
foreach ($row in $csv)
{
#Create Folder
$folder = $web.Folders.Add($libname + "/" + $row.Folder)
$clientContext.Load($folder)
$clientContext.ExecuteQuery()
#Assign Role
$group = $groups.GetByName($row.Group)
$clientContext.Load($group)
$clientContext.ExecuteQuery()
$roleType= $row.Role
$roleTypeObject = [Microsoft.SharePoint.Client.RoleType]$roleType
$roleObj = GetRole $roleTypeObject
$usrRDBC = $null
$usrRDBC = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($clientContext)
$usrRDBC.Add($roleObj)
# Remove inherited permissions
$folder.ListItemAllFields.BreakRoleInheritance($false, $true)
$clientContext.Load($folder.ListItemAllFields.RoleAssignments.Add($group, $usrRDBC))
$folder.Update()
$clientContext.ExecuteQuery()
# Display the folder name and permission
Write-Host -ForegroundColor Blue 'Folder Name: ' $folder.Name ' Group: '$row.Group ' Role: ' $roleType;
}
}
#Execute the function
CreateFolderWithPermissions
Let's assume that you will define user login in your CSv file. Than you have to change the line:
$group = $groups.GetByName($row.Group)
to
$user = $web.EnsureUser($row.User)
and replace all references to $group variable with $user
More generic approach for searching for a user (with for example display name) would be using Utility.ResolvePrincipal method:
[Microsoft.SharePoint.Client.Utilities.Utility]::ResolvePrincipal($clientContext, $web, "DisplayName", ([Microsoft.SharePoint.Client.Utilities.PrincipalType]::User), ([Microsoft.SharePoint.Client.Utilities.PrincipalSource]::All), $null, $false)
On SharePoint 2013, I am trying to get list items, with client-side SharePoint PowerShell.
Even for field Id or Title, I encounter this error: The collection has not been initialized.
I don't know how to include fields. I find many exemples in C# or JavaScript but none in client side powershell.
Here is my code (it returns correctly the number of items):
Function New-Context([String]$WebUrl) {
$context = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
$context.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$context
}
Function Get-List([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle) {
$list = $context.Web.Lists.GetByTitle($ListTitle)
$context.Load($list)
$context.ExecuteQuery()
$list
}
$context = New-Context -WebUrl "http://mysharepoint.com/sites/qp"
$list = Get-List -Context $context -ListTitle "QP-Configuration"
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()
$items.Count
$items[0]
foreach($item in $items)
{
$item.Id
}
$context.Dispose()
While getting a specific list item by index at line:
$items[0]
or iterating through a collection of Microsoft.SharePoint.Client.ListItemCollection:
foreach($item in $items)
{
#...
}
every property of object is assumed initialized in PowerShell but this is not the case with Microsoft.SharePoint.Client.ListItem since only a specific subset of properties could be retrieved and this why this error occurs.
To retrieve list items values I would suggest to access them via ListItem.FieldValues property:
#get list items values
$dataValues = #()
$items.GetEnumerator() | % {
$dataValues += $_.FieldValues
}
Example
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()
$dataValues = #()
$items.GetEnumerator() | % {
$dataValues += $_.FieldValues
}
$dataValues.Count #determine the amount of items
$dataValues[0] #access item by index
#iterate through list items and print a specific field value, for example FileRef
foreach($item in $dataValues)
{
$item.FileRef
}
The error was to try to get the full item like that: $items[0] or a column value using $item.Title instead of $item["Title"]
The correct code is:
#Import the required DLL
Add-Type -Path 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll'
Function New-Context([String]$WebUrl) {
$context = New-Object Microsoft.SharePoint.Client.ClientContext($WebUrl)
$context.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
$context
}
Function Get-List([Microsoft.SharePoint.Client.ClientContext]$Context, [String]$ListTitle) {
$list = $context.Web.Lists.GetByTitle($ListTitle)
$context.Load($list)
$context.ExecuteQuery()
$list
}
$context = New-Context -WebUrl "http://mysharepointsite.com/sites/qp"
$list = Get-List -Context $context -ListTitle "QP-Configuration"
$query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
$items = $list.GetItems($query)
$context.Load($items)
$context.ExecuteQuery()
$items.Count
foreach($item in $items)
{
$item["Title"]
}
$context.Dispose()
I am writing a PowerShell script to get bookings from SharePoint 2007. Booking is made by creating an item in Calender list. The list has already been used for over 6 years. I want to write a script to send SMTP email reminders to users for bookings after 3 days. I used the following code to get the list items.
$service = New-WebServiceProxy -Uri $uri -UseDefaultCredential
...
$xmlDoc = new-object System.Xml.XmlDocument
$query = $xmlDoc.CreateElement("Query")
$viewFields = $xmlDoc.CreateElement("ViewFields","Week")
$queryOptions = $xmlDoc.CreateElement("QueryOptions")
$query.set_InnerXml("FieldRef Name='Full Name'")
$rowLimit = "50000"
...
if($service -ne $null){
try{
$list = ($service.GetListItems($listName, $viewName, $query, $viewFields, $rowLimit, $queryOptions, "")).data.row
$list | export-csv "$path\list.csv"
}catch {
Write-host "Error !! Cannot update the list.csv."
}
I don't want to get all the items in this 6 years every time i run the script, can i get items only in the next 3 days?
You could loop through your results and use some simple math to compare the dates, using CSOM will make the logic much easier to adapt in the future. You might be able to use the CAML query to do the date filtering too but that's not my forte:
Import-Module 'C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll'
$siteUrl = "http://Your.Site/Subsite"
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($siteUrl)
$lookupList = $ctx.Web.Lists.GetByTitle('Bookings')
$query = New-Object Microsoft.SharePoint.Client.CamlQuery
$query.ViewXml = "<View>
<RowLimit></RowLimit>
</View>"
$listItems = $lookupList.getItems($query)
$ctx.Load($listItems)
$ctx.ExecuteQuery()
foreach($item in $listItems)
{
if([DateTime]$item["DueDate"] -lt [DateTime]::Now.Add([TimeSpan]::FromDays(3)) -and [DateTime]$item["DueDate"] -gt [DateTime]::Now)
{
$item["Title"]
}
}
I'm writing a script that clears out all of a list's existing items before writing new ones to it. Unfortunately, I can't figure out why my List is reporting that it has zero items in it when I can see all 90+ of them via Sharepoint. Here's the code I'm running:
function uploadDataFromCSV($_ctx, $_listName)
{
Write-Host "[$_listName]"
$list = $_ctx.Web.Lists.GetByTitle($_listName)
if($list.Exists){write-host "yes"}
$list.ItemCount # Always returns 0
# Clear all the items from the list if the flag has been set
if($OverwriteItems)
{
Write-Host 'Deleting contents of list'
$list.ItemCount
$listItems = $list.Items
# Delete from last to first because %REASONS%
for($index = $listItems.Count-1; $index -gt -1; $index--)
{
$listItems[$index].Delete()
}
Write-Host 'List has been reset'
}
Write-Host 'Reading CSV file'
$csv = Import-Csv "$csvDir\$_listName.csv"
$headers = $csv | Get-Member -MemberType NoteProperty | %{$_.name}
$itemsAdded = 0
foreach($line in $csv)
{
$itemCreateInfo = New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
$newItem = $list.AddItem($itemCreateInfo)
# Map each value in the line to its corresponding header
$headers | % {
$statement = [scriptblock]::Create('$newItem["{0}"] = $line.{0}' -f $_)
$statement.Invoke()
}
$newItem.Update()
$itemsAdded++
}
Write-Host' Importing items'
#Add the items to the list
#$_ctx.ExecuteQuery()
Write-Host $itemsAdded 'items imported'
}
#Load .NET CSOM modules
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
$site_url = "https://url.goes/here"
$username = "user#domain.com"
$password = ConvertTo-SecureString -AsPlainText -Force 'gibberishPassword'
#Set up the context and set its credentials
$ctx = New-Object Microsoft.SharePoint.Client.ClientContext($site_url)
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
$ctx.Credentials = $credentials
uploadDataFromCSV $ctx "TableName"
I need the number of items in the list so I can iterate through and delete them all one-by-one (I know I know, deleting the list and restoring from template isn't an option). I know I'm grabbing the correct list because the items I add further down the script are inserted correctly - after the script runs I can refresh Sharepoint and see the newly added items in addition to the list's existing items.
Why is $list.ItemCount saying there's nothing in the list?
When working with SharePoint CSOM in order to retrieve client object like List or its properties like List.ItemCount property it has to be requested using ClientContext.ExecuteQuery method.
In your case since List object has not been loaded, List.ItemCount property is not initialized, the following example demonstrates how to get List.ItemCount property:
$list = $context.Web.Lists.GetByTitle($listName) #get List object
$context.Load($list) #prepare query to load List object
$context.ExecuteQuery() #submit query to request List Object
$itemsCount = $list.ItemCount #ItemCount property is loaded now and returns list items count