This post was most recently updated on September 17th, 2020.
3 min read.The news is out – Delve Blogs will be axed, leaving your users without a blogging platform on Office 365, and their data homeless. And by homeless, I mean deleted. Might be a good time to start thinking about storing it somewhere else instead!
This post is the second post in my impromptu, Delve Blogs -themed blog series:
- Part 1: Delve Blogs getting deprecated – what do?
- Part 2: How to export your Delve blogs content? (this post)
- Part 3: How to migrate your Delve Blogs content to Modern SharePoint?
While we’re all still waiting to see whether Microsoft sticks to their ambitious schedule (partial content freeze in December 2019, total content freeze in January 2020, and finally, total content deletion in April 2020), and whether they’ll finally offer a migration option or not, it probably doesn’t hurt to get ready for the move by yourself – so I’m offering one way to export the content from your tenant’s Delve blogs!
How to export Delve Blogs content
I crafted this handy little script for exporting the content as a CSV, and all of the used header pictures as separate images in the defined “temp folder”.
You can set the location for the exported CSV with all of the Delve blogs content as well. Authors of different blog posts will also be stored.
Just like described in my earlier post about Delve Blogs deprecation, the script is loosely based on Drew Madelung’s excellent script to report on Delve Blog usage.
You’ll need the following things to run this:
- SharePointPnPPowershellOnline PowerShell module
- At least SharePoint-admin credentials
PowerShell script to export Delve blogs’ content
function Make-ServerRelative ($path) {
return $path.Substring($path.IndexOf("sharepoint.com/")+14)
}
try {
# Variables for export
$creds = Get-Credential
$tenantadmin = "https://contoso-admin.sharepoint.com"
$outputfilepath = "c:\temp\delveblogexport.csv"
$tempfolder = "c:\temp"
# Variables for modern blog creation
$modernBlogUrl = "https://contoso.sharepoint.com/sites/blogposts"
# Connect to tenant to get blog sites
Connect-PnPOnline $tenantadmin -Credentials $creds
$sites = Get-PnPTenantSite -Template POINTPUBLISHINGPERSONAL#0
$resultsarray = @()
# Loop through sites to get details for blog
foreach($s in $sites){
Connect-PnPOnline $s.Url -Credentials $creds
$ctx = Get-PnPContext
$list = Get-PnPList -Identity "Pages"
$pagecount = $list.ItemCount
$contributor = Get-PnPGroupMembers -Identity "Contributors" | select Email
$items = Get-PnPListItem -List $list
$ctx.ExecuteQuery();
Write-Host "Exporting from: "$s.Url -ForegroundColor Yellow
foreach($i in $items){
$ctx.Load($i)
$ctx.Load($i.File)
$ctx.ExecuteQuery()
$path = $s.Url + "/pPg/" + $i.File.Name
$path = Make-ServerRelative $path
Write-Host "Exporting page "$path
$f = Get-PnPFile -Url $path -AsString
$lastmodified = (Get-PnPFile -Url $path).TimeLastModified
$o = ConvertFrom-Json $f
$title = $o.Title
$subTitle = $o.SubTitle
$content = ""
$filename = $i.File.Name
$headerImage = ""
$color = ""
$listItem = Get-PnPListItem -List $list -Id $i.Id
$ctx.Load($listItem)
$ctx.ExecuteQuery()
$listItem = $listItem.LastItemUserModifiedDate
$props = $o.ControlData.psobject.properties.name
$count = $props | measure-object
for ($index = 0; $index -lt $count.Count; $index++)
{
$propName = $props[$index]
Write-Host "Exporting item: "$index" "$propName" of type " $o.ControlData.$propName.ControlType
# Header content
if ($o.ControlData.$propName.ControlType -eq 4)
{
$content += "<h1>"+$o.ControlData.$propName.DataContext.Title+"</h1><h2>"+$o.ControlData.$propName.DataContext.Subtitle+"</h2>"
$headerImage = $o.ControlData.$propName.DataContext.ImageSource
continue;
}
# Text content
if ($o.ControlData.$propName.ControlType -eq 0) {
$content += $o.ControlData.$propName.DataContext.Value
}
# Picture content
if ($o.ControlData.$propName.ControlType -eq 1) {
$content += "<img src='"+$o.ControlData.$propName.DataContext.ImageSource+"' /><caption>"+$o.ControlData.$propName.DataContext.CaptionText+"</caption>"
}
# Document content
if ($o.ControlData.$propName.ControlType -eq 8) {
$content += "<a href='"+$o.ControlData.$propName.DataContext.OfficeDocumentDataContext.DocPath+"'>"+$o.ControlData.$propName.DataContext.Annotation+"</a>"
}
# Video content
if ($o.ControlData.$propName.ControlType -eq 9) {
$content += "<a href='"+$o.ControlData.$propName.DataContext.VideoSource+"'><caption><img src='"+$o.ControlData.$propName.DataContext.ImageSource+"' />"+$o.ControlData.$propName.DataContext.CaptionText+"</caption></a>"
}
}
if ($null -ne $headerImage -and $headerImage.IndexOf('#') -ge 0)
{
$color = $headerImage
}
else
{
try
{
$serverRelativeImageHeaderUrl = Make-ServerRelative $headerImage
$imgFile = Get-PnPFile -Url $serverRelativeImageHeaderUrl
Get-PnPFile -Url $serverRelativeImageHeaderUrl -Path $tempfolder -AsFile
}
catch {
Write-Host "There was likely no header image present, so couldn't export it."
}
}
# Add to the export object
$obj = New-Object PSObject
Add-Member -InputObject $obj -MemberType NoteProperty -Name DelveBlogUrl -Value $s.Url
Add-Member -InputObject $obj -MemberType NoteProperty -Name BlogPageCount -Value $pagecount
Add-Member -InputObject $obj -MemberType NoteProperty -Name Email -Value $contributor.Email
Add-Member -InputObject $obj -MemberType NoteProperty -Name LastModified -Value $lastmodified
Add-Member -InputObject $obj -MemberType NoteProperty -Name Title -Value $title
Add-Member -InputObject $obj -MemberType NoteProperty -Name Subtitle -Value $subTitle
Add-Member -InputObject $obj -MemberType NoteProperty -Name HeaderImage -Value $headerImage
Add-Member -InputObject $obj -MemberType NoteProperty -Name Content -Value $content
Add-Member -InputObject $obj -MemberType NoteProperty -Name FileName -Value $filename
Add-Member -InputObject $obj -MemberType NoteProperty -Name HeaderFile -Value $imgFile.Name
Add-Member -InputObject $obj -MemberType NoteProperty -Name ThemeColor -Value $color
$resultsarray += $obj
$obj = $null
}
}
# Export results
$resultsarray | Export-Csv -Path $outputfilepath -NoTypeInformation -Force
Write-Host "Export Complete" -ForegroundColor Green
Disconnect-PnPOnline
}
catch
{
Write-Host $_.Exception.Message -ForegroundColor Red
}
It’s not super pretty, but at least it’s modifiable. Feel free to tweak to your needs!
What’s next?
Tomorrow, I’ll be posting about importing this content into Modern SharePoint Communication site as new articles with (somewhat) matching styling.
- M365 Copilot claiming “You have turned off web search in the work mode”? Easy fix! - November 19, 2024
- “Performing cleanup” – Excel is stuck with an old, conflicted file and will never recover. - November 12, 2024
- How to add multiple app URIs for your Entra app registration? - November 5, 2024