Tuesday, January 31, 2017

SharePoint Online: Download Attachments from List using PowerShell

Requirement: Download attachments from SharePoint Online List

PowerShell to download attachments from a List Item:
Lets download SharePoint list item attachment programmatically from a particular list item.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

Function Download-ListItemAttachments()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ListName,
        [Parameter(Mandatory=$true)] [string] $ListItemID,
        [Parameter(Mandatory=$true)] [string] $DownloadPath
    )    
   Try {
        #Setup Credentials to connect
        $Cred = Get-Credential
        $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)
    
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Cred

        #Get the List Item
        $List = $Ctx.Web.Lists.GetByTitle($ListName)
        $ListItem= $List.GetItemByID($ListItemID)
    
        #Get All attachments from the List Item
        $AttachmentsColl = $ListItem.AttachmentFiles
        $Ctx.Load($AttachmentsColl)
        $Ctx.ExecuteQuery()
    
        #Get each attachment
        ForEach($Attachment in $AttachmentsColl)
        {
            #Download attachment
            $FileContent = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Ctx, $Attachment.ServerRelativeUrl)
            $FileStream = [System.IO.File]::Create($DownloadPath+$Attachment.FileName)
            $FileContent.Stream.CopyTo($FileStream)
            $FileStream.Close()
       }

        write-host  -f Green "Total List Attachments Downloaded : $($AttachmentsColl.count)"
    }
    Catch {
        write-host -f Red "Error Downloading List Item Attachments!" $_.Exception.Message
    } 
}

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/"
$ListName="Projects"
$ListItemID="1"
$DownloadPath="C:\Temp\"

#Call the function to copy list items
Download-ListItemAttachments -SiteURL $SiteURL -ListName $ListName -ListItemID $ListItemID -DownloadPath $DownloadPath

Download Attachments from All Items in the List using PowerShell:
Here is the PowerShell to download SharePoint Online list attachments from all items.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

Function Download-ListAttachments()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ListName,
        [Parameter(Mandatory=$true)] [string] $DownloadDirectory
    )    
   Try {
        #Setup Credentials to connect
        $Cred = Get-Credential
        $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)
    
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Cred

        #Get All Items from the List
        $List = $Ctx.Web.Lists.GetByTitle($ListName)
        $ListItems = $List.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
        $Ctx.Load($ListItems)
        $Ctx.ExecuteQuery()
        
        #Create download directory if it doesn't exist
        If (!(Test-Path -path $DownloadDirectory))        
        {            
            New-Item $DownloadDirectory -type directory          
        }
        
        #Iterate through each list item
        Foreach($Item in $ListItems)
        {
            #Get All attachments from the List Item
            $AttachmentsColl = $Item.AttachmentFiles
            $Ctx.Load($AttachmentsColl)
            $Ctx.ExecuteQuery()

            #Get attachment for each list item
            ForEach($Attachment in $AttachmentsColl)
            {
                #Download attachment
                $FileContent = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Ctx, $Attachment.ServerRelativeUrl)
                $FileName= $DownloadDirectory+$Item.id.ToString()+"_"+$Attachment.FileName
                $FileStream = [System.IO.File]::Create($FileName)
                $FileContent.Stream.CopyTo($FileStream)
                $FileStream.Close()
           }
        }

        write-host  -f Green "List Attachments Downloaded Successfully!"
    }
    Catch {
        write-host -f Red "Error Downloading List Attachments!" $_.Exception.Message
    } 
}

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/"
$ListName="Projects"
$DownloadDirectory="C:\Temp\"

#Call the function to copy list items
Download-ListAttachments -SiteURL $SiteURL -ListName $ListName -DownloadDirectory $DownloadDirectory


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


SharePoint Online: Copy List Items from One List to Another using PowerShell

Requirement:Copy List items to another list in SharePoint Online

How to copy list items to another list in SharePoint Online?
Use Quick Edit (Datasheet view) to copy-paste list items between lists in SharePoint online. Make sure you have matching columns and column order is same in both views.
copy list items to another list sharepoint online

SharePoint Online: Copy List Item to Another List using PowerShell
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

Function Copy-ListItems()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceListName,
        [Parameter(Mandatory=$true)] [string] $TargetListName
    )    
    Try {
        #Setup Credentials to connect
        $Cred = Get-Credential
        $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)
    
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Cred

        #Get the Source List and Target Lists
        $SourceList = $Ctx.Web.Lists.GetByTitle($SourceListName)
        $TargetList = $Ctx.Web.Lists.GetByTitle($TargetListName)
    
        #Get All Items from Source List
        $SourceListItems = $SourceList.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
        $Ctx.Load($SourceListItems)
        $Ctx.ExecuteQuery()
    
        #Get each column value from source list and add them to target
        ForEach($SourceItem in $SourceListItems)
        {
            $NewItem =New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
            $ListItem = $TargetList.AddItem($NewItem)
        
            #Map each field from source list to target list - INTERNAL NAMES
            $ListItem["Title"] = $SourceItem["Title"]
            $ListItem["IsActive"] = $SourceItem["IsActive"]
            $ListItem["ProjectStartDate"] = $SourceItem["ProjectStartDate"]
            $ListItem["Department"] = $SourceItem["Department"]
            $ListItem["Priority"] = $SourceItem["Priority"]
            $ListItem.update()
        }
        $Ctx.ExecuteQuery()

        write-host  -f Green "Total List Items Copied from '$SourceListName' to '$TargetListName' : $($SourceListItems.count)"
    }
    Catch {
        write-host -f Red "Error Copying List Items!" $_.Exception.Message
    }
}

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/"
$SourceListName="Projects Template"
$TargetListName="Project Innovate"

#Call the function to copy list items
Copy-ListItems -siteURL $SiteURL -SourceListName $SourceListName -TargetListName $TargetListName
This script copies all mapped column values from the source to the target list. Lets enhance the script bit to automatically copy all columns matching from the source to target list.

SharePoint Online: Copy List items using PowerShell
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

Function Copy-ListItems()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceListName,
        [Parameter(Mandatory=$true)] [string] $TargetListName
    )    
    Try {
        #Setup Credentials to connect
        $Cred = Get-Credential
        $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)
    
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Cred

        #Get the Source List and Target Lists
        $SourceList = $Ctx.Web.Lists.GetByTitle($SourceListName)
        $TargetList = $Ctx.Web.Lists.GetByTitle($TargetListName)
    
        #Get All Items from Source List
        $SourceListItems = $SourceList.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
        $Ctx.Load($SourceListItems)
        $Ctx.ExecuteQuery()
    
        #Get All fields from Source List & Target List
        $SourceListFields = $SourceList.Fields
        $Ctx.Load($SourceListFields)
        $TargetListFields = $TargetList.Fields
        $Ctx.Load($TargetListFields)        
        $Ctx.ExecuteQuery()

        #Get each column value from source list and add them to target
        ForEach($SourceItem in $SourceListItems)
        {
            $NewItem =New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
            $ListItem = $TargetList.AddItem($NewItem)        
 
            #Map each field from source list to target list
            Foreach($SourceField in $SourceListFields)
            {  
                #Skip Read only, hidden fields, content type and attachments
                If((-Not ($SourceField.ReadOnlyField)) -and (-Not ($SourceField.Hidden)) -and ($SourceField.InternalName -ne  "ContentType") -and ($SourceField.InternalName -ne  "Attachments") )  
                {
                    $TargetField = $TargetListFields | where { $_.Internalname -eq $SourceField.Internalname}
                    if($TargetField -ne $null)
                    {
                        #Copy column value from source to target
                        $ListItem[$TargetField.InternalName] = $SourceItem[$SourceField.InternalName]  
                    }
                }
            }
            $ListItem.update()
            $Ctx.ExecuteQuery()
        }

        write-host  -f Green "Total List Items Copied from '$SourceListName' to '$TargetListName' : $($SourceListItems.count)"
    }
    Catch {
        write-host -f Red "Error Copying List Items!" $_.Exception.Message
    }
}

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/"
$SourceListName="Projects Template"
$TargetListName="Project Innovate"

#Call the function to copy list items
Copy-ListItems -siteURL $SiteURL -SourceListName $SourceListName -TargetListName $TargetListName

PowerShell to Copy List Items with Attachments from One List to another List: 
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

Function Copy-ListItems()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $SourceListName,
        [Parameter(Mandatory=$true)] [string] $TargetListName
    )    
    Try {
        #Setup Credentials to connect
        $Cred = Get-Credential
        $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)
    
        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Cred

        #Get the Source List and Target Lists
        $SourceList = $Ctx.Web.Lists.GetByTitle($SourceListName)
        $TargetList = $Ctx.Web.Lists.GetByTitle($TargetListName)
    
        #Get All Items from Source List
        $SourceListItems = $SourceList.GetItems([Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery())
        $Ctx.Load($SourceListItems)
        $Ctx.ExecuteQuery()
    
        Write-host "Total Number of List Items Found in the source:"$SourceListItems.count

        #Get All fields from Source List & Target List
        $SourceListFields = $SourceList.Fields
        $Ctx.Load($SourceListFields)
        $TargetListFields = $TargetList.Fields
        $Ctx.Load($TargetListFields)        
        $Ctx.ExecuteQuery()

        #Get each column value from source list and add them to target
        ForEach($SourceItem in $SourceListItems)
        {
            $NewItem =New-Object Microsoft.SharePoint.Client.ListItemCreationInformation
            $ListItem = $TargetList.AddItem($NewItem)        
 
            #Map each field from source list to target list
            Foreach($SourceField in $SourceListFields)
            {  
                #Skip Read only, hidden fields, content type and attachments
                If((-Not ($SourceField.ReadOnlyField)) -and (-Not ($SourceField.Hidden)) -and ($SourceField.InternalName -ne  "ContentType") -and ($SourceField.InternalName -ne  "Attachments") )  
                {
                    $TargetField = $TargetListFields | where { $_.Internalname -eq $SourceField.Internalname}
                    if($TargetField -ne $null)
                    {
                        #Copy column value from source to target
                        $ListItem[$TargetField.InternalName] = $SourceItem[$SourceField.InternalName]  
                    }
                }
            }
            
            $ListItem.update()
            $Ctx.ExecuteQuery()

            #Copy attachments
            $AttachmentsColl = $SourceItem.AttachmentFiles
            $Ctx.Load($AttachmentsColl)
            $Ctx.ExecuteQuery()

            ForEach($Attachment in $AttachmentsColl)
            {
                $AttachmentCreation = New-Object Microsoft.SharePoint.Client.AttachmentCreationInformation

                #Get the Source attachment
                $FileContent = [Microsoft.SharePoint.Client.File]::OpenBinaryDirect($Ctx, $Attachment.ServerRelativeUrl)
                $Buffer = New-Object byte[]($FileContent.length)
                $BytesRead = $FileContent.stream.Read($Buffer, 0, $Buffer.Length)
                $ContentStream = New-Object -TypeName System.IO.MemoryStream ($Buffer)

                $AttachmentCreation.ContentStream = $ContentStream
                $AttachmentCreation.FileName = $Attachment.FileName 
                [void]$ListItem.AttachmentFiles.Add($AttachmentCreation)
                $Ctx.ExecuteQuery()                
            }
            Write-host "Copied Item to the Target List:"$SourceItem.id -f Yellow
        }

        write-host  -f Green "Total List Items Copied from '$SourceListName' to '$TargetListName' : $($SourceListItems.count)"
    }
    Catch {
        write-host -f Red "Error Copying List Items!" $_.Exception.Message
    }
}

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/"
$SourceListName="Projects"
$TargetListName="Project Temp"

#Call the function to copy list items
Copy-ListItems -siteURL $SiteURL -SourceListName $SourceListName -TargetListName $TargetListName

Here is my another post for SharePoint On-premises to copy list item: Copy SharePoint List Item to Another List using PowerShell

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Monday, January 30, 2017

SharePoint Online: How to Enable Versioning on a Document Library using PowerShell

What is versioning in SharePoint Online?
Version history feature in SharePoint Online tracks every change to the document and creates a copy of it when someone changes a document. Each version of the document has the following:
  • Version No
  • When the version was created
  • Who made the version (change)
  • Size of the version
Once the versioning feature is enabled, you can view/restore the previous versions of the document.

How to Enable Version History in SharePoint Online Document Library?
To Enable or Disable Versioning in SharePoint Online Document Library:
  • Navigate to your document library >> Click on Settings gear >> and then "Library Settings" Menu item.
  • Under Library settings page, Click on "Versioning Settings"
  • Select "Create major versions" option and enter number of versions to track (by default, this is enabled with 500 versions in SharePoint Online). sharepoint online powershell to enable versioning in document library
  • Scroll to the bottom of the page. Click "OK" to apply versioning setting changes.

SharePoint Online: PowerShell to enable versioning in document library
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"

Function Enable-DocLibraryVersioning()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $DocLibraryName
    )    
    Try {
    #Setup Credentials to connect
    $Cred = Get-Credential
    $Cred = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.UserName,$Cred.Password)

    #Setup the context
    $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
    $Ctx.Credentials = $Cred

    #Get the Library from the web
    $Library = $Ctx.Web.Lists.GetByTitle($DocLibraryName)

    #enable versioning in sharepoint online
    $Library.EnableVersioning = $True
    $Library.MajorVersionLimit = 50

    $Library.update()
    $Ctx.ExecuteQuery()
    
    write-host  -f Green "Version History Enabled for Document Library!"
    }
    Catch {
        write-host -f Red "Error enabling versioning in Document Library!" $_.Exception.Message
    }
}

#Set Parameters
$SiteURL= "https://crescent.sharepoint.com/"
$DocLibraryName="Project Docs"

#Call the function to enable versioning in document library
Enable-DocLibraryVersioning -siteURL $SiteURL -DocLibraryName $DocLibraryName

To Enable version history on all lists and libraries, use: 
SharePoint Online: Enable Versioning on All List and Libraries using PowerShell

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Explorer View in SharePoint Online

SharePoint Online Explorer view provides great flexibility like Windows Explorer functionality to manage Files and folders. Majority of the usage: drag and drop!

Where is Explorer View in SharePoint Online?
Explorer view in SharePoint online modern UI is moved under View section! To enable explorer view in sharepoint online,
  • Click on the View menu drop down from top-right area ( such as "All Documents")  >> Select "View in File Explorer" Menu item. >> This opens the document library in explorer view for SharePoint Online.
explorer view in sharepoint online

SharePoint Online explorer view not working? or Greyed out?
Explorer view is available only on 32 bit version of Internet Explorer! You cannot open in explorer view on Google Chrome or Microsoft Edge browsers.

Now SharePoint Online modern document libraries also provides drag and drop functionalities. E.g.
  • You can do multiple file upload with drag and drop
  • Create folders and drag and drop files to it with in browser itself. (You can't drag and drop a folder however!). 
  • You can copy/move files within the SharePoint Online libraries using Modern document library user interface.
Tags: sharepoint online explorer view not working, sharepoint online view in windows explorer, sharepoint online open in explorer view, using explorer view in sharepoint online, sharepoint online explorer view greyed out, sharepoint online cannot open in explorer view

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


How to Disable Quick Edit in SharePoint?

Requirement:  Disable quick edit in SharePoint 2016 list.

How to disable quick edit in sharepoint 2013 or SharePoint 2016?
Bit background: We've a project tracking list with field "Project Health" which is updated by an event receiver based on certain parameters and business logic. So, we made the field hidden in SharePoint online using: SharePoint Online: How to Hide a Column from NewForm/EditForm?

Now the problem is: users can go to "Quick Edit" mode of the list and they get hidden field there! Although the column was hidden from Edit and New Forms, SharePoint quick edit (which replaced Datasheet view in previous versions of SharePoint) still displays the hidden field and we decided to disable quick edit mode for the SharePoint list.

SharePoint how to disable quick edit:
To disable quick edit mode in SharePoint 2013/2016 or in SharePoint online,
  • Go to the list settings >> Click on "Advanced settings" link
  • In Advanced Settings link, Scroll down and Under "Quick property editing " option, choose "No" for "Allow items in this list to be edited using Quick Edit?" and then click OK.
    sharepoint 2013 disable quick edit powershell
  • This disables quick edit in SharePoint list.

Disable quick edit using PowerShell
Here is how we can disable quick edit sharepoint 2013 programmatically with PowerShell.
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue

#Parameters
$WebURL="http://intranet.crescent.com"
$ListName="Projects"

#Get Web and List objects
$Web = Get-SPWeb $WebURL
$List = $Web.Lists.TryGetList($ListName)

$List.DisableGridEditing=$true
$List.Update()

CSOM to disable quick edit in SharePoint online: Unfortunately, this property is not exposed in SharePoint CSOM. So, you can't disable quick edit using CSOM. As a workaround you can hide the quick edit button with CSS (or create a list, disable quick edit using above UI method, save the list as template, and then create a new list instance from the template).
how to disable quick edit in sharepoint 2013

CSS to disable quick edit in SharePoint Online  
Alternatively, you can hide Quick Edit button in the ribbon with CSS also. Here is the CSS to hide sharepoint quick edit:
<style>
#Ribbon\.List\.ViewFormat\.Datasheet-Large {
display:none;
}
</style>
Click on Settings Gear >> Edit Page >> Click on "Add Web Part " link and then Add script editor web part. Edit snippet and Place this CSS code in it, Stop Editing to save your changes. For Libraries, use: #Ribbon\.Library\.ViewFormat\.Datasheet-Large

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Wednesday, January 25, 2017

SharePoint Online: Update User Profile Properties using PowerShell

Requirement: Update User Profile Property in SharePoint Online using PowerShell

How to Update User Profiles in SharePoint Online?
To update SharePoint Online user profile properties, follow these steps:
  • Login to SharePoint Online Admin Center >> Click on "User Profiles" link from the left navigation
  • In User Profiles, Click on "Manage User Profiles" under People tab. Use Search to find the user profile of the user to update >> Click on "Edit My Profile" link from the context menu drop down of the user result.
  • Update any allowed user profile property and click on "Save and Close" button.
    powershell sharepoint online user profile properties
SharePoint Online: Update user profile using PowerShell

Here is the PowerShell for SharePoint Online to set User profile properties.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll"

Function Update-UserProfileProperty()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $AdminCenterURL,
        [Parameter(Mandatory=$true)] [string] $UserAccount,
        [Parameter(Mandatory=$true)] [string] $PropertyName,
        [Parameter(Mandatory=$true)] [string] $PropertyValue
    )    
    Try {
        #Setup Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($AdminCenterURL)
        $Ctx.Credentials = $Credentials
        
        #Get the User
        $User = $Ctx.web.EnsureUser($UserAccount)
        $Ctx.Load($User)
        $Ctx.ExecuteQuery()

        #Get User Profile
        $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Ctx)
        
        #update User Profile Property
        $PeopleManager.SetSingleValueProfileProperty($User.LoginName, $PropertyName, $PropertyValue)
        $Ctx.ExecuteQuery()

        Write-host "User Profile Property has been Updated!" -f Green
    }
    Catch {
        write-host -f Red "Error Updating User Profile Property!" $_.Exception.Message
    }
}
#Define Parameter values
$AdminCenterURL="https://crescent-admin.sharepoint.com"
$UserAccount="Zahia@Crescent.com"
$PropertyName="Department"
$PropertyValue="Operations - IT"

#Call the function
Update-UserProfileProperty -AdminCenterURL $AdminCenterURL -UserAccount $UserAccount -PropertyName $PropertyName -PropertyValue $PropertyValue

PowerShell for SharePoint Online User profile properties Update:
There are fields with Multi-values in People profiles. E.g. Skills! Lets update Multi-valued fields in SharePoint Online user profiles.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll"

Function Update-MultiUserProfileProperty()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $AdminCenterURL,
        [Parameter(Mandatory=$true)] [string] $UserAccount,
        [Parameter(Mandatory=$true)] [string] $PropertyName,
        [Parameter(Mandatory=$true)] [System.Collections.Generic.List``1[System.string]] $PropertyValues
    )    
    Try {
        #Setup Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($AdminCenterURL)
        $Ctx.Credentials = $Credentials
        
        #Get the User
        $User = $Ctx.web.EnsureUser($UserAccount)
        $Ctx.Load($User)
        $Ctx.ExecuteQuery()

        #Get User Profile
        $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Ctx)
        $PropertyValues
        #update User Profile Property
        $PeopleManager.SetMultiValuedProfileProperty($User.LoginName, $PropertyName, $PropertyValues)
        $Ctx.ExecuteQuery()

        Write-host "User Profile Property has been Updated!" -f Green
    }
    Catch {
        write-host -f Red "Error Updating User Profile Property!" $_.Exception.Message
    }
}
#Define Parameter values
$AdminCenterURL="https://crescent-admin.sharepoint.com"
$UserAccount="SPAdmin@crescent.com"
$PropertyName="SPS-Skills"
$PropertyValues = New-Object "System.Collections.Generic.List``1[System.string]"
$PropertyValues.Add("SharePoint")
$PropertyValues.Add("PowerShell")
$PropertyValues.Add("C#")

#Call the function
Update-MultiUserProfileProperty -AdminCenterURL $AdminCenterURL -UserAccount $UserAccount -PropertyName $PropertyName -PropertyValues $PropertyValues


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Tuesday, January 24, 2017

SharePoint Online: Get User Profile Properties using PowerShell

Requirement: SharePoint Online Get All User Profiles and export to CSV.

How to Get All user Profiles and User Profile Properties in SharePoint Online?
  • Login to SharePoint Online Admin Center >> Click on "User Profiles" link from left navigation
  • In User Profiles, Click on "Manage User Profiles" under People tab. Use Search to get the user profile of the user.
    SharePoint online get all user profiles powershell
This interface helps us to get individual user profiles and properties one by one. Lets use PowerShell to get all user profiles in SharePoint Online.

SharePoint Online PowerShell to Get User Profile Properties
This PowerShell gets the specific property "Department" of the particular user from given site collection.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll"

Function Get-SPOUserProfileProperty()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $AdminSiteURL,
        [Parameter(Mandatory=$true)] [string] $UserAccount,
        [Parameter(Mandatory=$true)] [string] $Property
    )    
    Try {
        #Setup Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($AdminSiteURL)
        $Ctx.Credentials = $Credentials
        
        #Get the User
        $User = $Ctx.web.EnsureUser($UserAccount)
        $Ctx.Load($User)
        $Ctx.ExecuteQuery()

        #Get User Profile
        $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Ctx)
        $UserProfile = $PeopleManager.GetPropertiesFor($User.LoginName)
        $Ctx.Load($UserProfile)
        $Ctx.ExecuteQuery()
        
        #Get the User Profile Property
        Write-host $UserProfile.UserProfileProperties[$Property]

    }
    Catch {
        write-host -f Red "Error Getting User Profile Properties!" $_.Exception.Message
    }
}
#Call the function
$AdminSiteURL="https://crescent-admin.sharepoint.com"
$UserAccount="Kacper@crescent.com"
$Property="Department"

Get-SPOUserProfileProperty -AdminSiteURL $AdminSiteURL -UserAccount $UserAccount -Property $Property
This PowerShell gets the particular property of a specific user. How to get all user profiles of a site collection?

Get All User Profiles in SharePoint Online Site Collection using PowerShell
Here is how to user profile in SharePoint online using PowerShell.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll"

Function Export-SPOUserProfileProperties()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $CSVPath
    )    
    Try {
        #Setup Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($SiteURL)
        $Ctx.Credentials = $Credentials
        
        #Delete the CSV report file if exists
        if (Test-Path $CSVPath) { Remove-Item $CSVPath }

        #Get all Users
        $Users = $Ctx.Web.SiteUsers
        $Ctx.Load($Users)
        $Ctx.ExecuteQuery()
        
        Write-host "Total Number of Profiles Found:"$Users.count -f Yellow
        #Get User Profile Manager
        $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Ctx)
        #Array to hold result
        $UserProfileData = @()

        Foreach ($User in $Users)
        {
            Write-host "Processing User Name:"$User.LoginName
            #Get the User Profile
            $UserProfile = $PeopleManager.GetPropertiesFor($User.LoginName)
            $Ctx.Load($UserProfile)
            $Ctx.ExecuteQuery()
            if($UserProfile.Email -ne $Null)
            {
            #Send Data to object array
            $UserProfileData += New-Object PSObject -Property @{
            'User Account' = $UserProfile.UserProfileProperties["UserName"]
            'Full Name' = $UserProfile.UserProfileProperties["PreferredName"]
            'E-mail' =  $UserProfile.UserProfileProperties["WorkEmail"]
            'Department' = $UserProfile.UserProfileProperties["Department"]
            'Location' = $UserProfile.UserProfileProperties["Office"]
            'Phone' = $UserProfile.UserProfileProperties["WorkPhone"]
            'Job Title' = $UserProfile.UserProfileProperties["Title"]
            }
            }
        }
        #Export the data to CSV
        $UserProfileData | Export-Csv $CSVPath -Append -NoTypeInformation

        write-host -f Green "User Profiles Data Exported Successfully to:" $CSVPath
    }
    Catch {
        write-host -f Red "Error Exporting User Profile Properties!" $_.Exception.Message
    }
}

#Call the function
$SiteURL="https://crescent.sharepoint.com"
$CSVPath="C:\Temp\UserProfiles.csv"

Export-SPOUserProfileProperties -SiteURL $SiteURL -CSVPath $CSVPath
This PowerShell script gets user profiles from given site collection and exports them to Excel file (CSV). Well, How do we extract user profiles for all site collections? There is no direct way to connect to User Profile Service Application in SharePoint Online and get all user profile properties for all users in the tenant using CSOM. Either you'll have iterate through all Site Collections (and remove duplicates among them!) or use Web Services to connect to SharePoint Online and retrieve all user profiles.

However, There is a better way: Lets use the Combination of SharePoint Online CSOM and Azure AD Connect!

Pr-Requisites: Make sure you have SharePoint Online Client SDK (https://www.microsoft.com/en-us/download/details.aspx?id=42038) and Azure Active Directory Module (https://technet.microsoft.com/en-us/library/dn975125.aspx) installed on your client machine, before using this script!

SharePoint Online Get User Profile Properties using PowerShell 
Rather getting user profiles belong to a particular site collection, lets get all user profiles of the tenant and export user profile properties to CSV file.
#Load SharePoint CSOM Assemblies
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.dll"
Add-Type -Path "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "C:\Program Files\Common Files\microsoft shared\Web Server Extensions\16\ISAPI\Microsoft.SharePoint.Client.UserProfiles.dll"
#Import Azure AD Module
Import-Module MSOnline

Function Export-AllUserProfiles()
{
    param
    (
        [Parameter(Mandatory=$true)] [string] $TenantURL,
        [Parameter(Mandatory=$true)] [string] $CSVPath
    )    
    Try {
        #Setup Credentials to connect
        $Cred= Get-Credential
        $Credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($Cred.Username, $Cred.Password)

        #Setup the context
        $Ctx = New-Object Microsoft.SharePoint.Client.ClientContext($TenantURL)
        $Ctx.Credentials = $Credentials
        
        #Delete the CSV report file if exists
        if (Test-Path $CSVPath) { Remove-Item $CSVPath }

        #Get all Users
        Connect-MsolService -Credential $Cred
        $Users = Get-MsolUser -All |  Select-Object -ExpandProperty UserPrincipalName
        
        Write-host "Total Number of Profiles Found:"$Users.count -f Yellow
        #Get User Profile Manager
        $PeopleManager = New-Object Microsoft.SharePoint.Client.UserProfiles.PeopleManager($Ctx)
        #Array to hold result
        $UserProfileData = @()

        Foreach ($User in $Users)
        {
            Write-host "Processing User Name:"$User
            #Get the User Profile
            $UserLoginName = "i:0#.f|membership|" + $User  #format to claims
            $UserProfile = $PeopleManager.GetPropertiesFor($UserLoginName)
            $Ctx.Load($UserProfile)
            $Ctx.ExecuteQuery()
            if($UserProfile.Email -ne $Null)
            {
            #Send Data to object array
            $UserProfileData += New-Object PSObject -Property @{
            'User Account' = $UserProfile.UserProfileProperties["UserName"]
            'Full Name' = $UserProfile.UserProfileProperties["PreferredName"]
            'E-mail' =  $UserProfile.UserProfileProperties["WorkEmail"]
            'Department' = $UserProfile.UserProfileProperties["Department"]
            'Location' = $UserProfile.UserProfileProperties["Office"]
            'Phone' = $UserProfile.UserProfileProperties["WorkPhone"]
            'Job Title' = $UserProfile.UserProfileProperties["Title"]
            }
            }
        }
        #Export the data to CSV
        $UserProfileData | Export-Csv $CSVPath -Append -NoTypeInformation

        write-host -f Green "User Profiles Data Exported Successfully to:" $CSVPath
  }
    Catch {
        write-host -f Red "Error Exporting User Profile Properties!" $_.Exception.Message
    } 
}

#Call the function
$TenantURL="https://crescent.sharepoint.com"
$CSVPath="C:\Temp\UserProfiles.csv"

Export-AllUserProfiles -TenantURL $TenantURL -CSVPath $CSVPath
This script extracts all user profiles from SharePoint online Tenant to a CSV File with following properties:
  • Account
  • Full Name
  • E-Mail
  • Department
  • Location,
  • Job Title
You can add additional properties. Here is the Report output created by the PowerShell Script:
get user profile sharepoint online powershell


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Friday, January 20, 2017

SharePoint Online: How to Make a Site Collection Read Only?

Requirement: SharePoint Online Make Site Collection Read only.

How to make a SharePoint Online Site Read Only?
We've a business requirement to set a SharePoint online site collection into read-only mode, in order to prevent any further addition/modification of content but make the existing content available as read-only to the end users. Unlike SharePoint On-premises, there are no direct ways (Central Admin/PowerShell) to make a SharePoint Online site or site collection read only. However, we can use site policies in SharePoint Online to make site collection read only.
You can set the SharePoint online site collection lock status to "NoAccess" - But it defeats the purpose of Read-only mode!
SharePoint Online: Make a Site Collection read only using  site policies
Here is how to use SharePoint site policies for SharePoint Online to make site collection read only:
  • Navigate to the site collection that you want to make Read Only >> Click on Settings Gear and then Site Settings Menu item.
  • Click on "Site Policies" under Site Collection Administration. 
  • Create a new policy by clicking "Create" link
  • Provide a Name to your Policy, say for e.g. "Read only", optionally the Description. Set the following options and click on "OK" to create site policy:
    • Do not close or delete site automatically
    • Check the option "The site collection will be read only when it is closed"
      sharepoint online make site read only
This will create a Read only policy. So now, We have defined the site policy which will not close or delete the site automatically but will set the site to read-only mode when its closed.

Apply the policy and close the site:
Now the next step is to apply the policy and close the site.
  • Go to Site Settings >> Click on Site Closure & Deletion under Site Administration
  • Select the Site Policy you created in the previous step and click on Close this site now. (At times, You may have to select the policy and Click OK and then visit the "Site Closure & Deletion" page again to click "Close this site now" button)
    sharepoint online make site collection read only
That's it! Now you can see your site is set to read only mode with a notification at the top saying the site is read only!
how to make sharepoint online site read only
You can clear read-only mode and make the site editable by re-opening the closed site again, so that its available for users to add and update.

You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


Sunday, January 8, 2017

Get User Account By Display Name in SharePoint

Requirement: Get user by display name in SharePoint
We have a CSV file with list of projects and their Team leads information. This list to be updated on a SharePoint list. But the challenge is 'Team Lead' field has display names of users instead of account name (Domain\LoginID). So prior updating to SharePoint list, we need the Login ID of the user from his display name.

Solution: Lets Query Active directory for the given display name to get the user's Login ID.

Prerequisites: You need to have PowerShell module for Active directory installed to use: Import-Module ActiveDirectory! Use PowerShell cmdlet: Add-WindowsFeature RSAT-AD-PowerShell to add AD Module for PowerShell to your server/desktop! Otherwise, you'll get an error message: "Import-Module : The specified module 'ActiveDirectory' was not loaded because no valid module file was found in any module directory"

PowerShell script to get user accounts from display name and update SharePoint List:
Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
Import-Module ActiveDirectory

#Configuration Variables
$SiteURL = "http://intranet.crescent.com/"
$ListName = "Projects"                
$FieldName="Team Lead"
$CSVFile ="C:\TeamLeads.csv" 

#Custom Function Get User Account from Display Name in AD 
Function Get-UserAccount($DisplayName)
{
    $UserAccount=Get-ADUser -LDAPFilter "(displayName=$DisplayName)" | Select sAMAccountName
    if($UserAccount.sAMAccountName -ne $null)
    {
        return $UserAccount.sAMAccountName.tostring()
    }
    else
    {
        write-host $DisplayName not found in AD! -f Red
        return $null
    }
} 
#Import from CSV file - CSV has Headers ("ProjectName", "TeamLead")
$CSVData = Import-CSV -path $CSVFile

#Get the Target Web & List
$Web = Get-SPWeb -identity $WebURL
$List = $web.Lists[$ListName]
 
#Iterate through each Row in the CSV file
foreach ($Row in $CSVData) 
{
    #Filter by Project Name
 $Item = $List.Items | Where-Object { $_["Project Name"] -eq $Row.ProjectName }
  
 #If the matching project found
    If($Item -ne $null)
    {
  write-host "Searching for:"$Row.TeamLead
  #Get the User Account from Display Name
  $UserAccount = Get-UserAccount $Row.TeamLead
  
  #If User account found in AD
        if($UserAccount -ne $null)
        {
            $TeamLead=$web.ensureuser($UserAccount)
     
      #Update Team member field
   $item["Team Lead"] = $TeamLead
   $item.Update()
         Write-Host "Updated Project:"$Row.ProjectName -ForegroundColor Green
  }
  else
  {
   write-host "No matching User Account Found for :"$Row.TeamLead -f Red
  }
    }
    else
    {
        write-host "No matching List Item Found for:"$Row.ProjectName -f Red
    }  
}
Using SPUtility's ResolvePrincipal Method: Instead of querying Active directory, you can also use SPUtility's ResolvePrincipal method to get a user by display name:
$Web = Get-SPWeb "http://intranet.crescent.com"
$DisplayName="Barunx Romeih"
$Principal = [Microsoft.SharePoint.Utilities.SPUtility]::ResolvePrincipal($web, $DisplayName, "All", "All", $null, $false)
$Principal.LoginName


You might also like:
SharePoint Usage Reports
Usage reports, collaboration and audit for SharePoint.
Document SharePoint Farm
Automatically generate SharePoint documentation.
*Sponsored


You might also like:

Related Posts Plugin for WordPress, Blogger...