Find and Replace in Excel with PowerShell - excel

I have a column with computer names however the names are formatted like this domain\computer name. Usually in Excel I can use find/replace and search for *\ and replace with blank leaving just the computer name. I have a powershell script that finds *\ however it replaces the whole cell with nothing. It's like its searching for any cell that contains *\ and replacing that instead of just leaving the computer name.
$file = "C:\reports\report.xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$Workbok = $Excel.workbooks.open($file)
$Worksheets = $Workbook.worksheets
$Worksheet = $Workbook.Worksheets.Item(1)
$Worksheet = $Workbok.Worksheets.Item(1)
$SearchString = "*\"
$Range = $Worksheet.Range("A1").EntireColumn
$Search = $Range.find($SearchString)
if($search -ne $null){
$FirstAddress = $Search.Address
do{
$Search.value() = ""
$search = $Range.FindNext($search)
}while ($search -ne $null -and $search.Address -ne $FirstAddress)

In your Do-While loop you are taking the value of the search and setting it to an empty string. $Search.value() = "". If you take that and change it something like this $search.Value() = $Search.value() -replace "^.*\\",'' it should work. I used -replace with some regex to replace everything from the backslash until the beginning of the line.
Cleaned up your code a bit because it seems you had some misspelled variables
$file = "C:\reports\report.xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$Workbook = $Excel.workbooks.open($file)
$Worksheet = $Workbook.Worksheets.Item(1)
$SearchString = "*\"
$Range = $Worksheet.Range("A1").EntireColumn
$Search = $Range.find($SearchString)
if ($search -ne $null) {
$FirstAddress = $Search.Address
do {
$search.Value() = $Search.value() -Replace "^.*\\", ''
$search = $Range.FindNext($search)
} while ($search -ne $null -and $search.Address -ne $FirstAddress)
}

Related

Powershell Excel Code changing table info

Hello all I need a little help with my code not sure what I am doing wrong or why its not working. Slowly learning PS to automate some of my work.
I have this code, What I am trying to do it have it clear all filters of all the excel files in a folder. Then have it search some of the columns in a table and replace all the blanks with N\A.
So far I have it working to clear all filters and it replaces blanks with N/A but it does not stop in the table it just continues.
$Path = "C:\Users\Username\Downloads\Workstations (21)\Workstations\"
$files = Get-ChildItem "C:\Users\Username\Downloads\Workstations (21)\Workstations" -Filter *.xlsx
ForEach ($item in $files) {
$Excel = New-Object -ComObject Excel.Application
$Excel.visible = $true
$Workbook = $Excel.workbooks.open($Path + [System.IO.Path]::GetFileName("$item"))
$Worksheets = $Workbooks.worksheets
$Worksheet = $Workbook.Worksheets.Item(2)
$worksheet.AutoFilter.ShowAllData()
$SearchString = "" #String to Find
$Range = $Worksheet.ListObjects("Table1").ListColumns("Column3").Range # Column or Columns want to search single "R4" multi "R4:Y4"
$Search = $Range.find($SearchString) }
$Search = $Range.find($SearchString)
if ($search -ne $null) {
$FirstAddress = $search.Address
do {
$Search.value() = "N/A" # Replacement Value
$search = $Range.FindNext($search)
} while ( $search -ne $null -and $search.Address -ne $FirstAddress)
}
$WorkBook.Save()
$WorkBook.Close()
[void]$excel.quit()

Replace a string of text in multiple Excel files using a PowerShell script

I have multiple Excel files that have similar data, and I want a PowerShell script that searches and replaces a string of text in all Excel files in a specified folder.
So far, I have the following PowerShell script that opens all my Excel files and attempts to replace matching strings in the second Worksheet, but the expected changes are not made:
$Path = "C:\Users\mabrant\Downloads\Workstations (21)\Workstations\"
$files = Get-ChildItem "C:\Users\mabrant\Downloads\Workstations (21)\Workstations" -Filter *.xlsx
ForEach ($item in $files) {
$Excel = New-Object -ComObject Excel.Application
$Excel.visible = $true
$Workbook = $Excel.workbooks.open($Path + [System.IO.Path]::GetFileName("$item"))
$Worksheets = $Workbooks.worksheets
$Worksheet = $Workbook.Worksheets.Item(2)
$SearchString = "NEW" #String to Find
$Range = $Worksheet.Range("S4:Y4").EntireColumn #Range of Cells to look at
$Search = $Range.find($SearchString) }
$Search = $Range.find($SearchString)
if ($search -ne $null) {
$FirstAddress = $search.Address
do {
$Search.value() = "Installed" # Replacement Value
$search = $Range.FindNext($search)
} while ( $search -ne $null -and $search.Address -ne $FirstAddress)
}
$WorkBook.Save()
$WorkBook.Close()
[void]$excel.quit() `
Seems like you were really close to having a working script. I believe the main problem is that your ForEach block should include everything except the $excel.quit() so that you save and close each workbook as you go.
I reformatted your code to make it easier to see the entire ForEach block, I removed the duplicate $Search = $Range.find($SearchString) statement, and I set some Excel.Application properties to $false to make it work better.
Here is the updated code:
$Path = "C:\Users\mabrant\Downloads\Workstations (21)\Workstations\"
$files = Get-ChildItem $Path -Filter *.xlsx
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Excel.EnableEvents = $false
$Excel.DisplayAlerts = $false
ForEach ($item in $files) {
$Workbook = $Excel.Workbooks.Open($Path + [System.IO.Path]::GetFileName("$item"))
$Worksheet = $Workbook.Worksheets.Item(2)
$SearchString = "NEW" #String to Find
$Range = $Worksheet.Range("S4:Y4").EntireColumn #Range of Cells to look at
$Search = $Range.find($SearchString)
if ($Search -ne $null) {
$FirstAddress = $Search.Address
do {
$Search.Value() = "Installed" # Replacement Value
$Search = $Range.FindNext($Search)
} while ( $Search -ne $null -and $Search.Address -ne $FirstAddress)
}
$WorkBook.Save()
$WorkBook.Close()
}
$Excel.Quit()

How do I set the path correctly so that my code works for subfolders?

I have a code that allows me to search and replace in multiple Excel files within a folder and its subfolders.
However, this does not work properly yet, because I think that the following line contains an error:
$Workbook = $Excel.workbooks.open($Path + [System.IO.Path]::GetFileName("$item"))
All Excel files located directly in the main "test" folder are opened and saved correctly. However, the Excel files in the subfolders are not opened and saved.
This is the code:
$Path = "G:\test"
$files = Get-ChildItem -Path G:\test -Filter *.xlsx -Recurse -ErrorAction SilentlyContinue -Force
ForEach ($item in $files) {
$Excel = New-Object -ComObject Excel.Application
$Excel.visible = $false
$Workbook = $Excel.workbooks.open($Path + [System.IO.Path]::GetFileName("$item"))
$Worksheets = $Workbooks.worksheets
$Worksheet = $Workbook.Worksheets.Item(1)
$SearchString = "Test" #String to Find
$Range = $Worksheet.Range("A1:DZ100000").EntireColumn #Range of Cells to look at
$Search = $Range.find($SearchString)
if ($search -ne $null) {
$FirstAddress = $search.Address
do {
$Search.value() = $Search.value().Replace($SearchString, "Test2") #String to Update
$search = $Range.FindNext($search)
} while ( $search -ne $null -and $search.Address -ne $FirstAddress)
}
$WorkBook.Save()
$WorkBook.Close()
[void]$excel.quit()
}
I hope someone can help me.

Powershell loop for excel replace

I have found a bit of code here on stack overflow, and added a few bits. It works like a charm with the current settings... On Sheet1 in the columns from A to D.
I would like it to run on all the sheets in the workbook. But I cant fold my brain around the a solotion that works.
This is my code that works on Sheet1:
$replacecount = 0
$file = "H:\test4.xlsx"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Workbook = $Excel.workbooks.open($file)
$SearchString = "2019-AUG"
$replacestring = "2020-MAY"
$Worksheet = $Workbook.Worksheets.Item(1)
$Range = $Worksheet.Range("A1:D1").EntireColumn
write-output $worksheet.index
$Search = $Range.find($SearchString)
if ($search -ne $null) {
$FirstAddress = $Search.Address
do {
$search.Value() = $Search.value() -Replace $SearchString, $replacestring
$search = $Range.FindNext($search)
$replacecount++
} while ($search -ne $null -and $search.Address -ne $FirstAddress)
}
Write-output "status Close"
Write-output $replacecount
$WorkBook.Save()
$WorkBook.Close()
I'm thinking that I should be using a FOREACH (sheet in worksheet) but when I try to set the range inside the loop I get an error
Consider looping through Excel's Sheets.Count property:
$num = $Workbook.Sheets.Count()
For ($i = 1; $i -le $num; $i++) {
write-host $Workbook.Worksheets.Item($i).Name
$Worksheet = $Workbook.Worksheets.Item($i)
$Range = $Worksheet.Range("A1:D1").EntireColumn
write-output $worksheet.index
$Search = $Range.find($SearchString)
if ($search -ne $null) {
$FirstAddress = $Search.Address
do {
$search.Value() = $Search.value() -Replace $SearchString, $replacestring
$search = $Range.FindNext($search)
$replacecount++
} while ($search -ne $null -and $search.Address -ne $FirstAddress)
}
}
Alternatively, directly loop on worksheets and not via sheet index with Item as #Theo comments:
foreach ($Worksheet in $Workbook.Worksheets){
write-host $Worksheet.Name
# $Worksheet = $Workbook.Worksheets.Item($i) REMOVE THIS ASSIGNMENT
...
}

excel/powershell - find multiple cells that match a string not just the last one

Is it possible to find all cell references that contain a specific string in powershell? $Range.Find always just returns the last cell in the sheet, I want all the cells (or do I have to loop through each row? groan).
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$Workbook = $Excel.Workbooks.Open("C:\Users\some.xlsx")
$MySheet = $Excel.Worksheets.Item("somesheet")
$Range = $MySheet.UsedRange
$Targets = $Range.Find("Cheese")
Foreach ($Target in $Targets)
{
Write-Host $Target.AddressLocal()
}
I think you should use:
$Target = $Range.Find("Cheese")
$First = $Target
Do
{
Write-Host $Target.AddressLocal()
$Target = $Range.FindNext($Target)
}
While ($Target -ne $NULL -and $Target.AddressLocal() -ne $First.AddressLocal())

Resources