Find Column Usage
This PnP PowerShell script checks where a defined set of site columns are used across a SharePoint Online site. For each column, it scans every visible list and library — and their associated content types — to produce a clear picture of where that column is in use. Results are exported to a CSV for review.
Purpose
Understanding where site columns are used is essential when you need to:
- Audit metadata before renaming or removing a column
- Verify that columns have been correctly deployed to the right lists and content types
- Identify unused columns that are candidates for cleanup
- Map column dependencies before a site restructure or migration
- Troubleshoot why a column is not appearing where expected
What the script reports
For each column in your list, the exported CSV records:
- ColumnInternalName — the internal name as defined in SharePoint
- ColumnDisplayName — the display name shown to users
- UsageType — whether the column is found in a List/Library, a List Content Type, a Site Content Type, or is Not Used
- LocationName — the name of the list, library, or site level location
- LocationUrl — the server-relative URL of the list or library
- ContentTypeName — the content type the column belongs to, where applicable
Prerequisites
- PnP PowerShell module installed
- Site collection administrator permissions
- Access to your PnP app Client Id
PowerShell Script
# Configuration variables
$SiteUrl = "https://tenantName.sharepoint.com/sites/siteName"
$ClientId = "" # Enter Client ID
# Connect to your site
Connect-PnPOnline -Url $SiteUrl -ClientId $ClientId -Interactive
# Array of site column internal names to check
$columnsToCheck = @(
"Key",
"Order",
"Order1"
)
# Results array
$results = @()
Write-Host "Starting site column usage check..." -ForegroundColor Cyan
Write-Host "Site: $SiteUrl" -ForegroundColor Cyan
Write-Host "Checking $($columnsToCheck.Count) columns" -ForegroundColor Cyan
Write-Host "="*60
foreach ($columnInternalName in $columnsToCheck) {
Write-Host "`nChecking column: $columnInternalName" -ForegroundColor Yellow
# Get the site column
$siteColumn = Get-PnPField -Identity $columnInternalName -ErrorAction SilentlyContinue
if ($null -eq $siteColumn) {
Write-Host " x Site column not found!" -ForegroundColor Red
$results += [PSCustomObject]@{
ColumnInternalName = $columnInternalName
ColumnDisplayName = "NOT FOUND"
UsageType = "N/A"
LocationName = "N/A"
LocationUrl = "N/A"
ContentTypeName = ""
}
continue
}
$usageFound = $false
# Check all lists in the site
$lists = Get-PnPList | Where-Object { $_.Hidden -eq $false }
foreach ($list in $lists) {
# Get fields for this list
$listFields = Get-PnPField -List $list.Title -ErrorAction SilentlyContinue
# Check if the site column is used in this list
$fieldInList = $listFields | Where-Object { $_.InternalName -eq $columnInternalName }
if ($null -ne $fieldInList) {
$usageFound = $true
Write-Host " Found in List: $($list.Title)" -ForegroundColor Green
# Add to results
$results += [PSCustomObject]@{
ColumnInternalName = $columnInternalName
ColumnDisplayName = $siteColumn.Title
UsageType = "List/Library"
LocationName = $list.Title
LocationUrl = $list.RootFolder.ServerRelativeUrl
ContentTypeName = ""
}
# Check if it's in any content types of this list
$listContentTypes = Get-PnPContentType -List $list.Title
foreach ($ct in $listContentTypes) {
$ctFields = Get-PnPProperty -ClientObject $ct -Property Fields
if ($ctFields.InternalName -contains $columnInternalName) {
Write-Host " - Used in Content Type: $($ct.Name)" -ForegroundColor Cyan
$results += [PSCustomObject]@{
ColumnInternalName = $columnInternalName
ColumnDisplayName = $siteColumn.Title
UsageType = "List Content Type"
LocationName = $list.Title
LocationUrl = $list.RootFolder.ServerRelativeUrl
ContentTypeName = $ct.Name
}
}
}
}
}
# Check site content types
$siteContentTypes = Get-PnPContentType
foreach ($ct in $siteContentTypes) {
$ctFields = Get-PnPProperty -ClientObject $ct -Property Fields
if ($ctFields.InternalName -contains $columnInternalName) {
$usageFound = $true
Write-Host " Found in Site Content Type: $($ct.Name)" -ForegroundColor Green
$results += [PSCustomObject]@{
ColumnInternalName = $columnInternalName
ColumnDisplayName = $siteColumn.Title
UsageType = "Site Content Type"
LocationName = "Site Level"
LocationUrl = ""
ContentTypeName = $ct.Name
}
}
}
if (-not $usageFound) {
Write-Host " Column not used anywhere in this site" -ForegroundColor Yellow
$results += [PSCustomObject]@{
ColumnInternalName = $columnInternalName
ColumnDisplayName = $siteColumn.Title
UsageType = "Not Used"
LocationName = ""
LocationUrl = ""
ContentTypeName = ""
}
}
}
# Export to CSV
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
$csvPath = "C:\Temp\SiteColumnUsage_$timestamp.csv"
$results | Export-Csv -Path $csvPath -NoTypeInformation -Encoding UTF8
Write-Host "`n="*60
Write-Host "Check complete!" -ForegroundColor Green
Write-Host "Results exported to: $csvPath" -ForegroundColor Green
Write-Host "Total columns checked: $($columnsToCheck.Count)" -ForegroundColor Cyan
Write-Host "Total usage records: $($results.Count)" -ForegroundColor Cyan
Usage Notes
- Update
$SiteUrland$ClientIdbefore running - Add the internal names of the columns you want to check to the
$columnsToCheckarray - Internal names are case-sensitive — use the exact name as defined in the site column, not the display name
- The script only scans visible lists; hidden system lists are excluded
- The CSV output path defaults to
C:\Temp\— update this if the folder does not exist on your machine - For large sites with many lists and content types, the script may take several minutes to complete