I'm trying to replace multiple strings in a word document using PowerShell, but only one string is replaced when running the code below:
#Includes
Add-Type -AssemblyName System.Windows.Forms
#Functions
#Function to find and replace in a word document
function FindAndReplace($objSelection, $findText,$replaceWith){
$matchCase = $true
$matchWholeWord = $true
$matchWildcards = $false
$matchSoundsLike = $false
$matchAllWordForms = $false
$forward = $true
$wrap = [Microsoft.Office.Interop.Word.WdFindWrap]::wdReplaceAll
$format = $false
$replace = [Microsoft.Office.Interop.Word.WdFindWrap]::wdFindContinue
$objSelection.Find.Execute($findText,$matchCase,$matchWholeWord,$matchWildcards,$matchSoundsLike,$matchAllWordForms,$forward,$wrap,$format,$replaceWith, $replace) > $null
}
$item1 = "Should"
$item2 = "this"
$item3 = "work"
$item4 = "?"
$fileName = "NewFile"
#Opens a file browsers to select a word document
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property #{
InitialDirectory = [Environment]::GetFolderPath('Desktop')
Filter = 'Documents (*.docx)|*.docx'
}
Write-Host "Select word template file"
$FileBrowser.ShowDialog()
$templateFile = $FileBrowser.FileName
$word = New-Object -comobject Word.Application
$word.Visible = $false
$template = $word.Documents.Open($templateFile)
$selection = $template.ActiveWindow.Selection
FindAndReplace $selection '#ITEM1#' $item1
FindAndReplace $selection '#ITEM2#' $item2
FindAndReplace $selection '#ITEM3#' $item3
FindAndReplace $selection '#ITEM4#' $item4
$fileName = $fileName
$template.SaveAs($fileName)
$word.Quit()
If I comment out FindAndReplace the first one that runs works, but subsequent calls do not.
For example running this as is results in:
Input Output
#ITEM1# Should
#ITEM2# #ITEM2#
#ITEM3# #ITEM3#
#ITEM4# #ITEM4#
I'm not sure what I'm missing, any help would be appreciated
As was suggested it appears that the cursor was not returning to the beginning of the document. I added the following code:
Set-Variable -Name wdGoToLine -Value 3 -Option Constant
Set-Variable -Name wdGoToAbsolute -Value 1 -Option Constant
To the beginning of my script and:
$objSelection.GoTo($wdGoToLine, $wdGoToAbsolute, 1) > $null
as the first line in my FindAndReplace function, and now it works as expected.
There may be a more elegant solution, but this works for me
Related
I hope someone can help me understand what I am doing wrong.
The script works, if I enter multiple computers or multiple lines, but if I only enter 1 line (1 value). Lets say: Computer 201... the result will be 1
I have disabled the PING feature for now until I can figure out why it does not work with 1 line.
I added the whole code so you can test it yourself.
Thank you
# Load required assemblies
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
# Drawing form and controls
$Harvester = New-Object System.Windows.Forms.Form
$Harvester.Text = "Ping Computers"
$Harvester.Size = New-Object System.Drawing.Size(490,300)
$Harvester.FormBorderStyle = "FixedDialog"
$Harvester.TopMost = $true
$Harvester.MaximizeBox = $false
$Harvester.MinimizeBox = $false
$Harvester.ControlBox = $true
$Harvester.StartPosition = "CenterScreen"
$Harvester.Font = "Segoe UI"
#======================== INPUTBOX - Computers ========================#
$label_message2 = New-Object System.Windows.Forms.Label
$label_message2.Location = New-Object System.Drawing.Size(20,10)
$label_message2.Size = New-Object System.Drawing.Size(100,15)
$label_message2.Text = "Computers"
$Harvester.Controls.Add($label_message2)
# Inputbox
$Inputbox = New-Object System.Windows.Forms.TextBox
$Inputbox.Multiline = $True;
$Inputbox.Location = New-Object System.Drawing.Size(20,30)
$Inputbox.Size = New-Object System.Drawing.Size(200,150)
$Inputbox.ScrollBars = "Vertical"
$Harvester.Controls.Add($Inputbox)
#======================== INPUTBOX - Completed ========================#
$label_message_success = New-Object System.Windows.Forms.Label
$label_message_success.Location = New-Object System.Drawing.Size(250,10)
$label_message_success.Size = New-Object System.Drawing.Size(100,15)
$label_message_success.Text = "Successful"
$Harvester.Controls.Add($label_message_success)
# Inputbox
$Inputbox_success = New-Object System.Windows.Forms.TextBox
$Inputbox_success.Multiline = $True;
$Inputbox_success.Location = New-Object System.Drawing.Size(250,30)
$Inputbox_success.Size = New-Object System.Drawing.Size(200,150)
$Inputbox_success.ScrollBars = "Vertical"
$Harvester.Controls.Add($Inputbox_success)
#======================== Ping ========================#
$button_Ping = New-Object System.Windows.Forms.Button
$button_Ping.Location = New-Object System.Drawing.Size(120,200)
$button_Ping.Size = New-Object System.Drawing.Size(80,32)
$button_Ping.TextAlign = "MiddleCenter"
$button_Ping.Text = "Ping"
$button_Ping.Add_Click({
If ($Inputbox.TextLength -eq 0){
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show('Please enter at 1 computer to perform this action')
Return
}
[collections.arraylist] $ref = #(($Inputbox.Text -split '\r?\n').Trim() -ne '')
if(-not $ref) { return } # if the textbox is empty, don't do anything
$i = 0
1..$ref.Count | ForEach-Object {
#if(Test-Connection $ref[$i] -Quiet) {
$Inputbox_success.Text += $ref[$i] + [environment]::NewLine
$ref.RemoveAt($i)
#}
$Inputbox.Text = $ref | Out-String
$Inputbox, $Inputbox_success | ForEach-Object Refresh
}
})
$Harvester.Controls.Add($button_Ping)
# show form
$Harvester.Add_Shown({$Harvester.Activate()})
[void] $Harvester.ShowDialog()
On a single object you get a value of 1 because of this line:
[collections.arraylist] $ref = #(($Inputbox.Text -split '\r?\n').Trim() -ne '')
More specifically because when a string is evaluated against -ne '' it will return $true or $false, but when you pass an array to that it will instead output all results where that evaluated as true. The way to fix this is to force it to be an array every time. That can be done like this:
[collections.arraylist] $ref = [string[]]($Inputbox.Text -split '\r?\n') -ne ''
That fixes that, but it still leaves other issues, or, at least one other issue I see. You set $i to 0, then loop through things starting at 1, but always reference $i, which will always evaluate to 0, and effectively manipulate item 0 in the $ref array for each thing you evaluate against. So if your If statement succeeds on 3 out of 6 things it will always move the first 3 things over, regardless of what succeeds. To resolve that I changed your code as little as I could, but ended up with this:
0..($ref.Count -1) | ForEach-Object {
# if(Test-Connection $ref[$i] -Quiet) {
if($ref[$_][-1]%2){
$Inputbox_success.Text += $ref[$_] + [environment]::NewLine
}
}
$Inputbox.Text = $ref |Where{$Inputbox_success.Text -notmatch ([regex]::Escape($_))}| Out-String
$Inputbox, $Inputbox_success | ForEach-Object Refresh
So rather than remove things from the array, I rather copy the successes to the $Inputbox_success box, and then rebuild $Inputbox based on the items that are not present in $Inputbox_success at the end. Now, I just set $Inputbox.text to be this:
$Inputbox.Text = #'
Computer201
Computer202
Computer203
Computer204
Computer206
Computer207
'#
And evaluated which name ended in an odd number, but you can comment out my If statement, and re-implement your own to make it actually ping things and go off that.
I want to decide which folder that I need to choose based on my data, then if I can't find it, it will show the GUI for waiting and do looping to check it. I try this code, I can find the folder, but when I can't find it once I want to show the GUI it returns some error.
This is how I checking the folder
function FIND {
Write-Host "call the function that can call the GUI.ps1 script"
$Path = "D:\Process"
Write-Host "Starting Mapping SSID and Finding Job"
$SSID_Unit = "111dddddfafafesa"
Try{
$Path_Job = (Get-Item (Get-ChildItem "$Path\*\SSID_LST" | Select-String -Pattern "$SSID_Unit").Path).Directory.FullName
$global:Result = [PSCustomObject]#{
Exists = $true
FileName = $Path_Job.FullName
Attempts = 1
}
Write-Host "Job'$($global:Result.FileName)' Exists. Found after $($global:Result.Attempts) attempts." -ForegroundColor Green
Write-Host "Continue to Assigned Job"
Pause
} Catch {
Write-Host "Waiting for the jobss"
& D:\X\Wait_GUI.ps1 -Path $Path_Job -MaxAttempts 20
Write-Host "Job not found after $($global:Result.Attempts) attempts." -ForegroundColor Red
}
}
FIND
This is the GUI
Param (
[string]$Path = '*.*',
[string]$MaxAttempts = 5
)
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
# set things up for the timer
$script:nAttempts = 0
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000 # 1 second
$timer.Add_Tick({
$global:Result = $null
$script:nAttempts++
$Path_Job = Get-Item -Path $Path
if ($Path_Job) {
$global:Result = [PSCustomObject]#{
Exists = $true
FileName = $Path_Job.FullName
Attempts = $script:nAttempts
}
$timer.Dispose()
$Form.Close()
}
elseif ($script:nAttempts -ge $MaxAttempts) {
$global:Result = [PSCustomObject]#{
Exists = $false
FileName = ''
Attempts = $script:nAttempts
}
$timer.Dispose()
$Form.Close()
}
})
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '617,418'
$Form.text = "AutoGM"
$Form.BackColor = "#8b572a"
$Form.TopMost = $false
$Form.WindowState = 'Maximized'
$Label1 = New-Object system.Windows.Forms.Label
$Label1.text = "UNDER AUTOMATION PROCESS"
$Label1.AutoSize = $true
$Label1.width = 25
$Label1.height = 10
$Label1.Anchor = 'top,right,bottom,left'
$Label1.ForeColor = "#ffffff"
$Label1.Anchor = "None"
$Label1.TextAlign = "MiddleCenter"
$Label2 = New-Object system.Windows.Forms.Label
$Label2.text = "Waiting for the job..."
$Label2.AutoSize = $true
$Label2.width = 25
$Label2.height = 10
$Label2.ForeColor = "#ffffff"
$Label2.Anchor = "None"
$Label2.TextAlign = "MiddleCenter"
$Form.controls.AddRange(#($Label1,$Label2))
[void]$Form.Show()
# Write-Host $Form.Height
# Write-Host $Form.Width
$Label1.location = New-Object System.Drawing.Point(($Form.Width*0.35), ($Form.Height*0.4))
$Label2.location = New-Object System.Drawing.Point(($form.Width*0.43), ($Form.Height*0.5))
$L_S = (($Form.Width/2) - ($Form.Height / 2)) / 15
$Label1.Font = "Microsoft Sans Serif, $L_S, style=Bold"
$Label2.Font = "Microsoft Sans Serif, $L_S, style=Bold"
$Form.controls.AddRange(#($Label1,$Label2))
# start the timer as soon as the dialog is visible
$Form.Add_Shown({ $timer.Start() })
$Form.Visible = $false
[void]$Form.ShowDialog()
# clean up when done
$Form.Dispose()
if not found, it return this
Waiting for the jobss
Job not found after 1 attempts.
and the GUI is not shown
Ok, first of all, you are using different tests for the file and/or directory in the code and in the GUI. Furthermore, you call the GUI.ps1 file with a path set to a $null value.
I would change your code to something like this:
$Path = "D:\Process\*\SSID_LST\*" # the path to look for files
$SSID_Unit = "111dddddfafafesa" # the Search pattern to look for inside the files
function Test-FileWithGui {
[CmdletBinding()]
param(
[Parameter(Mandatory = $true, Position = 0)]
[string]$Path,
[Parameter(Mandatory = $true, Position = 2)]
[string]$Pattern,
[int]$MaxAttempts = 5
)
Write-Host "Starting Mapping SSID and Finding Job"
# set up an 'empty' $global:Result object to return on failure
$global:Result = '' | Select-Object #{Name = 'Exists'; Expression = {$false}}, FileName, Directory, #{Name = 'Attempts'; Expression = {1}}
# test if the given path is valid. If not, exit the function
if (!(Test-Path -Path $Path -PathType Container)) {
Write-Warning "Path '$Path' does not exist."
return
}
# try and find the first file that contains your search pattern
$file = Select-String -Path $Path -Pattern $Pattern -SimpleMatch -ErrorAction SilentlyContinue | Select-Object -First 1
if ($file) {
$file = Get-Item -Path $file.Path
$global:Result = [PSCustomObject]#{
Exists = $true
FileName = $file.FullName
Directory = $file.DirectoryName
Attempts = 1
}
}
else {
& "D:\GUI.ps1" -Path $Path -Pattern $Pattern -MaxAttempts $MaxAttempts
}
}
# call the function that can call the GUI.ps1 script
Test-FileWithGui -Path $Path -Pattern $SSID_Unit -MaxAttempts 20
# show the $global:Result object with all properties
$global:Result | Format-List
# check the Global result object
if ($global:Result.Exists) {
Write-Host "File '$($global:Result.FileName)' Exists. Found after $($global:Result.Attempts) attempts." -ForegroundColor Green
}
else {
Write-Host "File not found after $($global:Result.Attempts) attempts." -ForegroundColor Red
}
Next the GUI file.
As you are now searching for a file that contains some text, you need a third parameter to call this named Pattern.
Inside the GUI file we perform the exact same test as we did in the code above, using the parameter $Pattern as search string:
Param (
[string]$Path,
[string]$Pattern,
[int]$MaxAttempts = 5
)
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
# set things up for the timer
$script:nAttempts = 0
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000 # 1 second
$timer.Add_Tick({
$global:Result = $null
$script:nAttempts++
# use the same test as you did outside of the GUI
# try and find the first file that contains your search pattern
$file = Select-String -Path $Path -Pattern $Pattern -SimpleMatch -ErrorAction SilentlyContinue | Select-Object -First 1
if ($file) {
$file = Get-Item -Path $file.Path
$global:Result = [PSCustomObject]#{
Exists = $true
FileName = $file.FullName
Directory = $file.DirectoryName
Attempts = $script:nAttempts
}
$timer.Dispose()
$Form.Close()
}
elseif ($script:nAttempts -ge $MaxAttempts) {
$global:Result = [PSCustomObject]#{
Exists = $false
FileName = $null
Directory = $null
Attempts = $script:nAttempts
}
$script:nAttempts = 0
$timer.Dispose()
$Form.Close()
}
})
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '617,418'
$Form.Text = "AutoGM"
$Form.BackColor = "#8b572a"
$Form.TopMost = $true
$Form.WindowState = 'Maximized'
# I have removed $Label2 because it is easier to use
# just one label here and Dock it to Fill.
$Label1 = New-Object system.Windows.Forms.Label
$Label1.Text = "UNDER AUTOMATION PROCESS`r`n`r`nWaiting for the job..."
$Label1.AutoSize = $false
$Label1.Dock = 'Fill'
$Label1.TextAlign = "MiddleCenter"
$Label1.ForeColor = "#ffffff"
$L_S = (($Form.Width/2) - ($Form.Height / 2)) / 10
$Label1.Font = "Microsoft Sans Serif, $L_S, style=Bold"
$Form.controls.Add($Label1)
# start the timer as soon as the dialog is visible
$Form.Add_Shown({ $timer.Start() })
[void]$Form.ShowDialog()
# clean up when done
$Form.Dispose()
The results during testing came out like below
If the file was found within the set MaxAttempts tries:
Starting Mapping SSID and Finding Job
Exists : True
FileName : D:\Process\test\SSID_LST\blah.txt
Directory : D:\Process\test\SSID_LST
Attempts : 7
File 'D:\Process\test\SSID_LST\blah.txt' Exists. Found after 7 attempts.
When the file was NOT found:
Starting Mapping SSID and Finding Job
Exists : False
FileName :
Directory :
Attempts : 20
File not found after 20 attempts.
If even the folder $Path was not found, the output is
Starting Mapping SSID and Finding Job
WARNING: Path 'D:\Process\*\SSID_LST\*' does not exist.
Exists : False
FileName :
Directory :
Attempts : 1
File not found after 1 attempts.
Hope that helps
i want to replace a string with an hyperlink
i try with something like this
Update:
$FindText = "[E-mail]"
$email ="asdadasd#asdada.com"
$a=$objSelection.Find.Execute($FindText)
$newaddress = $objSelection.Hyperlinks.Add($objSelection.Range,$email) )
but this insert the email at beginnig of file word don't replace the string "[E-mail]"
Add-Type -AssemblyName "Microsoft.Office.Interop.Word"
$wdunits = "Microsoft.Office.Interop.Word.wdunits" -as [type]
$objWord = New-Object -ComObject Word.Application
$objWord.Visible = $false
$findText = "[E-mail]"
$emailAddress = "someemail#example.com"
$mailTo = "mailto:"+$emailAddress
$objDoc = $objWord.Documents.Open("Path\to\input.docx")
$saveAs = "Path\to\output.docx")
$range = $objDoc.Content
$null = $range.movestart($wdunits::wdword,$range.start)
$objSelection = $objWord.Selection
$matchCase = $false
$matchWholeWord = $true
$matchWildcards = $false
$matchSoundsLike = $false
$matchAllWordForms = $false
$forward = $true
$wrap = 1
$format = $False
$wdReplaceNone = 0
$wdFindContinue = 1
$wdReplaceAll = 2
$wordFound = $range.find.execute($findText,$matchCase,$matchWholeWord,$matchWildCards,$matchSoundsLike,$matchAllWordForms,$forward,$wrap)
if($wordFound)
{
if ($range.style.namelocal -eq "normal")
{
$null = $objDoc.Hyperlinks.Add($range,$mailTo,$null,$null,$emailAddress)
}
}
$objDoc.SaveAs($saveAs)
$objDoc.Close()
$objWord.Quit()
Remove-Variable -Name objWord
[gc]::Collect()
[gc]::WaitForPendingFinalizers()
Kinda ugly, but this script will do what you need. It loads the .docx specified with $objDoc, finds all instances of $findText, and replaces it with a mailto link for $emailAddress and then saves the changes to $saveAs.
Most of this based on a "Hey, Scripting Guy" Article
Using PowerShell, I need to write a script which would remove all hidden text of a Word Document.
Here is what I have so far :
$WordDocument = Get-Item "C:\MyWordDocument.docx"
$word_app = New-Object -ComObject Word.Application
$word_app.Visible = $false
$document = $word_app.Documents.Open($WordDocument.FullName)
$objSelection = $word_app.Selection
$objSelection.Font.Hidden = $True
$FindText = "" # search on formatting only (according to MS doc)
$wdFindContinue = 1
$ReplaceAll = 2
$MatchCase = $False
$MatchWholeWord = $False
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$Wrap = $wdFindContinue
$Format = $True # ?
$ReplaceWith = ""
$a = $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord, `
$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,`
$Wrap,$Format,$ReplaceWith,$ReplaceAll)
$document.Save()
$document.Close()
$word_app.Quit()
It does not work, and I cannot figure out why.
Any idea ?
The mistake is where you set the search filter to find hidden text. Instead of $objSelection.Font.Hidden = $True (this actually hides the currently selected text) you need to set the property on the $objSelection.Find object:
$objSelection.Find.Font.Hidden = $True
I've managed to find& edit per one word file. With this code:
$objWord = New-Object -comobject Word.Application
$objWord.Visible = $false
$objDoc = $objWord.Documents.Open("C:\users\stefan\test\New Microsoft Word Document.docx")
$objSelection = $objWord.Selection
$FindText = "that"
$MatchCase = $False
$MatchWholeWord = $true
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$Wrap = $wdFindContinue
$Format = $False
$wdReplaceNone = 0
$ReplaceWith = "this"
$wdFindContinue = 1
$a = $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord, `
$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,`
$Wrap,$Format,$ReplaceWith)
$objDoc.Save()
$objWord.Quit()
But I want to do it for whole folder. I've tried to insert something like this:
$objWord = New-Object -comobject Word.Application
$objWord.Visible = $false
$list = Get-ChildItem "c:\users\stefan\test\*.*" -Include *.doc*
foreach($item in $list){
$objDoc = $objWord.Documents.Open($list.FullName,$true)
$objSelection = $objWord.Selection
$FindText = "Sara"
$MatchCase = $False
$MatchWholeWord = $true
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$Wrap = $wdFindContinue
$Format = $False
$wdReplaceNone = 0
$ReplaceWith = "AJMOO"
$wdFindContinue = 1
$a = $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord, `
$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,`
$Wrap,$Format,$ReplaceWith)
$objDoc.Save()
$objWord.Quit()
}
Also, it changes only one item that is found, but I want all items in the file.
Thanks.
Multiple Replacements
Also, it changes only one item that is found, but I want all items in the file
This is because you have not set the scope of the replacement to be all items. The is from the next argument you did not specify in your Execute method call. Set a variable called $wdReplaceAll and set it to 2. Then you adjust your call to add that variable.
$a = $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord, `
$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,`
$Wrap,$Format,$ReplaceWith,$wdReplaceAll)
That fixes that issue when run against one file.
Multiple Files
But I want to do it for whole folder
The partial issue with that is your are not properly querying the folder for files. -Include is finicky and work when partnered with -Recurse however you are treating it like a -Filter anyway so adjust as such.
$list = Get-ChildItem "c:\users\stefan\test\" -filter "*.doc*"
Next, when you are looping you are not using the current iteration but the whole collection when calling .open()
$objDoc = $objWord.Documents.Open($list.FullName,$true)
Should instead be
$objDoc = $objWord.Documents.Open($item.FullName,$true)
as per your loop definition.
Now you need to be sure you close each document before you quit the application. Right now you are quitting word inside the loop.
foreach($item in $list){
#.... Stuff and things happens here.
$objDoc.Save()
$objDoc.Close()
}
$objWord.Quit()
Variable declaration and calls
Right now you set $wrap to the value of the variable $wdFindContinue. When that is first called $wdFindContinue is null as it is not set to a few lines later in the code.
$Wrap = $wdFindContinue
#...
$wdFindContinue = 1
Switch the order of these lines or just set $wrap directly to 1. I am unsure of the implications of this being incorrect.
Thankfully to #Matt I've solved my code.
Here is a correct version which works:
$objWord = New-Object -comobject Word.Application
$objWord.Visible = $false
$list = Get-ChildItem "c:\users\stefan\test\*.*" -Include *.doc*
foreach($item in $list){
$objDoc = $objWord.Documents.Open($item.FullName,$true)
$objSelection = $objWord.Selection
$wdFindContinue = 1
$FindText = "Sara"
$MatchCase = $False
$MatchWholeWord = $true
$MatchWildcards = $False
$MatchSoundsLike = $False
$MatchAllWordForms = $False
$Forward = $True
$Wrap = $wdFindContinue
$Format = $False
$wdReplaceNone = 0
$ReplaceWith = "AJMOO"
$wdFindContinue = 1
$ReplaceAll = 2
$a = $objSelection.Find.Execute($FindText,$MatchCase,$MatchWholeWord, `
$MatchWildcards,$MatchSoundsLike,$MatchAllWordForms,$Forward,`
$Wrap,$Format,$ReplaceWith,$ReplaceAll)
$objDoc.Save()
$objDoc.Close()
}
$objWord.Quit()