PowerShell find next empty column in Excel - excel

I need a PowerShell snippet that searches for the next empty column in an Excel sheet.
Every help is appreciated.
I've tried this so far:
$Excel = New-Object -Com Excel.Application
$Excel.visible = $True
$WorkBook = $Excel.Workbooks.Open("C:\Users\Garry\Desktop\test.xlsx")
$Sheet = $Excel.WorkSheets.Item(1)
$xlLastCell = [Microsoft.Office.Interop.Excel.Constants]::xlLastColumn
$z=1
Do{$z, $z++}until ($Sheet.Column.Item(1, $xlLastCell).Value -eq "")
I tried to loop it so it checks every column if there is a value with the do and until statement, but I always get the error
"It is not possible to call a method for an expression that has the value NULL." The errorstatement refers to the Do until loop.

Change condition from "0" to "$null" and replace $xlLastCell with counter $z:
Add-Type -AssemblyName Microsoft.Office.Interop.Excel
$excel = New-Object -ComObject Excel.Application
$excel.visible = $true
$workBook = $excel.Workbooks.Open("C:\Users\Garry\Desktop\test.xlsx")
$workSheet = $excel.WorkSheets.Item(1)
# not needed $xlLastCell = [Microsoft.Office.Interop.Excel.Constants]::xlLastColumn
$z = 1
Do {
$z
}
until ( $workSheet.Cells.Item(1, $z++).Value2 -eq $null )

Related

Powershell - Filter an Excel File

I would like to add a filter for an Excel file within a PowerShell script.
So "if you find in column D the entry "Listener", make the whole row invisible, so filter it out, so that only rows are shown where no "Listener" occurs.
Can I implement this with PowerShell somehow? I tried but it didn't work.
i tried it with this :
$column = 4 # column D
$filename = "C:\Users\xxxxx\Desktop\Test.XLS"
$criteria = "Listener"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$workbook = $Excel.Workbooks.Open($filename)
$worksheet = $workbook.Worksheets.Item(1)
$usedrange = $worksheet.UsedRange
$usedrange.EntireColumn.AutoFilter()
$usedrange.AutoFilter($column, $criteria)
$worksheet.UsedRange.offset($column,4).EntireLine.Delete()
Thanks!
This should work for you:
$column = 4 # column D
$filename = "C:\Users\xxxxx\Desktop\Test.XLS"
$criteria = "Listener"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$workbook = $Excel.Workbooks.Open($filename)
$worksheet = $workbook.Worksheets.Item(1)
$worksheet.Activate()
# find the number of used rows in the table
$rowMax = $worksheet.UsedRange.Rows.Count
# hide rows that match the criteria
# go from bottom to top
# if your file does not have column headers, use $row -gt 0
for ($row = $rowMax; $row -gt 1; $row--) {
if ($worksheet.Cells.Item($row, $column).Value() -eq $criteria) {
$worksheet.Rows($row).Hidden = $true
}
}
# save and close the workbook
$workbook.Close($true)
# quit Excel and clean up the COM objects from memory
$Excel.Quit()
# IMPORTANT: clean-up used Com objects
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()
Edit
I may have misinterpreted your question and instead of hiding the rows that match the criteria like in the code above, all you need is to turn on an Autofilter on column 'D':
$column = 4 # column D
$filename = "C:\Users\xxxxx\Desktop\Test.XLS"
$criteria = "Listener"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $true
$workbook = $Excel.Workbooks.Open($filename)
$worksheet = $workbook.Worksheets.Item(1)
$worksheet.Activate()
# find the number of used rows in the table
$rowMax = $worksheet.UsedRange.Rows.Count
# add the autofilter to to column D
[void]$worksheet.Range("D$(1):D$($rowMax)").AutoFilter(1,"<>$criteria")
# save and close the workbook
$workbook.Close($true)
# quit Excel and clean up the COM objects from memory
$Excel.Quit()
# IMPORTANT: clean-up used Com objects
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($worksheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Compare two EXCEL files to delete duplicate data using Powershell

I have a excel sheet that has number of columns and rows i need to delete all columns except one and delete all rows except predefined one(have an other excel sheet with one column and data(in rows) that are need to be deleted.
I have done the first that is to delete all the columns except, but i was only able to do that with Column number and i want to do this with Header name i.e. "Product Name" as Column number may change with other sheets.
Also want to do the same with Rows so i can compare row data from my reference execl.xlsx file and delete the one that are same.
$file = "C:\TE.xlsx" # here goes the path and name of the excel file.
$ColumnsToKeep = 4 # Specify the column numbers to delete.
$excel = New-Object -comobject Excel.Application # Creating object of excel in powershell.
$excel.DisplayAlerts = $False
$excel.visible = $False
$workbook = $excel.Workbooks.Open($file)
$sheet = $workbook.Sheets.Item(1) # Referring to first sheet.
$maxColumns = $sheet.UsedRange.Columns.Count
$ColumnsToRemove = Compare-Object $ColumnsToKeep (1..$maxColumns) | Where-Object{$_.SideIndicator -eq "=>"} | Select-Object -ExpandProperty InputObject
0..($ColumnsToRemove.Count - 1) | %{$ColumnsToRemove[$_] = $ColumnsToRemove[$_] - $_}
$ColumnsToRemove | ForEach-Object{
[void]$sheet.Cells.Item(1,$_).EntireColumn.Delete()
}
$workbook.SaveAs("C:\data1.XLSX")
$workbook.Close($true)
$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
Remove-Variable excel
Provided all your columns have headers in the first row, you can use this:
$file = "C:\TE.xlsx"
$columnToKeep = 'product'
$excel = New-Object -ComObject Excel.Application
$excel.DisplayAlerts = $false
$excel.Visible = $false
$workbook = $excel.Workbooks.Open($file)
$sheet = $workbook.Worksheets.Item(1)
$maxColumns = $sheet.UsedRange.Columns.Count
# remove all columns except the one with header named $columnToKeep
for ($col = 1; $col -le $maxColumns; $col++) {
if ($sheet.Cells.Item(1, $col).Value() -ne $columnToKeep) {
[void]$sheet.Columns($col).EntireColumn.Delete()
}
}
$workbook.SaveAs("C:\data1.XLSX")
$workbook.Close($true)
$excel.Quit()
## clean-up used Com objects
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($sheet)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbook)
$null = [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
[System.GC]::Collect()
[System.GC]::WaitForPendingFinalizers()

Powershell with Excel

What I need to do is to extract the data in the excel row and output them into different rows on Excel. After that, I will need to use the extracted data and perform certain conditions on the extracted data.
This is my current script:
To open excel and apply the formulas
$excel = New-Object -ComObject excel.application
$filepath = 'D:\testexcel.xlsx'
$workbook = $excel.workbooks.open("$filepath")
$worksheet = $workbook.worksheets.item(1)
$excel.Visible = $true
$rows = $worksheet.range("A1").currentregion.rows.count
$worksheet.range("S1:S$rows").formula = $worksheet.range("S1").formula
Function to find the row, apply the formula and output it
function test123(){
param([string]$test123)
$sourcefile = "D:\testexcel.xlsx"
$sheetname = "abc"
$excel = new-object -comobject excel.application
$excel.Visible = $true
$excelworkbook = $excel.Workbooks.open($sourcefile, 2, $true)
$excelworksheet = $excelworkbook.worksheets.item($sheetname)
$row = 1
$column = 1
$found = $false
while(($excelworksheet.cells.item($row, $column).value() -ne $null) -and($found -eq $false)){
if(($excelworksheet.cells.item($row, $column).value()).toupper() -eq $test123.ToUpper()){
write-host $excelworksheet.cells.item($row, $column).value() $excelworksheet.cells.item($row, $column+1).value(),
$excelworksheet.cells.item($row, $column +2).value() $found = $true
}
$row += 1
}
#close workbook
$excelworkbook.close()
$excel.quit()
}
test123 -test123 "Test123"
Please guide me and tell me if this is the right way to do it... Thanks
Please have a look into the ImportExcel module by Douge Finke. This module has the capability to do what you need.
Get it from PowerShell gallery: Install-Module -Name ImportExcel
Github link: https://github.com/dfinke/ImportExcel
you can then do Get-Help Import-Excel -Examples which has pretty good examples.

How to return a cell range (e.g. A10:C20) from a named range in Excel using PowerShell

I need to know how to return a cell range (e.g. A10:C20) from a named range called "Items" in Excel using PowerShell. I would like to delete entries in the second column of "Items" (B10:B20). I tried using .RefersToLocal method to return the range but it doesn't return anything. I'm new to PowerShell. Thank you for your help.
$Path = "C:\file.xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Workbook = $Excel.Workbooks.Open($Path)
$page = 'Main'
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
$ws.Range("Items").RefersToLocal
you can use range directly and then use the column attribute of the range elements (2 for B column) to clear and save it, like this:
$Path = "i:\named.xls"
$Excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Workbook = $Excel.Workbooks.Open($Path)
$page = 'Main'
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
$namedarea = $ws.Range("items")
$namedarea | ?{$_.column -eq 2} | %{$_.clear()}
$excel.Save()

need some help getting powershell do delete cell content and inserting a formula

Here is the script as it sits. $of is set to the name of the file that gets downloaded with wget. I am getting exception from HRESULT: 0x0800A03EC which has something to do with the range portion and it seeing a 0 based range, but I am giving it 2 : # of rows.
How can I get PowerShell to clear the range and then insert the formula?
#open the downloaded worksheet
$Excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($of)
$page = 'Project Summary'
$ws = $Workbook.Worksheets | Where-Object {$_.Name -eq $page}
# Set variables for the worksheet cells, and for navigation
$cells = $ws.Cells
$row = 1
$col = 5
# Add the header to the worksheet
$headers = "Region"
$headers | foreach {
$cells.Item($row, $col) = $_
}
# Add the formula to each occupied row
$rows = $worksheet.UsedRange.Rows.Count
$ws.Range("E2:E" + $rows).Clear()
$ws.Range("E2:E" + $rows).Formula = "=SUM(E2:E5)"
$Excel.Visible = $true
$Excel.DisplayAlerts = $false
$Excel.ActiveWorkbook.SaveAs('W:\test.xlsx')
I also tried
$rows | foreach {
$ws.Cells("E" + $rows).Clear()
$ws.Cells("E" + $rows).Formula = "=SUM(E2:E5)"
}
That gives me a Value does not fall within the expected range error.
How can I get this to clear each cell in the range E2:E<lastRow> and then insert a formula?
I have gone back to the following after finding a way to escape the entire formula using #' ... '#; there was clearly an error in my escape sequence earlier, but the following is not performing exactly as expected either.
$ws.Range("E2:E$rows").Clear();
$ws.Range("E2:E$rows").Formula = $Formula1
This now populates the formula, but it comes in as text and not as a formula; I have to solve for this.
#open the downloaded worksheet
$Excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($of)
$page = 'Project Summary'
$ws = $Workbook.Worksheets | Where-Object {$_.Name -eq $page}
# Set variables for the worksheet cells, and for navigation
$cells = $ws.Cells
$row = 1
$col = 5
# Add the header to the worksheet
$headers = "Region"
#open the downloaded worksheet
$excel = New-Object -Com Excel.Application
$Workbook = $Excel.Workbooks.Open($of)
$page = 'Project Summary'
$ws = $Workbook.worksheets | where-object {$_.Name -eq $page}
$Formula1 = #"
=SUM(E2:E5)
"#
$cells=$ws.Cells
$row=1
$col=5
$range = $ws.UsedRange
$rows = $range.Rows.Count
$ws.Range("E2:E$rows").Clear();
$ws.Range("E2:E$rows").Formula = $Formula1
# Add the header to the worksheet
$headers = "Region"
$headers | foreach {
$cells.item($row, $col) = $_
}
$excel.visible = $true
$excel.DisplayAlerts = $False
$excel.ActiveWorkbook.SaveAs('W:\Test.xlsx')
$excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
Remove-Item $of
This is the outcome. Escaping may or may not have been the original issue, but the help here guided me to a better way to deal with it if it was the issue. I still never solved why the loop was giving the value error, but this works so I won't have to tackle that yet; that is the next script which this post will also help me with.

Resources