Update Pages Approval Status in a Folder
This PnP PowerShell script automates the management of page approval status for all pages within a specific folder in SharePoint Online. It helps maintain content governance by programmatically updating approval workflows and status for multiple pages in a targeted folder structure.
Purpose
Bulk page approval management in folders enables you to:
- Update approval status for all pages in a specific folder
- Maintain content governance across page libraries
- Automate page publishing workflows
- Ensure compliance with content approval policies
Prerequisites
- PnP PowerShell module installed
- Page library edit permissions or higher
- Content approval enabled on target page libraries
- Connection to your SharePoint Online site
PowerShell Script
# SharePoint Online - Update Page Approval Status Script
# This script updates the approval status of all pages in a specific document library
# Variables - Update these as needed
$ClientId = ""
$SiteUrl = "https://tenantName.sharepoint.com/sites/siteName"
$LibraryName = "Site Pages"
$FolderName = "Supporting Documents" # Optional: Leave empty "" to process all pages
$ApprovalStatus = 0 # 0 for Approved
# Logging variables
$ScriptPath = $PSScriptRoot
if ([string]::IsNullOrEmpty($ScriptPath)) { $ScriptPath = Get-Location }
$TimeStamp = Get-Date -Format "yyyyMMdd_HHmmss"
$LogFile = Join-Path $ScriptPath "SharePoint_Approval_Update_Log_$TimeStamp.txt"
$CsvFile = Join-Path $ScriptPath "SharePoint_Approval_Update_Results_$TimeStamp.csv"
$Results = @()
# Function to write to log file
function Write-Log {
param(
[string]$Message,
[string]$Level = "INFO"
)
$TimeStamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogEntry = "[$TimeStamp] [$Level] $Message"
# Write to console
switch ($Level) {
"ERROR" { Write-Host $Message -ForegroundColor Red }
"WARNING" { Write-Host $Message -ForegroundColor Yellow }
"SUCCESS" { Write-Host $Message -ForegroundColor Green }
default { Write-Host $Message }
}
# Write to log file
try {
Add-Content -Path $LogFile -Value $LogEntry -ErrorAction SilentlyContinue
}
catch {
# If logging fails, continue without stopping the script
}
}
# Function to add result to CSV data
function Add-Result {
param(
$ItemId,
$ItemName,
$ItemUrl,
$OriginalStatus,
$NewStatus,
$Status,
$ErrorMessage = ""
)
$script:Results += [PSCustomObject]@{
ItemId = $ItemId
ItemName = $ItemName
ItemUrl = $ItemUrl
OriginalStatus = $OriginalStatus
NewStatus = $NewStatus
Status = $Status
ErrorMessage = $ErrorMessage
ProcessedDateTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
}
# Function to connect to SharePoint Online
function Connect-ToSharePoint {
param($SiteUrl)
try {
Write-Log "Connecting to SharePoint Online site: $SiteUrl" "INFO"
# Connect using interactive login (will prompt for credentials)
Connect-PnPOnline -Url $SiteUrl -Interactive -ClientId $ClientId
Write-Log "Successfully connected to SharePoint Online" "SUCCESS"
return $true
}
catch {
Write-Log "Error connecting to SharePoint: $($_.Exception.Message)" "ERROR"
return $false
}
}
# Function to update page approval status
function Update-PageApprovalStatus {
param(
$LibraryName,
$FolderName,
$ApprovalStatus
)
try {
if ([string]::IsNullOrEmpty($FolderName)) {
Write-Log "Getting all items from library: $LibraryName" "INFO"
$ListItems = Get-PnPListItem -List $LibraryName
} else {
Write-Log "Getting items from library: $LibraryName, folder: $FolderName" "INFO"
# Get items from specific folder
try {
$ListItems = Get-PnPListItem -List $LibraryName -FolderServerRelativeUrl "/sites/devintranet/SitePages/$FolderName"
}
catch {
Write-Log "Folder '$FolderName' not found with direct path. Trying alternative method..." "WARNING"
# Alternative: Get all items and filter by folder path
$AllItems = Get-PnPListItem -List $LibraryName
$ListItems = $AllItems | Where-Object {
$_.FileSystemObjectType -eq "File" -and
($_.FieldValues.FileDirRef -like "*/$FolderName" -or
$_.FieldValues.FileDirRef -like "*/$FolderName/*" -or
$_.FieldValues.FileRef -like "*/$FolderName/*")
}
}
}
if ($ListItems.Count -eq 0) {
if ([string]::IsNullOrEmpty($FolderName)) {
Write-Log "No items found in the library" "WARNING"
} else {
Write-Log "No items found in the folder '$FolderName'" "WARNING"
}
return
}
if ([string]::IsNullOrEmpty($FolderName)) {
Write-Log "Found $($ListItems.Count) items in the library" "SUCCESS"
} else {
Write-Log "Found $($ListItems.Count) items in folder '$FolderName'" "SUCCESS"
}
$SuccessCount = 0
$ErrorCount = 0
# Loop through each item and update approval status
foreach ($Item in $ListItems) {
try {
$ItemName = $Item["Title"]
if ([string]::IsNullOrEmpty($ItemName)) {
$ItemName = $Item["FileLeafRef"]
}
$ItemUrl = $Item.FieldValues.FileRef
$CurrentStatus = $Item.FieldValues["_ModerationStatus"]
Write-Log "Processing: $ItemName (ID: $($Item.Id))" "INFO"
Write-Log " Current moderation status: $CurrentStatus" "INFO"
# Update the approval status - try common approval status fields
$UpdateValues = @{}
if ($Item.FieldValues.ContainsKey("_ModerationStatus")) {
$UpdateValues["_ModerationStatus"] = $ApprovalStatus
}
if ($Item.FieldValues.ContainsKey("PublishingPageStatus")) {
$UpdateValues["PublishingPageStatus"] = $ApprovalStatus
}
if ($Item.FieldValues.ContainsKey("ApprovalStatus")) {
$UpdateValues["ApprovalStatus"] = $ApprovalStatus
}
# If no specific approval field found, try the moderation status
if ($UpdateValues.Count -eq 0) {
$UpdateValues["_ModerationStatus"] = $ApprovalStatus
}
Set-PnPListItem -List $LibraryName -Identity $Item.Id -Values $UpdateValues
Write-Log " ✓ Successfully updated approval status" "SUCCESS"
Add-Result -ItemId $Item.Id -ItemName $ItemName -ItemUrl $ItemUrl -OriginalStatus $CurrentStatus -NewStatus "Approved" -Status "Success"
$SuccessCount++
}
catch {
$ErrorMsg = $_.Exception.Message
Write-Log " ✗ Error updating item: $ErrorMsg" "ERROR"
Add-Result -ItemId $Item.Id -ItemName $ItemName -ItemUrl $ItemUrl -OriginalStatus $CurrentStatus -NewStatus "Failed" -Status "Failed" -ErrorMessage $ErrorMsg
$ErrorCount++
}
}
# Summary
Write-Log "`n=== UPDATE SUMMARY ===" "INFO"
Write-Log "Total items processed: $($ListItems.Count)" "INFO"
Write-Log "Successfully updated: $SuccessCount" "SUCCESS"
Write-Log "Errors encountered: $ErrorCount" "ERROR"
}
catch {
Write-Log "Error processing library: $($_.Exception.Message)" "ERROR"
}
}
# Function to enable content approval on the library (if needed)
function Enable-ContentApproval {
param($LibraryName)
try {
Write-Log "Checking if content approval is enabled for library: $LibraryName" "INFO"
$List = Get-PnPList -Identity $LibraryName
if (-not $List.EnableModeration) {
Write-Log "Content approval is not enabled. Enabling now..." "WARNING"
Set-PnPList -Identity $LibraryName -EnableContentApproval $true
Write-Log "Content approval has been enabled" "SUCCESS"
} else {
Write-Log "Content approval is already enabled" "SUCCESS"
}
}
catch {
Write-Log "Error checking/enabling content approval: $($_.Exception.Message)" "ERROR"
}
}
# Function to export results to CSV
function Export-ResultsToCsv {
try {
if ($Results.Count -gt 0) {
$Results | Export-Csv -Path $CsvFile -NoTypeInformation -Encoding UTF8
Write-Log "Results exported to CSV file: $CsvFile" "SUCCESS"
} else {
Write-Log "No results to export to CSV" "WARNING"
}
}
catch {
Write-Log "Error exporting results to CSV: $($_.Exception.Message)" "ERROR"
}
}
# Main execution
try {
# Initialize log file
Write-Log "=== SharePoint Online Page Approval Status Update Script Started ===" "INFO"
Write-Log "Script executed by: $env:USERNAME" "INFO"
Write-Log "Execution time: $(Get-Date)" "INFO"
Write-Log "Script location: $ScriptPath" "INFO"
Write-Log "Log file: $LogFile" "INFO"
Write-Log "CSV file: $CsvFile" "INFO"
Write-Log "" "INFO"
Write-Log "=== CONFIGURATION ===" "INFO"
Write-Log "Site: $SiteUrl" "INFO"
Write-Log "Library: $LibraryName" "INFO"
if (-not [string]::IsNullOrEmpty($FolderName)) {
Write-Log "Folder: $FolderName" "INFO"
}
Write-Log "New Approval Status: Approved (Value: $ApprovalStatus)" "INFO"
Write-Log "" "INFO"
# Confirm execution
$Confirmation = Read-Host "Do you want to proceed with updating all pages? (Y/N)"
if ($Confirmation -ne "Y" -and $Confirmation -ne "y") {
Write-Log "Script execution cancelled by user" "WARNING"
exit
}
# Connect to SharePoint
if (-not (Connect-ToSharePoint -SiteUrl $SiteUrl)) {
Write-Log "Failed to connect to SharePoint. Exiting." "ERROR"
exit
}
# Enable content approval if needed
Enable-ContentApproval -LibraryName $LibraryName
# Update page approval status
Update-PageApprovalStatus -LibraryName $LibraryName -FolderName $FolderName -ApprovalStatus $ApprovalStatus
# Export results to CSV
Export-ResultsToCsv
Write-Log "" "INFO"
Write-Log "=== SCRIPT EXECUTION COMPLETED ===" "SUCCESS"
Write-Log "Log file saved to: $LogFile" "INFO"
if ($Results.Count -gt 0) {
Write-Log "Results exported to: $CsvFile" "INFO"
}
}
catch {
Write-Log "Script execution failed: $($_.Exception.Message)" "ERROR"
}
finally {
# Disconnect from SharePoint
try {
Disconnect-PnPOnline
Write-Log "Disconnected from SharePoint Online" "INFO"
}
catch {
# Ignore disconnect errors
}
Write-Log "=== SCRIPT EXECUTION ENDED ===" "INFO"
}
Usage Notes
- Verify content approval is enabled on the Pages library
- Test script with a small folder before bulk operations
- Valid approval status values: Pending, Approved, Rejected, Draft
- Ensure appropriate permissions for page approval actions
- Consider notification requirements for status changes
- Script will skip items that are not pages (if any exist in folder)