Monday, January 15, 2018

SharePoint Online: Export List Version History to Excel using PowerShell

Requirement: Export all versions of SharePoint Online List Items to CSV (Excel) file.
sharepoint online export list version history to excel using powershell
PowerShell to Extract and Export List Item's Version History 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"

Function Export-VersionHistory()
{
  param
    (
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ListName,
        [Parameter(Mandatory=$true)] [string] $CSVFile
    )
    Try {

        #Delete the Output report file if exists
        if (Test-Path $CSVFile) { Remove-Item $CSVFile }

        #Get 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
        
        #Get the List
        $List = $Ctx.Web.Lists.GetByTitle($ListName)
        $Ctx.Load($List)
        $Ctx.ExecuteQuery()
        
        #Get all items
        $Query = [Microsoft.SharePoint.Client.CamlQuery]::CreateAllItemsQuery()
        $ListItems = $List.GetItems($Query)
        $Ctx.Load($ListItems)
        $Ctx.ExecuteQuery()

        #Array to hold result
        $VersionHistoryData = @()

        #Iterate throgh each item
        Foreach ($Item in $ListItems)
        {
            write-host "Processing Item:" $item.id -f Yellow
            
            #Get all versions of the list item
            $Versions = $Item.versions
            $ctx.Load($Versions)
            $Ctx.ExecuteQuery()

            If($Versions.count -gt 0)
            {
                #Iterate each version
                Foreach($Version in $Versions)
                {
                    #Get the Creator object of the version
                    $CreatedBy =  $Version.createdby
                    $Ctx.Load($CreatedBy)
                    $Ctx.ExecuteQuery()

                    #Send Data to object array
                    $VersionHistoryData += New-Object PSObject -Property @{
                    'Item ID' = $Item.ID
                    'Title' =  $Version.FieldValues["Title"]
                    'Version Label' = $Version.VersionLabel 
                    'Version ID' = ($Version.VersionId/512)
                    'Created On' = (Get-Date ($Version.Created) -Format "yyyy-MM-dd/HH:mm:ss")
                    'Created By' = $CreatedBy.Email
                    }
                }
            }
        }
        
        #Export the data to CSV
        $VersionHistoryData | Export-Csv $CSVFile -Append -NoTypeInformation

        write-host -f Green "Version History Exported Successfully to:" $CSVFile
     }
    Catch {
        write-host -f Red "Error Exporting version History to CSV!" $_.Exception.Message
    }
}

#Set parameter values
$SiteURL="https://crescent.sharepoint.com"
$ListName="Projects"
$CSVFile="C:\Temp\VersionHistory.csv"

#Call the function to generate version History Report
Export-VersionHistory -SiteURL $SiteURL -ListName $ListName -CSVFile $CSVFile

Important: This script works ONLY on CSOM version 16.1.6906.1200 or Later! Download the latest version of CSOM SDK from https://www.microsoft.com/en-us/download/confirmation.aspx?id=42038

This script produces a CSV file with version data such as:
  • Version Label,
  • Version ID
  • When the version was created
  • Who created the version
  • Title field value of the version (You can add any additional field too!)


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


Thursday, January 4, 2018

SharePoint Online: Find and Delete Orphaned Users using PowerShell

find and delete orphaned users in sharepoint online

What is "Orphaned Users" in SharePoint Online?
In short, Orphaned users are those who deleted from the authentication provider (such as removed from Active Directory when user leaves the organization), and still continue to exist in SharePoint online sites! scanning each user in SharePoint online site collection for orphaned users could take days to complete! Since, Here is my PowerShell script to search for orphan users and delete them.

Pr-Requisites: Before using this script, you need to have SharePoint Online Management Shell (https://www.microsoft.com/en-us/download/details.aspx?id=35588) and Azure Active Directory Module (https://technet.microsoft.com/en-us/library/dn975125.aspx) installed on your machine!

Find Orphan Users in SharePoint Online using PowerShell:
This script scans each and every user from the given site collection URL and exports list of orphaned users to a CSV file.

#Import SharePoint Online and Azure Online modules
Import-Module Microsoft.Online.SharePoint.Powershell
Import-Module MSOnline

Function Generate-OrphanedUsersReport ()
{
param
    (
        [Parameter(Mandatory=$true)] [string] $AdminURL,
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ReportOutput        
    )
Try {
    #Get Credentials to connect
    $Cred = Get-Credential

    #Connect to SharePoint and Azure AD
    Connect-MsolService -Credential $cred
    Connect-SPOService -Url $AdminURL -Credential $Cred

    #Function to check if a user account exists
    Function Check-UserExists()
    {
        Param( [Parameter(Mandatory=$true)] [string]$UserID )
    
        $User=Get-Msoluser -UserPrincipalName $UserID -Erroraction SilentlyContinue
        if ($User -ne $null)
        {
            Return $True
        }
        else
        {
            Return $false
        }
    }
    $OrphanedUsers = @()

    #Get all users of a given SharePoint Online site collection
    $AllUsers = Get-SPOUser $SiteURL -Limit ALL

    Foreach($User in $AllUsers)
    {
        #Exclude Built-in User Accounts and Security Groups 
        if(($User.DisplayName.ToLower() -ne "nt authority\authenticated users") -and ($User.LoginName.ToLower() -ne "sharepoint\system") -and 
        ($User.DisplayName.ToLower() -ne "sharepoint app") -and ($user.IsGroup -eq $false ) -and(-not $user.DisplayName.ToLower().Contains("_spocache")) -and 
        (-not $user.DisplayName.ToLower().Contains("_spocrawl")) -and ($User.DisplayName.ToLower() -ne "sharepoint service administrator") -and 
        ($User.DisplayName.ToLower() -ne "guest contributor") -and ($User.DisplayName.ToLower() -ne "everyone except external users")-and ($User.DisplayName.ToLower() -ne "company administrator"))
        {
            Write-host "Checking user $($user.DisplayName)" -f Yellow
            #Check if user exists
            if((Check-UserExists $User.LoginName) -eq $False)
            {
                Write-Host "User Doesn't Exists: $($user.DisplayName) - $($User.LoginName)" -f Red

                #Send the Result to CSV 
                $Result = new-object PSObject
                $Result| add-member -membertype NoteProperty -name "LoginName" -Value $User.LoginName
                $Result | add-member -membertype NoteProperty -name "DisplayName" -Value $User.DisplayName
                $OrphanedUsers += $Result
            }
        }
    }
    #Export results to CSV
    $OrphanedUsers | Export-csv $ReportOutput -notypeinformation

        Write-host "Orphan Users Report Generated to $ReportOutput" -f Green
   }

    Catch {
    write-host -f Red "Error Deleting Unique Permissions!" $_.Exception.Message
    }
}

#Config Parameters
$AdminURL ="https://crescent-admin.sharepoint.com"
$SiteURL = "https://crescent.sharepoint.com"
$ReportOutput="C:\Temp\OrphanUsers.csv"

#Call the function to find and generate orphaned users report
Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $SiteURL -ReportOutput $ReportOutput
Be sure the CSV generated doesn't include any built-in user accounts and groups, prior providing the CSV file as an input to the next step of removing orphan users!

How to Delete Orphan Users from SharePoint Online with PowerShell: 
While its possible to remove each user from SharePoint online site collection individually, it becomes cumbersome when we have large number of orphan users to  remove! Here is the PowerShell script to read orphan users from the CSV file generated in previous step and remove them all in one go!
#Import SharePoint Online module
Import-Module Microsoft.Online.SharePoint.Powershell

Function Remove-OrphanedUsers ()
{
param
    (
        [Parameter(Mandatory=$true)] [string] $AdminURL,
        [Parameter(Mandatory=$true)] [string] $SiteURL,
        [Parameter(Mandatory=$true)] [string] $ReportInput        
    )
    Try {
        #Get Credentials to connect
        $Cred = Get-Credential
   
        #Connect to SharePoint online
        Connect-SPOService -Url $AdminURL -Credential $Cred

        #Get the Data from CSV and Add to SharePoint List
        $OrphanUsers = Import-Csv $ReportInput
        Foreach ($Row in $OrphanUsers) 
        {
            #Remove user from site
            Remove-SPOUser -Site $SiteURL -LoginName $Row.LoginName
            Write-host "Removed the Orphaned User $($Row.DisplayName) from $($SiteURL)"   
        }
            Write-host "Orphaned Users Removed from SharePoint Online Site!"
       }
    Catch {
    write-host -f Red "Error Deleting Unique Permissions!" $_.Exception.Message
    }
}

#Config Parameters
$AdminURL ="https://crescent-admin.sharepoint.com"
$SiteURL = "https://crescent.sharepoint.com"
$ReportInput="C:\Temp\OrphanUsers.csv"

#Call the function to Remove Orphaned users
Remove-OrphanedUsers -AdminURL $AdminURL -SiteURL $SiteURL -ReportInput $ReportInput
You can use these functions to find and/or remove orphaned users from all site collections. Just add:
Get-SPOSite -Limit all | ForEach-Object { 
  #Call the function to find and generate orphaned users report
  Generate-OrphanedUsersReport -AdminURL $AdminURL -SiteURL $_.Url -ReportOutput $ReportOutput
}


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


Wednesday, December 20, 2017

SharePoint Online: Add Site Column to List using PowerShell

Requirement: Add an existing site column to SharePoint list or library using PowerShell.

How to Add a Site Column to SharePoint Online List?
Site columns in SharePoint provides great re-usability without having to recreate same columns multiple times! Once created at top level site, we can utilize them to store metadata in any number of lists and libraries under the hierarchy. To add a site column to SharePoint list, follow these steps:
  • Go to List Settings >> Under Columns, Click on "Add from existing site columns" link.
  • From the available site columns, pick the required site column(s) and click on Add button.
    sharepoint online powershell to add site column to list
  • Click OK to save your changes.

Add Site Column to List or Library with 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"
 
#Variables
$SiteURL="https://crescent.sharepoint.com"
$ListName="Projects"
$SiteColumnName="Department"

$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
$Web = $Ctx.web

#Get the list
$List=$Ctx.Web.Lists.GetByTitle($ListName)
    
#Get the Site column
$Field = $Web.Fields.GetByTitle($SiteColumnName)

#Add the site column to the list
$List.Fields.Add($Field)
$ctx.ExecuteQuery() 
    
Write-host "Site Column Added to the List Successfully!" -f Green
Lets add some error handling to the above code to handle scenarios, such as:
  • What if the given site column doesn't exist?
  • What if the given site column is already added to the list?
  • What if the given list doesn't exist? or what if the given credentials are invalid?, etc.
PowerShell to Add a Site Column to SharePoint 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"
 
#Parameters
$SiteURL="https://crescent.sharepoint.com"
$ListName="Projects"
$SiteColumnName="Department"

Try {
    $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
    $Web = $Ctx.web

    #Get the Site column from web
    $SiteColumns = $Web.Fields
    $Ctx.Load($SiteColumns)
    $Ctx.ExecuteQuery()
    $SiteColumn = $SiteColumns | Where {$_.Title -eq $SiteColumnName}
    
    #Check if given site column exists
    if($SiteColumn -eq $Null)
    {
        Write-host "Site Column $SiteColumnName doesn't exists!" -f Yellow
    }
    else
    {
        #Get the list
        $List=$Ctx.Web.Lists.GetByTitle($ListName)

        #Check if the Filed exist in list already
        $Fields = $List.Fields
        $Ctx.Load($List)
        $Ctx.Load($Fields)
        $Ctx.ExecuteQuery() 
        $Field = $Fields | where {$_.Title -eq $SiteColumnName}
        if($Field -ne $NULL)  
        {
            Write-host "Column Name $SiteColumnName already exists in the list!" -f Yellow
        }
        else
        {
            #Add the site column to the list
            $NewColumn = $List.Fields.Add($SiteColumn)
            $ctx.ExecuteQuery() 
    
            Write-host "Site Column Added to the List Successfully!" -f Green
        }
    }
}
Catch {
    write-host -f Red "Error Adding Site Column to List!" $_.Exception.Message
}


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


Tuesday, November 28, 2017

How to Add a Custom Tile to SharePoint 2016 App Launcher

Requirement: Add new tile to App Launcher in SharePoint Online.

How to Add a Custom Tile to SharePoint 2016 App Launcher?
We wanted to place a new tile in SharePoint 2016 app launcher for support center site, as an end-user usability improvement. SharePoint 2016 Feature Pack 1 brought us the capability to add new tile to app launcher. Here is how you can customize SharePoint 2016 App launcher.

Step 1: Enable the "Custom Tiles" feature in SharePoint 2016 with PowerShell:
Use this PowerShell script to enable custom tiles feature. 
Enable-SPFeature -Identity CustomTiles -Url "http://intranet.crescent.com" -Force
This creates a new list "Custom Tiles" in the given web application's root site collection.

Step 2: Create new Tile in "Custom Tiles" list
Once the feature is activated, navigate to: http://intranet.crescent.com/Lists/Custom%20Tiles/AllItems.aspx URL and add a new entry with desired URL and image for tile for your custom tile. Please note, this list is hidden from browser interface, so you should use the link to directly in the browser to navigate to the list.sharepoint 2016 app launcher customize

It may take up to 24 hours for the new tile to reflect. Clear your browser cache, or open the browser in Private mode to see the new tile in action.
how to add custom tile in sharepoint 2016





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


Sunday, November 12, 2017

SharePoint Online: Grant Permission to List Item using PowerShell

Permissions are hierarchical in SharePoint from Top Site collection till the List Item level. To set unique permissions on list items, you need to configure permissions on item level. Here is how:

How to Grant Access to Individual List Items in SharePoint Online?
Got a business requirement to grant permissions at List item level. To set explicit permissions on SharePoint online list items, we need to break the permission inheritance first (stop inheriting permissions) and then add user or group to the List Item.
  • Go to your SharePoint Online list or library >> Select the Item to which you want to provide unique permissions. 
  • Click on "Shared With" button from the ribbon. On the Shared With page, click Advanced.
    set item level permission in sharepoint online
  • On the Permissions tab, in the Inheritance group, click Stop Inheriting Permissions button. Confirm the prompt.
    sharepoint online list item permissions powershell
  • Now, from the ribbon, click on "Grant Permissions." button. In the Share dialog box, enter names, email addresses. Click the Show Options button. In the Select A Permission Level list box, select appropriate permission level such as Edit.
    powershell to grant permission to list item in sharepoint online
  • Click Share.
Having too many Item level permissions often leads to performance issues! so, be careful.

SharePoint Online: Set List Item Permissions 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"

#To call non-generic method Load(list, x => x.HasUniqueRoleAssignments)
Function Invoke-LoadMethod() {
    param(
            [Microsoft.SharePoint.Client.ClientObject]$Object = $(throw "Please provide a Client Object"),
            [string]$PropertyName
        ) 
   $ctx = $Object.Context
   $load = [Microsoft.SharePoint.Client.ClientContext].GetMethod("Load") 
   $type = $Object.GetType()
   $clientLoad = $load.MakeGenericMethod($type)

   $Parameter = [System.Linq.Expressions.Expression]::Parameter(($type), $type.Name)
   $Expression = [System.Linq.Expressions.Expression]::Lambda([System.Linq.Expressions.Expression]::Convert([System.Linq.Expressions.Expression]::PropertyOrField($Parameter,$PropertyName),[System.Object] ), $($Parameter))
   $ExpressionArray = [System.Array]::CreateInstance($Expression.GetType(), 1)
   $ExpressionArray.SetValue($Expression, 0)
   $clientLoad.Invoke($ctx,@($Object,$ExpressionArray))
}

Function Set-ListItemPermission
{
    param
    (   
        [Parameter(Mandatory=$true)] [string]$SiteURL,
        [Parameter(Mandatory=$true)] [string]$ListName,
        [Parameter(Mandatory=$true)] [string]$ItemID,
        [Parameter(Mandatory=$true)] [string]$PermissionLevel,
        [Parameter(Mandatory=$true)] [string]$UserID
    )
    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
        
        #Get the List and Item
        $List = $Ctx.Web.Lists.GetByTitle($ListName)
        $ListItem=$List.GetItemByID($ItemID)
        $Ctx.Load($List)
        $Ctx.Load($ListItem)
        $Ctx.ExecuteQuery()

        #Check if Item has unique permission already
        Invoke-LoadMethod -Object $list -PropertyName "HasUniqueRoleAssignments"
        $Ctx.ExecuteQuery()

        #Break Item's permision Inheritance, if its inheriting permissions from the parent
        if (-not $ListItem.HasUniqueRoleAssignments)
        {
            $ListItem.BreakRoleInheritance($false, $false) #keep the existing permissions: No -  Clear listitems permissions: No
            $ctx.ExecuteQuery()
        }

        #Get the User
        $User = $Ctx.Web.EnsureUser($UserID)
        $Ctx.load($User)
        $Ctx.ExecuteQuery()

        #Get the role 
        $Role = $Ctx.web.RoleDefinitions.GetByName($PermissionLevel)
        $RoleDB = New-Object Microsoft.SharePoint.Client.RoleDefinitionBindingCollection($Ctx)
        $RoleDB.Add($Role)
         
        #Assign permissions
        $UserPermissions = $ListItem.RoleAssignments.Add($User,$RoleDB)
        $ListItem.Update()
        $Ctx.ExecuteQuery()
    
        Write-host -f Green "Permission granted to List Item successfully!"
    }
    Catch {
        Write-host -f Red "Error granting permission to List Item!" $_.Exception.Message
    }
}

#Set parameter values
$SiteURL="https://crescent.sharepoint.com"
$ListName="Projects"
$ItemID="1"
$UserID="salaudeen@crescent.com"
$PermissionLevel="Edit"

#Call the function
Set-ListItemPermission -SiteURL $SiteURL -ListName $ListName -ItemID $ItemID -UserID $UserID -PermissionLevel $PermissionLevel 

This script grants permission on Item level for given user. If you want to provide permission to SharePoint Group, Instead of line
$User = $Web.EnsureUser($UserAccount)
#use:
$Group =$Web.SiteGroups.GetByName($GroupName)
#and then
$GroupPermissions = $Item.RoleAssignments.Add($Group,$RoleDB)


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...