Skip to content

Instantly share code, notes, and snippets.

@akashdborkar
Last active May 14, 2025 08:19
Show Gist options
  • Select an option

  • Save akashdborkar/54e599667a109f3a7b5bc2bd1f211430 to your computer and use it in GitHub Desktop.

Select an option

Save akashdborkar/54e599667a109f3a7b5bc2bd1f211430 to your computer and use it in GitHub Desktop.
A PowerShell script that uses Sitecore PowerShell Extensions to extract Sitecore items data to CSV and then use CSV to import data into Sitecore Items.
<#
.SYNOPSIS
Generic Page data extraction
.DESCRIPTION
Gets Sitecore Items from legacy database and extracts field values.
List could be exported to csv by OOTB feature of List View in SPE.
.NOTES
Akash Borkar
#>
function Write-LogExtended {
param(
[string]$Message,
[System.ConsoleColor]$ForegroundColor = $host.UI.RawUI.ForegroundColor,
[System.ConsoleColor]$BackgroundColor = $host.UI.RawUI.BackgroundColor
)
Write-Log -Object $message
Write-Host -Object $message -ForegroundColor $ForegroundColor -BackgroundColor $backgroundColor
}
# Function for getting item names from pipe-separated item ids
function GetItemNamesFromIds {
param(
[System.String] $ids
)
if($ids.Contains("|"))
{
# Split the string by pipe and clean up each GUID
$guids = $ids.Split("|")| ForEach-Object { $_.Trim(' {}')}
[Sitecore.Text.ListString]$nameArr = ""
foreach($id in $guids){
$formattedId = "{0}{1}{2}" -f '{', $id, '}'
$Id = [Sitecore.Data.ID]::Parse($formattedId)
$item = Get-Item -Path xyz: -ID $Id
if($item -ne $null -and !$nameArr.Contains($item.Name)){
$nameArr.Add($item.Name)| Out-Null
}
}
# Join the names with pipe separator and return the result
$names = [System.String]::Join("|", $nameArr)
return $names
}
else
{
$item = Get-Item -Path xyz: -ID $ids
return $item.Name
}
}
#Function for getting datasource item, which is further used for extracting field value & assigning to new rendering
function Get-DatasourceItem{
param(
[System.String] $path
)
$datasourceItem = $sourceDatabase.GetItem($path)
return $datasourceItem
}
Write-LogExtended "Generic Pages Data Extraction"
Write-LogExtended "-----------------------------------------------------------------"
$processedItems = [System.Collections.Generic.List[PSCustomObject]]::new()
$nonprocessedItems = [System.Collections.Generic.List[PSCustomObject]]::new()
$sourceDatabase = Get-Database "xyz"
$parentPath = Show-Input -Prompt "Please enter the Sitecore item path for getting children"
if($parentPath -ne $null)
{
Write-Host "Selected path: $parentPath"
#Get all child items based on provided path. /sitecore/content/XYZ/Home/Generic
$nodePath = "xyz:" + $parentPath
$items = Get-ChildItem -Path $nodePath -Recurse | Where-Object { $_.TemplateName -eq 'Generic Page'}
Write-LogExtended "Total child items: $($items.Count) Path: $($nodePath)" -ForegroundColor Green
foreach($sourceItem in $items)
{
if($sourceItem -ne $null){
#Retrieve RTE
$rts = Get-Rendering -Item $sourceItem -Device $defaultLayout -FinalLayout | Where-Object { $_.ItemID -eq "{278F7B0D-98F4-4873-9B7B-940082158E4A}"}
[Sitecore.Text.ListString]$rtArr = ""
if($rts -ne $null)
{
foreach($rt in $rts)
{
$item = $sourceDatabase.GetItem($rt.Datasource)
if($item -ne $null -and $item["Text"] -ne "")
{
$rtArr.Add($item["Text"])| Out-Null
}
}
}
#Retrieve Accordion
$accordion = Get-Rendering -Item $sourceItem -Device $defaultLayout -FinalLayout | Where-Object { $_.ItemID -eq "{165B5ECC-E6A0-4B41-AA23-D28FA5A9BF68}"}
$accordionCount = 0
[Sitecore.Text.ListString]$titleArr = ""
[Sitecore.Text.ListString]$descArr = ""
if($accordion -ne $null)
{
foreach($renderingItem in $accordion)
{
if($renderingItem.Datasource -ne "")
{
$rendering = Get-Item -Path xyz: -Id $renderingItem.Datasource
if($rendering.HasChildren)
{
$accdChildItems = Get-ChildItem -Path xyz: -ID $rendering.ID
foreach($item in $accdChildItems)
{
if($item["Title"] -ne "" -and $item["Description"] -ne "")
{
$titleArr.Add($item["Title"])| Out-Null
$descArr.Add($item["Description"])| Out-Null
}
}
$accordionCount++;
}
}
}
}
#Retrieve values of multilist field named Categories
$categories = $sourceitem["Categories"]
$categoriesnames = ""
if($categories -ne "" -and $categories -ne $null)
{
$categoriesnames = GetItemNamesFromIds -ids $categories
}
try{
$processedItems.Add(
[PSCustomObject]@{
Name = $sourceItem.Name
Id = $sourceItem.Id
Path = $sourceItem.Paths.FullPath
Title = $sourceItem["Title"]
HeaderTitle = $sourceItem["Header Title"]
Summary = $sourceItem["Summary"]
Image = $sourceItem["Image"]
OGImage = $sourceItem["Media Image"]
Categories = $categoriesnames
HasRTE = $rtArr.Count
RichText1 = $richText
RichText2 = $rtArr[1]
RichText3 = $rtArr[2]
HasAccordion = $accordionCount
AccTitle1 = $titleArr[0]
AccDesc1 = $descArr[0]
AccTitle2 = $titleArr[1]
AccDesc2 = $descArr[1]
AccTitle3 = $titleArr[2]
AccDesc3 = $descArr[2]
AccTitle4 = $titleArr[3]
AccDesc4 = $descArr[3]
}
)
Write-LogExtended "Added data for $($sourceItem.Name), Path: $($sourceItem.Paths.FullPath) " -ForegroundColor Green
}
catch{
Write-Host "Error occured" -BackgroundColor DarkRed
$nonprocessedItems.Add(
[PSCustomObject]@{
Name = $sourceItem.Name
Id = $sourceItem.Id
Path = $sourceItem.Paths.FullPath
}
)
}
}
else
{
Write-LogExtended "No Item found in csv for SourceURL: $($row.SourceURL)" -ForegroundColor RED
}
}
$processedItems | Show-ListView -PageSize 15000 -Property Name, Id, Path, Title, HeaderTitle, Summary, Categories, Image, OGImage,
HasRTE, RichText1, RichText2, RichText3, HasAccordion, AccTitle1, AccDesc1, AccTitle2, AccDesc2, AccTitle3,
AccDesc3, AccTitle4, AccDesc4
$processedItems | export-csv -Path "C:\inetpub\wwwroot\App_Data\Process.csv" -NoTypeInformation
$nonprocessedItems | Show-ListView -PageSize 15000 -Property Name, Id, Path
}
else
{
Write-Host "Path is not provided : $parentPath"
}
<#
.SYNOPSIS
Generic Pages Import
.DESCRIPTION
Iterate through CSV, create siteore items for generic pages and Populate fields. Generate List of processed and Non processed items.
By default, packages are saved to disk at C:\inetpub\wwwroot\App_Data\packages. Thus C:\inetpub\wwwroot\App_Data\GenericPages.csv will be
path
.NOTES
Akash Borkar
#>
functionWrite-LogExtended{
param(
[string]$Message,
[System.ConsoleColor]$ForegroundColor = $host.UI.RawUI.ForegroundColor,
[System.ConsoleColor]$BackgroundColor = $host.UI.RawUI.BackgroundColor
)
Write-Log -Object $message
Write-Host -Object $message -ForegroundColor $ForegroundColor -BackgroundColor $backgroundColor
}
Write-LogExtended"Generic Pages Import"
Write-LogExtended"-----------------------------------------------------------------"
# Prompt for the file path
$filePath = Show-Input -Prompt "Please enter the full path to the CSV file"
if($filePath -ne $null)
{
Write-Host"Selected file: $filePath"
# Import the CSV file
$csvData = Import-Csv -Path $filePath | Where-Object{ -join $_.psobject.Properties.Value }
Write-LogExtended"CSV file read successfully" -ForegroundColor Green
if($csvData -ne $null)
{
$processedItems = [System.Collections.Generic.List[PSCustomObject]]::new()
$NonProcessedItems = [System.Collections.Generic.List[PSCustomObject]]::new()
$database = Get-Database"master"
$placeholder = "/headless-main/container-1"
foreach($rowin$csvData){
#Generic Page branch
$branchTemplateId = [Sitecore.Data.ID]::Parse("{8032FE9E-3CD1-4E80-8377-66BBF74F839E}")
# Extract the desired item name, parent item and template id from the URL
$itemName = $row.Name
$parentItemPath = $row.Path -Replace $itemName, ""
# Get the parent item
$parentItem = $database.GetItem($parentItemPath)
if($parentItem)
{
# Check if the item already exists
$existingItemPath = "$($parentItem.Paths.FullPath)/$itemName"
$itemExists = Test-Path -Path $existingItemPath
if(-not $itemExists)
{
$item = [Sitecore.Data.Managers.ItemManager]::AddFromTemplate($itemName, $branchTemplateId, $parentItem)
if($item -eq $null)
{
Write-LogExtended"Unable to create new item - $($itemName) - in Language en" -ForegroundColor Red
$NonProcessedItems.Add(
[PSCustomObject]@{
ID = $row.ID
Name = $row.Name
Path = $row.Path
})
}
if($item -ne $null){
$item.Editing.BeginEdit()
$item["Title"] = $row.Title
#Meta Properties/OG
$item["OpenGraphTitle"] = $row.Title
$item["OpenGraphDescription"] = $row.Summary
$item["MetaDescription"] = $row.Summary
$item["TwitterDescription"] = $row.Summary
$item["TwitterImage"] = $row.OGImage
$item.Editing.EndEdit() | Out-Null
$datasourcePath = $item.Paths.FullPath + "/Data/"
#Create and Populate Rich Text (Max RT are 3 as we had extracted 3 RTEs)
if($row.RichText1 -ne "")
{
For($i=1; $i -lt 4; $i++)
{
$propname = "RichText$i"
if($row.$propname -ne "")
{
$dsitem = New-Item -Path $datasourcePath -Name "Text $i" -ItemType "{4FBDBF79-C7D6-42F1-8048-D5E70D6167D5}"
$dsitem.Editing.BeginEdit()
$dsitem.Text = $row.$propname
$dsitem.Editing.EndEdit() | Out-Null
#Create and Set Rich text Rendering
$rendering = get-item -path master: -id {EF82E4AE-C274-40D4-837C-B3E1BF180CCC}
$renderinginstance = $rendering | new-rendering -placeholder $placeholder
$renderinginstance.datasource = $dsitem.id
Add-Rendering -Item $item -placeholder $placeholder -instance $renderinginstance -finallayout
$item.Editing.beginedit()
$item.Editing.endedit() | out-null
}
}
}
#Create and Populate Accordion datasource item (Max Acc are 4)
if($row.AccTitle1 -ne "" -and $row.AccDesc1 -ne "")
{
$accDatasourcePath = $item.Paths.FullPath + "/Data/"
#Accordion
$Accitem = New-Item -Path $accDatasourcePath -Name "Accordion" -ItemType "{D482D45C-4248-46C8-BDD5-DE7C2255C52A}"
$Accitem.Editing.BeginEdit()
$Accitem.Title = "Accordion"
$Accitem.Editing.EndEdit() | Out-Null
#Create and Set Acc rendering
$rendering = Get-Item -Path master: -ID {3341A94D-42C9-4EE3-8A25-51D8B437982B}#Accordion
$renderingInstance = $rendering | New-Rendering -Placeholder $placeholder
$renderingInstance.Datasource = $Accitem.ID
Add-Rendering -Item $item -PlaceHolder $placeholder -Instance $renderingInstance -FinalLayout
For($i=1; $i -lt 5; $i++)
{
$titlename = "AccTitle$i"
$descname = "AccDesc$i"
if($row.$titlename -ne "" -and $row.$descname -ne "")
{
#Acc Panel
$dsitem = New-Item -Path $Accitem.Paths.FullPath -Name $row.$titlename -ItemType "{B50C502C-2740-44C8-A63E-E9E4AF4BAA4B}"
$dsitem.Editing.BeginEdit()
$dsitem.Title = $row.$titlename
$dsitem.Content = $row.$descname
$dsitem.Editing.EndEdit() | Out-Null
#Create and Set Acc panel rendering
$rendering = Get-Item -Path master: -ID {7614DFFF-6735-4BA5-929A-A82FBC91DB25}#Acc Panel
$renderingInstance = $rendering | New-Rendering -Placeholder "/headless-main/container-1/accordion-panels-1"
$renderingInstance.Datasource = $dsitem.ID
Add-Rendering -Item $item -PlaceHolder "/headless-main/container-1/accordion-panels-1" -Instance $renderingInstance -FinalLayout
$item.Editing.BeginEdit()
$item.Editing.EndEdit() | Out-Null
Write-LogExtended"Added Accordion datasource to New Item - $($item.Name) at $($dsitem.Paths.FullPath)" -ForegroundColor Green
}
}
}
$ManualWork = "No"
if(($row.HasRTE -gt 3) -or($row.HasAccordion -gt 4))
{
$ManualWork = "Yes"
}
Write-LogExtended"Created New Item - $($itemName) at $($parentItemPath)" -ForegroundColor Green
$processedItems.Add(
[PSCustomObject]@{
Name = $item.Name
Id = $item.ID
NewPath = $item.Paths.FullPath
HasRTE = $row.HasRTE
HasAccordion = $row.HasAccordion
ManualWork = $ManualWork
})
}
}
else
{
Write-LogExtended"Item $($itemName) already exists at $($parentItemPath) " -ForegroundColor Yellow
}
}
else
{
Write-LogExtended"Parent item not found: $parentItemPath" -ForegroundColor Red
}
}
$processedItems | Show-ListView -PageSize 2000 -InfoTitle "Processed Items" -Property Name, Id, NewPath, HasRTE, HasAccordion, ManualWork
$processedItems | export-csv -Path "C:\inetpub\wwwroot\App_Data\GenericPagesReport.csv" -NoTypeInformation
$NonProcessedItems | Show-ListView -PageSize 2000 -InfoTitle "Non Processed Items" -Property ID, Name, Path
}
}
else
{
Write-Host"No file selected : $filePath"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment