Programmatically update embded hyperlink on a document on SP document library , with PowerShell

I worked on a migration project where content for MS word document also needed to be changed after migration.

In a nutshell in my old SharePoint I had a Library which all word documents had embedded hyperlinks which linked to the Version History of items on SharePoint and labelled as Version History.

So after the migration I have to find a way to replace http://OLDSERVENAME/Site/MyLibaray/MyItem/VersionHistory to http://SERVERNAME/site/MyLibrary/Myitem/VersionHistory for these hyperlinks embedded on the word documents.

So the world of Word Automation with PowerShell came to rescue me. Note that you need to have word dll install on your server before running this scripts. See the link below for more information:

http://blogs.technet.com/b/heyscriptingguy/archive/2009/05/14/how-can-i-use-windows-powershell-to-look-for-and-replace-a-word-in-a-microsoft-word-document.aspx

The basic principle of my scripts was: first check the approval status. If published only change the hyper link and save the document without changing the version number. If it was draft the scripts still change the hyperlink but I was not interested the version number to be changes or not.

Here is my scripts:

# add SharePoint snap in

If ((Get-PSSnapIn -Name Microsoft.SharePoint.PowerShell ) -eq $null )

{ Add-PSSnapIn -Name Microsoft.SharePoint.PowerShell } Write-Output “”

add-type -AssemblyName “Microsoft.Office.Interop.Word”

$wdunits = “Microsoft.Office.Interop.Word.wdunits” -as [type]

$donotsave = “Microsoft.Office.Interop.Word.wdDoNotSaveChanges” -as [type]

$save = “Microsoft.Office.Interop.Word.wdSaveChanges” -as [type]

$application = New-Object -ComObject word.application

$application.Visible = $false

$OldServerName = “OLDSERVERNAME”

# go to the destination site

$SPWeb = Get-SPWeb “http://SERVERNAME/site/subsite”

$SPwebURL = $SPWeb.URL

# get number of items on my library

$Output = “There are ” + $SPWeb.Lists.Count + ” lists”

#write-Output $Output

$Mylist = $SPWeb.Lists[“MyLibraryName”]

$Output = “I am ” + $Mylist.Title

write-Output $Output

# get list GUID

$ListGUID = $MYlist.ID

$Output = “I have ” + $Mlist.ItemCount + ” items.”

write-Output $Output

$MyItems = $Mylist.Items

foreach ($Item in $MyItems| where {$_.Name -match “.doc”}) # to filter based on a column name category you can use {$_.Properties.Category -match “Document”}

{

$Output = $Item.name + ” is ” + $Item.level

Write-Output $Output

# get document’s approval status; we are only interested on a published documents.

$modeinfo = $Item.ModerationInformation

$status = $Item.ModerationInformation.Status

$Output = $Item.name + ” is ” + $status

Write-Output $Output

$DocumentLocation = $SPwebURL + “/”+ $Item.URL

$Output = $DocumentLocation + ” about to be opened”

Write-Output $Output

$document = $application.Documents.Open($DocumentLocation)

$DocURLs = $Document.Hyperlinks

$needToSave = $False

$URLsToChange = $False

$NeedToPublish = $False

$NeedToUnPublish = $False

# First we see if there is anything to do

foreach ($URL in $DocURLs | where {$_.Address -match $OldServerName})

{

$URLsToChange = $True

$NeedToSave = $True

if ($Item.level -eq “Published”)

{

$NeedToUnPublish = $True

$NeedToPublish = $true

}

}

if ($NeedToUnPublish -eq $True)

{

$Item.File.UnPublish(” “)

$Item.File.Update();

$Output = $Item.name + ” has been unpublished and updated”

Write-Output $Output

}

if ($URLsToChange -eq $True)

{

foreach ($URL in $DocURLs | where {$_.Address -match $OldServerName})

{

# We only want to do this if the title text we are looking exist (eg. version history )

if ($URl.TextToDisplay -match “Version”)

{

$NewAddress = $SPwebURL + “/_layouts/Versions.aspx?list={” + $ListGUID + “}&ID=” + $Item.ID

$URl.Address = $NewAddress

$NeedToSave = $true

Write-Output “Version history link has been updated”

}

# If not version history but has a reference to oldserver

if ($URl.Address -match $OldServerName)

{

# Replace server name and replace the GUID of the list

$URl.Address = ” “

$NeedToSave = $true

$Output = “The URL ” + $url.TextToDisplay + ” has been updated”

Write-Output $Output

}

} #end foreach

}

if ($needToSave -eq $true)

{

$document.save()

$document.close([Ref]$donotsave)

$output = $item.name + ” — successfully saved —“

Write-Output $output

#get the status again

$modeinfo = $Item.ModerationInformation

$status = $Item.ModerationInformation.Status

$output = $item.name + ” has been saved”

Write-Output $output

if ($NeedToPublish -eq $true)

{

$output = $item.name + ” is being Published”

Write-Output $output

$Item.File.Publish(“Published by System”)

$Item.File.Approve(“Approved by System”)

$Item.File.Update();

$output = $item.name + ” processing completed”

Write-Output $output

}

}

else

{

$document.close([Ref]$donotsave)

$output = $item.name + ” — No changes required —“

Write-Output $output

}

}

$application.quit()

$SPWeb.Dispose()

Hope you find this useful.

Leave a comment