Making a list of computers and their rdp settings - excel

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.

Related

Improve multithreading and primary issue excel keeps closing

Primary issue is does anyone know why excel keeps closing? It is random and I do not know how to fix this issue.
My only thougths is to push everything into an array and do one final dump into excel at the end. but hoping for a better option. Or an improvement on how I am coding to help resolve this.
Everything appears to work except for excel randomly closing while processing the printers.
I have this script in multi-threaded form and in single threaded form and i get the same results.
only difference is multi-thread I get more results into the excel file.
Secondary question #2:
i have been reading about a dotnet workspace multithreading option that should be much faster. I am experimenting with but no success yet. Can I get an example where 2 parameters/arguments are passed to each job, with the results returned?
https://adamtheautomator.com/powershell-multithreading/
$Runspace = [runspacefactory]::CreateRunspace()
$PowerShell = [powershell]::Create()
$PowerShell.Runspace = $Runspace
$Runspace.Open()
$PowerShell.AddScript({Start-Sleep 5})
$PowerShell.BeginInvoke()
Back to Primary Issue:
Here is my current Script:
[CmdletBinding()]
Param (
[Parameter(Mandatory=$true)]
[string[]]$PrintServers = #("Rictx-print-p01","Rictx-print-p02","Rictx-cprint-p1","MHOH-CPRINT-P1","MTHOH-PRINT-P03","CORTX-PRINT-P01","PENFL-PRINT-P01","cdc-print","CN110","DA110","ito100","MarOH-PRINT-P01","mthoh-print-p01","mthoh-print-p02","PO100","SV-OHBA-001","SV-OHBUR-01","SV-OHBUR-02","SV-OHDS-001","sv-ohne-001","SV-OHPA-001","sv-ohtm-001","TE110"),
[string]$SaveAsPath = "\\rictx-script-p2\log\PrintServerReport\PrintServerInfo.xlsx", #\\rictx-script-p2\LOG\PrintServer\RICTX-PRINT-P02
[bool]$CloseReportFile = $false,
[bool]$RemoveSpecialCharacters = $true,
$ConcurrentJobProcess = 50
)
. \\rictx-script-p2\Scripts\Class\Log_Class_v3.ps1
# . \\rictx-script-p2\Scripts\Class\PrinterDetailClass.ps1
. \\rictx-script-p2\Scripts\Module\test\test-applicationrunning.ps1
#Excel Line Increment
$script:intRow = 0
#Prepare where file is being saved
if ($SaveAsPath.Substring(0,2) -eq '\\')
{
$Script_OutputLocationsUNCorDrive = ("\\$((Split-Path -Path "$SaveAsPath" -Parent))").Substring(2, ("\\$((Split-Path -Path "$SaveAsPath" -Parent))").IndexOf(("\\$((Split-Path -Path "$SaveAsPath" -Parent))").Split("\")[5]) + (("\\$((Split-Path -Path "$SaveAsPath" -Parent))").Split("\")[5]).Length -2)
$Script_OutputLocationsFolderPath = ("\\$((Split-Path -Path "$SaveAsPath" -Parent))").Substring(("\\$((Split-Path -Path "$SaveAsPath" -Parent))").IndexOf(("\\$((Split-Path -Path "$SaveAsPath" -Parent))").Split("\")[5]) + (("\\$((Split-Path -Path "$SaveAsPath" -Parent))").Split("\")[5]).Length)
}
else
{
$Script_OutputLocationsUNCorDrive = Split-Path -Path "$SaveAsPath" -Qualifier
$Script_OutputLocationsFolderPath = "$(Split-Path -Path $SaveAsPath -NoQualifier)".Substring(0,"$(Split-Path -Path $SaveAsPath -NoQualifier)".Length - (Split-Path -Path "$SaveAsPath" -Leaf).Length -1)
}
$Script_Log = ([log_class]::new())
$Script_Log.UNCorDrive = $Script_OutputLocationsUNCorDrive
$Script_Log.Folders_From_Root_to_Folder_Contaning_the_Log = "$Script_OutputLocationsFolderPath"
$Script_Log.LogFileName = Split-Path -Path $SaveAsPath -Leaf
$Script_Log.AddDatetoFileName = $true
$Script_Log.Enabled = $True
#$Script_Log.LogWrite("$TSQL")
#rename the saved file into a unique file name
$SaveAsPathFinal = "$($Script_Log.LogFolderPath)$($Script_Log.LogFileName).xlsx"
$PrintersInfo_Scriptblock =
{
Param
(
#$TestOnlyPingableComputers = $true,
[String]$PrinterName, $PrintServer
)
#####################################################################################################################################################
# Get Printer Information #
#####################################################################################################################################################
. \\rictx-script-p2\Scripts\Class\PrinterDetailClass.ps1
Write-host $PrinterName
write-host $PrintServer
write-host "Gathering Information"
$PrinterInfo = [PrinterDetailClass]::new($PrinterName, $PrintServer)
$A=1
return $PrinterInfo
}
FUNCTION processCompletedJobs
{
#####################################################################################################################################################
# Send Printer Information to Excel #
#####################################################################################################################################################
[array] $data = #()
$jobs = Get-Job -State Completed
#$JobsProcessed =
foreach( $job in $jobs )
{
$PrinterInfo = Receive-Job $job -Wait -AutoRemoveJob
#If ($Printer.Name -notlike "Microsoft XPS*")
#{
#$PrinterInfo = [PrinterDetailClass]::new($Printer.Name,$PrintServer)
$Sheet.Cells.Item($intRow, 1) = $PrinterInfo.Server
$Sheet.Cells.Item($intRow, 2) = $PrinterInfo.Name
$Sheet.Cells.Item($intRow, 3) = $PrinterInfo.Location
$Sheet.Cells.Item($intRow, 4) = $PrinterInfo.Comment
$Sheet.Cells.Item($intRow, 5) = $PrinterInfo.IPAddress
$Sheet.Cells.Item($intRow, 6) = $PrinterInfo.MAC
$Sheet.Cells.Item($intRow, 7) = $PrinterInfo.PingbyIP
$Sheet.Cells.Item($intRow, 8) = $PrinterInfo.PingbyPrinterName
$Sheet.Cells.Item($intRow, 9) = $PrinterInfo.Shared
$Sheet.Cells.Item($intRow, 10) = $PrinterInfo.ShareName
$Sheet.Cells.Item($intRow, 11) = $PrinterInfo.PortName
$Sheet.Cells.Item($intRow, 12) = $PrinterInfo.SNMPEnabled
$Sheet.Cells.Item($intRow, 13) = $PrinterInfo.SNMPCommunityString
$Sheet.Cells.Item($intRow, 14) = $PrinterInfo.PortNumber
$Sheet.Cells.Item($intRow, 15) = $PrinterInfo.PrinterStatus
#$Sheet.Cells.Item($intRow, 16) = "Removed"
$Sheet.Cells.Item($intRow, 16) = $PrinterInfo.PrinterModel
$Sheet.Cells.Item($intRow, 17) = $PrinterInfo.DriverName
$Sheet.Cells.Item($intRow, 18) = $PrinterInfo.DriverVersion
$Sheet.Cells.Item($intRow, 19) = $PrinterInfo.Driver
$Sheet.Cells.Item($intRow, 20) = $PrinterInfo.PageTotalCount
$Sheet.Cells.Item($intRow, 21) = $PrinterInfo.PageColorCount
$Sheet.Cells.Item($intRow, 22) = $PrinterInfo.PageBlackCount
$Sheet.Cells.Item($intRow, 23) = $PrinterInfo.PageDuplexCount
$Sheet.Cells.Item($intRow, 24) = $PrinterInfo.PageTotalCountAlt
$Sheet.Cells.Item($intRow, 25) = $PrinterInfo.PageCopyBlackCount
$Sheet.Cells.Item($intRow, 26) = $PrinterInfo.PageCopyColorCount
$script:intRow ++ #move to the next in excel
}
}
# Create new Excel workbook
$Excel = New-Object -ComObject Excel.Application
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlOpenXMLWorkbook
$Excel.Visible = $True
$Excel = $Excel.Workbooks.Add()
$Sheet = $Excel.Worksheets.Item(1)
$Sheet.Name = "Printer Inventory"
#======================================================
$Sheet.Cells.Item(1,1) = "Print Server"
$Sheet.Cells.Item(1,2) = "Printer Name"
$Sheet.Cells.Item(1,3) = "Location"
$Sheet.Cells.Item(1,4) = "Comment"
$Sheet.Cells.Item(1,5) = "IP Address"
$Sheet.Cells.Item(1,6) = "MAC"
$Sheet.Cells.Item(1,7) = "Ping by IP"
$Sheet.Cells.Item(1,8) = "Ping by Printer Name"
$Sheet.Cells.Item(1,9) = "Shared"
$Sheet.Cells.Item(1,10) = "Share Name"
$Sheet.Cells.Item(1,11) = "Port Name"
$Sheet.Cells.Item(1,12) = "SNMP Enabled"
$Sheet.Cells.Item(1,13) = "SNMP Community String"
$Sheet.Cells.Item(1,14) = "Port Number"
$Sheet.Cells.Item(1,15) = "Printer Status"
#$Sheet.Cells.Item(1,16) = "Printer State - Removed"
$Sheet.Cells.Item(1,16) = "Printer Model"
$Sheet.Cells.Item(1,17) = "Driver Name"
$Sheet.Cells.Item(1,18) = "Driver Version"
$Sheet.Cells.Item(1,19) = "Driver"
$Sheet.Cells.Item(1,20) = "Page Total Count"
$Sheet.Cells.Item(1,21) = "Page Color Count"
$Sheet.Cells.Item(1,22) = "Page Black Count"
$Sheet.Cells.Item(1,23) = "Page Duplex Count"
$Sheet.Cells.Item(1,24) = "Page Total Count Alt"
$Sheet.Cells.Item(1,25) = "Page Copy Black Count"
$Sheet.Cells.Item(1,26) = "Page Copy Color Count"
#=======================================================
$script:intRow = 2
$WorkBook = $Sheet.UsedRange
$WorkBook.Interior.ColorIndex = 40
$WorkBook.Font.ColorIndex = 11
$WorkBook.Font.Bold = $True
$PrintServerCounter = 0
#=======================================================
ForEach ($PrintServer in $PrintServers)
{
#####################################################################################################################################################
# Print Servers #
#####################################################################################################################################################
$PrintServerCounter++
Write-Progress -Activity "Processing Print Server:" -Status "Querying $($PrintServer) PRINTSERVER: $PrintServerCounter of $($PrintServers.Count)" -PercentComplete (($PrintServerCounter/$PrintServers.Count) * 100)
Write-Verbose "$(Get-Date): Working on $PrintServer..."
#$Script_Log.LogWrite("$(Get-Date): Working on $PrintServer...")
$Printers = Get-WmiObject Win32_Printer -ComputerName $PrintServer
Write-Host $Printer.name -ForegroundColor Green
$PrinterCounter = 0
ForEach ($Printer in $Printers)
{
#####################################################################################################################################################
# Printers #
#####################################################################################################################################################
$PrinterCounter++
Write-Progress -Activity "Processing Print Server:" -Status "Querying $($Printer.Name) on $PrintServer PRINTER: $PrinterCounter of $($Printers.Count)" -PercentComplete (($PrinterCounter/$Printers.Count) * 100)
Write-Verbose "$(Get-Date): Working on $Printer..."
#$Script_Log.LogWrite("$(Get-Date): Working on $Printer...")
#Write-Host $Printer.name -ForegroundColor Green
$runningjobs = if ( ((get-job | ? { $_.State -eq "running" }) -ne $null) )
{
if ( ((get-job | ? { $_.State -eq "running" }).Count -ne $null) )
{
(get-job | ? { $_.State -eq "running" }).Count
}
else
{0}
}
else
{0}
$completedjobs = (get-job -State Completed).count
while ( ($runningjobs -gt $ConcurrentJobProcess) -or ($completedjobs -gt $ConcurrentJobProcess) )
{
#do nothing
processCompletedJobs
$Excel = $Excel.SaveAs("$SaveAsPathFinal”,1)
#$Excel.SaveAs ($SaveAsPathFinal, $xlFixedFormat, AccessMode:=xlExclusive,ConflictResolution:=Excel.XlSaveConflictResolution.xlLocalSessionChanges)
$completedjobs = (get-job -State Completed).count
$runningjobs = if ( ((get-job | ? { $_.State -eq "running" }) -ne $null) )
{
if ( ((get-job | ? { $_.State -eq "running" }).Count -ne $null) )
{
(get-job | ? { $_.State -eq "running" }).Count
}
else
{0}
}
else
{0}
}
if ($Printer.Name -notlike "Microsoft*")
{
Start-Job -ScriptBlock $PrintersInfo_Scriptblock -ArgumentList ($Printer.Name),$PrintServer -Name "$($PrintServer)_$($Printer.Name)"
get-job | FL
}
}
$WorkBook.EntireColumn.AutoFit() | Out-Null
}
#####################################################################################################################################################
# Completing Printer Information Gathering #
#####################################################################################################################################################
$runningjobs = if ( ((get-job | ? { $_.State -eq "running" }) -ne $null) )
{
if ( ((get-job | ? { $_.State -eq "running" }).Count -ne $null) )
{
(get-job | ? { $_.State -eq "running" }).Count
}
else
{0}
}
else
{0}
while ($runningjobs -gt 0)
{
write-progress -Activity "Completing Printer Information Gathering" `
-Status "Progress: $($runningjobs) to be COMPLETED" `
-PercentComplete (((get-job).count-$runningjobs)/(get-job).count*100)
processCompletedJobs
$Excel = $Excel.SaveAs("$SaveAsPathFinal”,1)
$runningjobs = if ( ((get-job | ? { $_.State -eq "running" }) -ne $null) )
{
if ( ((get-job | ? { $_.State -eq "running" }).Count -ne $null) )
{
(get-job | ? { $_.State -eq "running" }).Count
}
else
{0}
}
else
{0}
}
$intRow ++
$Sheet.Cells.Item($intRow,1) = "Printer inventory completed"
$Sheet.Cells.Item($intRow,1).Font.Bold = $True
$Sheet.Cells.Item($intRow,1).Interior.ColorIndex = 40
$Sheet.Cells.Item($intRow,2).Interior.ColorIndex = 40
Write-Verbose "$(Get-Date): Completed!"
$Excel = $Excel.SaveAs("$SaveAsPathFinal”,1)
$Excel = $Excel.Saved = $True
if ($CloseReportFile)
{
$Excel.Close()
}

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?

system._comobject doesnt not have a method named Cells in powershell while updating 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.

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 (.xls file) - 4 sheets not possible?

need your help again!
This Script doesn't work. It works for the first 3 Sheets, but doesn't work for the last one. If I switch the itemnumber (eg. 3->4 and 4->3) the new 3 works and the new 4 does not. Is this some sort of bug? Or am I missing some commandlet to increase the "maximum sheet number"?
$Path = "C:\test.xls"
#Excelvar:
$Row = [int] 2
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$Excel.DisplayAlerts = $false
#Sheets:
$ADUsers = "Active Directory Users"
$Groups = "Create Groups"
$UsertoGroup = "User to groups"
$DNS = "DNS"
#$Worksheet = $Workbook.Sheets.Add()
$checkxls = test-path -pathtype Any $Path
if ($checkxls -eq $false) {
$wb = $Excel.Workbooks.Add()
$ws1 = $wb.Worksheets.Item(1)
$ws1.Name = $ADUsers
$ws1.activate()
$ws2 = $wb.Worksheets.Item(2)
$ws2.Name = $Groups
$ws2.activate()
$ws3 = $wb.Worksheets.Item(3)
$ws3.Name = $UserToGroup
$ws3.activate()
$ws4 = $wb.Worksheets.Item(4)
$ws4.Name = $DNS
$ws4.activate()
$wb.SaveAs($Path)
$wb.Close()
$Excel.Quit()
Errorcode:
"Invalid Index. (Exception by HRESULT: 0x8002000B (DISP_E_BADINDEX))"
Thx for help in advance.
extra information:
using powershell 3.0
using excel 2010
I think it's because you're refering to a different workbook
this line
$wb = $Excel.Workbooks.Add()
implies you're working with a new workbook.
try adding
$wb.Worksheets.Add()
after the workbook is created, and see if that works.
$Path = "C:\test.xls"
#Excelvar:
$Row = [int] 2
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$Excel.DisplayAlerts = $false
#Sheets:
$ADUsers = "Active Directory Users"
$Groups = "Create Groups"
$UsertoGroup = "User to groups"
$DNS = "DNS"
#$Worksheet = $Workbook.Sheets.Add()
$checkxls = test-path -pathtype Any $Path
if ($checkxls -eq $false) {
$wb = $Excel.Workbooks.Add()
$wb.Worksheets.add()
$ws1 = $wb.Worksheets.Item(1)
$ws1.Name = $ADUsers
$ws1.activate()
$ws2 = $wb.Worksheets.Item(2)
$ws2.Name = $Groups
$ws2.activate()
$ws3 = $wb.Worksheets.Item(3)
$ws3.Name = $UserToGroup
$ws3.activate()
$ws4 = $wb.Worksheets.Item(4)
$ws4.Name = $DNS
$ws4.activate()
$wb.SaveAs($Path)
$wb.Close()
$Excel.Quit()
Tried adding Sheet4 on excel and it is code is reading Sheet4 just fine
#Declare the file path and sheet name
$file = "C:\Documents\Folder\ExcelFile.xlsx"
$sheetName = "Sheet1"
#Create an instance of Excel.Application and Open Excel file
$objExcel = New-Object -ComObject Excel.Application
$workbook = $objExcel.Workbooks.Open($file)
$sheetCount = $workbook.Worksheets.Count
$sheet = $workbook.Worksheets.Item($sheetName)
$sheet4 = $workbook.Worksheets.Item("Sheet4")
Write-Host $sheetCount #sheet count is 4
$objExcel.Visible=$false
#Count max row
$rowMax = ($sheet.UsedRange.Rows).count
#Declare the starting positions
$rowName,$colName = 1,1
$rowAge,$colAge = 1,2
$rowCity,$colCity = 1,3
#loop to get values and store it
for ($i=1; $i -le $rowMax-1; $i++)
{
$name = $sheet.Cells.Item($rowName+$i,$colName).text
$age = $sheet.Cells.Item($rowAge+$i,$colAge).text
$city = $sheet.Cells.Item($rowCity+$i,$colCity).text
Write-Host ("My Name is: "+$name)
Write-Host ("My Age is: "+$age)
Write-Host ("I live in: "+$city)
}
#used $rowMax from Sheet1, you can declare a separate for Sheet4
for ($i=1; $i -le $rowMax-1; $i++)
{
$name = $sheet4.Cells.Item($rowName+$i,$colName).text
$age = $sheet4.Cells.Item($rowAge+$i,$colAge).text
$city = $sheet4.Cells.Item($rowCity+$i,$colCity).text
Write-Host ("My Name is: "+$name)
Write-Host ("My Age is: "+$age)
Write-Host ("I live in: "+$city)
}
#close excel file
$objExcel.quit()
Pardon my example, just a noob script :)

Resources