问题
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