system._comobject doesnt not have a method named Cells in powershell while updating excel - excel

I have been trying this below code snippet to update a certain cell value in an excel file with 'xls' extension. This code snippet worked on my local system but its failing on the server giving the error as:
Method invocation failed system._comobject doesnt not have a method named Cells
function updateAprroval
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true)]
[ValidateNotNullOrEmpty()]
[Alias("change")]
[string]$changeNo,
[Parameter(Mandatory=$true)]
[Validateset('Email1','Email2','Email3')]
[Alias('email')]
[string]$mail,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[Alias('state')]
[string]$status,
[Parameter(Mandatory=$false)]
[Alias('start')]
[string]$sDate,
[Parameter(Mandatory=$false)]
[Alias('end')]
[string]$eDate
)
$searchFor = $changeNo
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$excel.ScreenUpdating = $false
$excel.DisplayAlerts = $false
$workbook = $excel.Workbooks.Open( $approvalFile ,$null, $false )
$ws = $workbook.WorkSheets.item(1)
#[void]$ws.Activate()
$searchRange = $ws.UsedRange
$searchResult = $searchRange.Find( $searchFor, [System.Type]::Missing, [System.Type]::Missing,
[Microsoft.Office.Interop.Excel.XlLookAt]::xlWhole,
[Microsoft.Office.Interop.Excel.XlSearchOrder]::xlByColumns,
[Microsoft.Office.Interop.Excel.XlSearchDirection]::xlNext )
if($mail -eq 'Email1')
{
$column = 3
}
elseif($mail -eq 'Email2')
{
$column = 4
}
else
{
$column = 5
}
if($searchResult)
{
$row = $searchResult.Row
$col = $searchResult.Column
$ws.Cells( $row, $column ).Value = $status
if($sDate -and $eDate)
{
$ws.Cells( $row, 6 ).Value = ([datetime]$sDate)
$ws.Cells( $row, 7 ).Value = ([datetime]$eDate)
}
#$searchResult = $searchRange.FindNext( $searchResult )
#if( $searchResult -and $searchResult.Row -le $row ) {
#break
#}
}
$workbook.Save()
$workbook.Close()
$excel.Quit()
#[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
}
#updateAprroval -changeNo 'CHG0158032' -mail Email1 -status 'new dates' -start '2021-02-12 15:30:00' -end '2021-04-12 15:30:00'
In my local desktop, the powershell version is 5, whereas on server it is version 4.
The excel version in my desktop is 2016 and on server it is 2013
Please help me resolve this issue.

The code worked for me after replacing this line in the code:
$ws.Cells( $row, $column ).Value = "assign something"
with
$ws.item( $row, $column ) = "assign something"
May be its because of the difference in versions.

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()

PowerShell - Open Excel and Unlock Certain Cells Based On Value

I have a report that I am running via SSRS to brings down some data that I need people to give comments on. I am attempting to write a PowerShell script that will open the file and unprotect certain cells based on their value.
This is what the report looks like:
The default for SSRS is that all cells are automatically protected. However, I would like to unprotect all the cells in column A (the column with the yellow text boxes) that do not have the value of "Manager Comments".
I am not really sure how to go about this. I have this so far for my script:
Param(
[string] $FolderPath,
[string] $FileName
)
Write-Output $FolderPath
Write-Output $FileName
$Files = Dir $FolderPath -Recurse | ? {$_.Name -eq $FileName} | Select -ExpandProperty FullName
$excl=New-Object -ComObject "Excel.Application"
foreach ($file in $Files)
{
$wrkb=$excl.Workbooks.Open($file, 0, $false)
$wrkb.Worksheets("Comments").Range("A1:A100").Locked = $False
$wrkb.Save()
$wrkb.Close()
}
$excl.Quit()
But this will just unprotect all of column A. Does anyone know how to have it look at the values and only unprotect those blank values? Bonus points if it can just look for certain colors (the yellow).
And yes, I know that this is a terrible way of doing this...but I work with what I have.
A little progress update...I now can pull the value and cell color index in a loop, but I am not sure how to write the IF statement to lock the cell if the $Color value is equal to "36".
Param(
[string] $FolderPath = "C:\Root\Data\VisualCron\Development\",
[string] $FileName = "Combined Master Report.xlsx"
)
Write-Output $FolderPath
Write-Output $FileName
$Files = Dir $FolderPath -Recurse | ? {$_.Name -eq $FileName} | Select -ExpandProperty FullName
$SheetName = "Comments"
$Excel = New-Object -ComObject "Excel.Application"
foreach ($File in $Files)
{
$Workbook = $Excel.Workbooks.Open($File, 0, $False)
$Sheet = $Workbook.Worksheets.Item("Comments")
$MaxRow = ($Sheet.UsedRange.Rows).Count
$Row,$Column = 1,1
for ($i = 0; $i -le $MaxRow - 1; $i++)
{
$Color = $Sheet.Cells.Item($Row+$i,$Column).Interior.ColorIndex
$Value = $Sheet.Cells.Item($Row+$i,$Column).Text
Write-Host ("Color Value:" + $Color + " " + $i + " " + $Value)
}
#$Workbook.Worksheets("Comments").Range("A3:A50").Locked = $False
#$Workbook.Worksheets("Comments").Protect('Test',1,1,1,1,0,0,0,0,0,0,0,0,0,0,0)
$Workbook.Save()
$Workbook.Close()
}
$excl.Quit()
Another update:
I have gotten it to work, but it is a little strange. When I first go through my loop, the color index appears to be "36", but once I change one value, the yellow index changes to "5". I am not really sure why it does that, but I wrote this script, and hopefully, it is consistent.
Param(
[string] $FolderPath = "C:\Root\Data\VisualCron\Development\",
[string] $FileName = "Combined Master Report.xlsx"
)
Write-Output $FolderPath
Write-Output $FileName
$Files = Dir $FolderPath -Recurse | ? {$_.Name -eq $FileName} | Select -ExpandProperty FullName
$SheetName = "Comments"
$Excel = New-Object -ComObject "Excel.Application"
foreach ($File in $Files)
{
$Workbook = $Excel.Workbooks.Open($File, 0, $False)
$Sheet = $Workbook.Worksheets.Item("Comments")
$MaxRow = ($Sheet.UsedRange.Rows).Count
$Row,$Column = 1,1
for ($i = 1; $i -le $MaxRow - 1; $i++)
{
$Color = $Sheet.Cells.Item($Row+$i,$Column).Interior.ColorIndex
$Value = $Sheet.Cells.Item($Row+$i,$Column).Text
#Write-Output ($Color)
$Range = "A" + ($Row + $i) + ":A" + ($Row + $i)
if ($Color -eq 36 -or $Color -eq 5)
{
$Range = "A" + ($Row + $i) + ":A" + ($Row + $i)
$Workbook.Worksheets("Comments").Range($Range).Locked = $False
#Write-Host $Range
}
}
$Workbook.Worksheets("Comments").Protect('Test',1,1,1,1,0,0,0,0,0,0,0,0,0,0,0)
$Workbook.Save()
$Workbook.Close()
}
$Excel.Quit()
Does anyone have any ideas on why the color index would be changing?

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
...
}

Making a list of computers and their rdp settings

I'm trying to use Powershell to compile a simple excel spreadsheet that lists my computer's ping status's, RPD settings, and Hostnames.
I'm frustrated with the portion of the code that uses excel. I'm not really sure why, but when I run this code I'm getting an multiple errors for calling a method on a null value expression.
$ComputerList = Get-Content C:\Users\\Desktop\RDPSTATUS\ComputerList.txt
$excel_file_path = 'C:\Users\\Desktop\RDPSTATUS\RDPSTATUS.xlsx'
# instantiate EXCEL object
$Excel = New-Object -ComObject Excel.Application
$ExcelWorkBook = $Excel.Workbooks.Open($excel_file_path)
$ExcelWorkSheet = $Excel.Worksheets.item("sheet1")
$ExcelWorksheet.activate()
$row = 0
$col = 0
$ExcelWorkSheet.Cells.Item($row , $col) = "Device Name"
$ExcelWorkSheet.Cells.Item($row , $col++) = "RDP Status"
$ExcelWorkSheet.Cells.Item($row , $col+2) = "ping Status"
$row = 1
foreach ($computername in $ComputerList){
$ExcelWorkSheet.Cells.Item($row , $col) = $computername
$PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$computername'" | Select-Object StatusCode
If ($PingStatus.StatusCode -eq 0)
{
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computername )
$regKey= $reg.OpenSubKey("System\\CurrentControlSet\\Control\\Terminal Server" ,$true)
$Value = $regkey.GetValue("fDenyTSConnections")
$ExcelWorkSheet.Cells.Item($row , $col+2) = "PING"
}
else {
$ExcelWorkSheet.Cells.Item($row , $col+2) = "NO PING"
}
If ($Value -eq 1){
$ExcelWorkSheet.Cells.Item($row , $col++) = "RDP is Disabled"
}
If ($Value -eq 0){
$ExcelWorkSheet.Cells.Item($row , $col++) = "RDP is Enabled"
}
}
$ExcelWorkBook.Save()
$ExcelWorkBook.Close()
$Excel.Quit([System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel))
Stop-Process -Name EXCEL -Force
You've got a couple immediate issues that I can see:
$ExcelWorkSheet = $Excel.Worksheets.item("sheet1") should be $ExcelWorkbook.Worksheets.item("sheet1"). The worksheet is a property of the workbook, not of the Excel application.
$row and $col beginning values should be 1, not 0.
$ExcelWorksheet.activate() is not necessary.

Resources