Replacing all occurrences of a string in a Word file by an hyperlink

两盒软妹~` 提交于 2021-01-28 16:31:47

问题


I have to create a Powershell script that reads a Word file (.docx) and replaces strings by hyperlinks. So far, based on this script, I can replace all occurrences of a string by another string easily. With that script, I can look for a string and replace it by an hyperlink. However, only the first occurrence is replaced.

Here's my understanding of the problem so far :

The first script uses the ReplaceWith and Replace=wdReplaceAll parameters of the Execute function of the Find Interface. The issue is that ReplaceWith expects a String and not an Hyperlink object.

The second script doesn't specify those parameters so it only uses the Find.Execute() function to move the start of the Range object to the found string and then insert a link at that position.

Since I can't replace all occurrences at once, I'd try to iterate through all matches to insert links at their location. But Find.Execute() only returns a Boolean... Now I'm thinking of maybe redefining the range to exclude the found occurrence and looping until the end of the doc, but this feels complicated.

Let's say I've got a Word file with this text :

In other words, each of the articles linked here is an index to multiple lists on a topic. Some of the linked articles are themselves lists of lists of lists. This article is also a list of lists.

Here's a bare bone script that replace only the first occurrence of "lists" by a relative link. I'm trying to replace all occurrences of "lists" to the hyperlink $linkPath, but can't find how. Help ?

Add-Type -AssemblyName "Microsoft.Office.Interop.Word"
$wdunits = "Microsoft.Office.Interop.Word.wdunits" -as [type]
$objWord = New-Object -ComObject Word.Application  
$objWord.Visible = $false

# Text to find and replace by a link
$findText = "lists"
# Link to file
$linkPath = ".\Untitled.png"
# Source Word (2007+) file
$objDoc = $objWord.Documents.Open([FILE TO READ FROM])
# Resulting file
$saveAs = [FILE TO SAVE TO]
# Set Range to all document content
$range = $objDoc.Content
$range.movestart($wdunits::wdword,$range.start) | Out-Null

# Execute params
$matchCase = $false
$matchWholeWord = $true
$matchWildcards = $false
$matchSoundsLike = $false
$matchAllWordForms = $false
$forward = $true 
$wrap = 1
$format = $False
$wdReplaceNone = 0 
$wdFindContinue = 1
$wdReplaceAll = 2

# $wordFound is true is $findText is found in $range. 
# $range.find.execute modifies the start of the range 
$wordFound = $range.find.execute($findText,$matchCase,`
             $matchWholeWord,$matchWildCards,$matchSoundsLike,`
             $matchAllWordForms,$forward,$wrap)

if($wordFound){
        $objDoc.Hyperlinks.Add($range,$linkPath,$null,$null,$findText) | Out-Null
}
$objDoc.SaveAs($saveAs)
$objDoc.Close()
$objWord.Quit()
$rc = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($objWord)
[gc]::Collect()
[gc]::WaitForPendingFinalizers()

Reference

  • Find Interface
  • Find.Execute
  • Range Interface
  • Hyperlinks Object

回答1:


As with any dataset you have to loop to hit all items in the data set to take action on specific in the dataset. You are not doing this in your code. In MSWord, you need to walk the document. For example I am show code for deletes, but this just as well could be your replace effort.

Example: VBA for just delete any hyper link

Sub RemoveHyperlinksInDoc()
    ' You need to delete collection members starting from the end going backwards
    With ActiveDocument
        For i = .Hyperlinks.Count To 1 Step -1
            .Hyperlinks(i).Delete
        Next
    End With
End Sub

Example PowerShell for delete all hyperlinks

Param
(
    [string]$Document = $Word.Documents.Open((Read-Host -Prompt 'Enter the full path to the Word document'))
)

$Word = New-Object -ComObject Word.application
$Hyperlinks = @($Document.Hyperlinks)  
$hyperlinks | ForEach { $_.Delete() }
$document.save()
$document.Close()
$word.quit()

Example: PowerShell for delete only image hyperlinks

Param
(
    [string]$Document = $Word.Documents.Open((Read-Host -Prompt 'Enter the full path to the Word document'))
)

$Word = New-Object -ComObject Word.application
$Hyperlinks = @($Document.Hyperlinks) 
$Hyperlinks | ForEach {
                         If ($_.Shape) {$_.Delete()}
                         Else {$_.Name;Write-Warning -Message 'Hyperlink is not a graphic and will not be removed'}
                      }
$Document.save()
$Document.Close()
$Word.quit()


来源:https://stackoverflow.com/questions/53344154/replacing-all-occurrences-of-a-string-in-a-word-file-by-an-hyperlink

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!