I'm trying to count the cell number of the first row (A1-D1) which is known as header and get that count as the counter.
As all the while find most of them using Usedrange to count the columns:
$headercolcount=($worksheet.UsedRange.Columns).count
But UsedRange will capture maximum count in the whole activesheet, which resulting not identical to the column count in first row if there is extra content data below the header.
I only wish to grab just the first row:
[]
Update:
For clearer view, here is an example.
As 1F & 1G there are no value present, so the answer should be 5 as 1A-1E as it contains data. So how should I grab the 5 correctly?
[]
Get-Process excel | Stop-Process -Force
# Specify the path to the Excel file and the WorkSheet Name
$FilePath = "C:\temp\A_A.xlsx"
$SheetName = "Blad1" # In english this is probably Sheet1
# Create an Object Excel.Application using Com interface
$objExcel = New-Object -ComObject Excel.Application
# Disable the 'visible' property so the document won't open in excel
$objExcel.Visible = $false
$objExcel.DisplayAlerts = $false
# Open Excel file and in $WorkBook
$WorkBook = $objExcel.Workbooks.Open($FilePath)
# Load WorkSheet 'Blad 1' in variable Worksheet
$WorkSheet = $WorkBook.sheets.item($SheetName)
$xlup = -4162
$lastRow = $WorkSheet.cells.Range("A1048576").End($xlup).row
# get the highest amount of columns
$colMax = ($WorkSheet.UsedRange.Columns).count
# initiatie a counter
$count = $null
# set the column you'd like to count
$row = 1
for ($i = 0; $i -le $colMax; $i++){
if($worksheet.rows.Item("$row").columns.Item($i+1).text){
$count++
}
}
$count
This should work. It takes the highest amount of columns. It then loops until it reaches that amount. During the loop it checks if the cell on that row is filled or not, if it is, it adds to the counter.
If you have millions of lines, this might not be the best way but this works for me.
I've testes it with an excel file:
With
$row = 1 this will give : 5
$row = 2 this will give : 6
$row = 3 this will give : 7
$row = 4 this will give : 8
# Specify the path to the Excel file and the WorkSheet Name
$FilePath = "C:\temp\A_A.xlsx"
$SheetName = "Blad1" # In english this is probably Sheet1
# Create an Object Excel.Application using Com interface
$objExcel = New-Object -ComObject Excel.Application
# Disable the 'visible' property so the document won't open in excel
$objExcel.Visible = $false
$objExcel.DisplayAlerts = $false
# Open Excel file and in $WorkBook
$WorkBook = $objExcel.Workbooks.Open($FilePath)
# Load WorkSheet 'Blad 1' in variable Worksheet
$WorkSheet = $WorkBook.sheets.item($SheetName)
$xlup = -4162
$lastRow = $WorkSheet.cells.Range("A1048576").End($xlup).row
$amountofcolumns = $worksheet.UsedRange.Rows(1).Columns.Count
#OUTPUT
write-host "Last Used row:" $lastRow
Write-host "Amount of columns" $amountofcolumns
#show all columnnames
for($i = 1 ; $i -le $amountofcolumns; $i++){
$worksheet.Cells.Item(1,$i).text
}
This will show you how many rows you have AND will show you all values in the first row , ergo your titles.
Related
I am working on xlsx file and i need to read values from column A and display the values in column B
For an example column A has 100 rows and some of them have a string. At column B (Also 100 rows) i have also values. I want to run in a loop a search for all the cells in column A, Store them and print the corresponding values in column B
I want to search for # and display 1,2,7 from B
I need an object that holds the values from A and object for B (For further actions)
The code below search in all the columns and display the values.
What i need is to read only from a specific column. and i need an object that holds the values from A and B
$data holds the data of column A.
I want to in a loop and search for data and then display the same data in the same row in column B?
$ExcelFile = "C:\Temp\SharedFolder\Test.xlsx"
$excel = New-Object -ComObject Excel.Application
$Excel.visible = $false
$Excel.DisplayAlerts = $False # Disable comfirmation prompts
$workbook = $excel.Workbooks.Open($ExcelFile)
$data = $workbook.Worksheets['Sheet1'].UsedRange.Rows.Columns[1].Value2
Doing this in Excel can be done, but takes a bit more work.
If this is your Excel file:
$ExcelFile = "D:\Test\Test.xlsx"
$searchValue = '#'
$excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Excel.DisplayAlerts = $False # Disable comfirmation prompts
$workbook = $excel.Workbooks.Open($ExcelFile)
$worksheet = $workbook.Worksheets.Item(1)
# get the number of rows in the sheet
$rowMax = $worksheet.UsedRange.Rows.Count
# loop through the rows to test if the value in column 1 equals whatever is in $searchValue
# and capture the results in variable $result
$result = for ($row = 1; $row -le $rowMax; $row++) {
$val = $worksheet.Cells.Item($row, 1).Value2
if ($val -eq $searchValue) {
# output an object with both values from columns A and B
[PsCustomObject]#{A = $val; B = $worksheet.Cells.Item($row, 2).Value2}
}
}
# when done, quit Excel and remove the used COM objects from memory (important)
$excel.Quit()
$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()
Now you can process the objects in $result. For demo just output:
$result
A B
- -
# 1
# 2
# 7
Of course, it would be far easier if you save your Excel file as CSV..
$searchValue = '#'
$result = Import-Csv -Path 'D:\Test\Test.csv' -UseCulture | Where-Object { $_.A -eq $searchValue }
$result
When exporting an Excel file to Csv, Excel won't always use the comma as delimiter character. That depends on your machine's local settings. This is the reason I added switch -UseCulture to the Import-Csv cmdlet which will make sure it uses the same delimiter character your locally installed Excel uses for its output.
I would like to search for a string in a column. If it finds that string, I would like the script to replace the string in another cell - same row, different column. So my columns are like this...
screenshot
I want to search for "Hours" or "Hrs" in column "Unit Type" and when it finds it, I want to change the "Job ID" in that same row to 3289. Here's what I got so far and nothing seems to happen. Any help would be greatly appreciated. Thanks!
$excelFile = "C:\do\BEFORE.xls"
$objExcel = New-Object -ComObject Excel.Application
$WorkBook = $objExcel.Workbooks.Open($excelFile)
$worksheet = $WorkBook.sheets.item("Sheet1")
$rowCount = $worksheet.usedrange.rows.count
Select-Object "Acct", "Customer_Name", "Invoice","Inv_Date","Cost_ID","Job_ID","Description","Hours", "Quantity", "Price", "Unit_Type", "Amount"
foreach ($row in $excelFile) {
if ($row.Unit_Type -eq "Hours") {
$row.Job_ID = "3289"
}
}
$WorkBook.Save()
$WorkBook.Close()
The Select-Object command is not doing anything as you're not providing it any data. Though that doesn't matter much since you're dealing with an excel com object. You'll need to specify which column you're checking and I find it's easiest to use a for loop. We will start on row 2 since the first row is the headers. Based on your example the Unit Type column is 6 and the Job ID column is 1. You also wanted to check for either hours or hrs so a regex match would be an appropriate approach.
$excelFile = "C:\do\BEFORE.xls"
$objExcel = New-Object -ComObject Excel.Application
$WorkBook = $objExcel.Workbooks.Open($excelFile)
$worksheet = $WorkBook.sheets.item("Sheet1")
$rowCount = $worksheet.usedrange.rows.count
$unittypecolumn = 6
$jobidcolumn = 1
for($i = 2; $i -le $rowCount; $i++)
{
if($worksheet.Cells($i,$unittypecolumn).Value2 -match "hours|hrs")
{
$worksheet.Cells($i,$jobidcolumn).Value2 = "3289"
}
}
$WorkBook.Save()
$WorkBook.Close()
I need to split and save an excel file based on the values of the first column via a powershell script. Here is how the excel file is build up (app 30.000 rows)
´´´Column1 # Column2 # Column3´´´
´´´AA # data # data # data´´´
´´´AA # data # data # data´´´
´´´AB # data # data # data´´´
´´´AC # data # data # data´´´
´´´AC # data # data # data´´´
The result should be multiple files with filenames AA.xlxs, AB.xlxs, AC.xlxs and of course the according rows data.
What I have so far is the following code:
$objexcel = New-Object -ComObject Excel.Application
$wb = $objexcel.WorkBooks.Open("C:\Test.xlsx")
$objexcel.Visible = $true
$objexcel.DisplayAlerts = $False
$ws = $wb.Worksheets.Item(1)
$doc = $ws.Range("A:A")
foreach ($doc in $docs) {
$newfile,$objexcel = $objexcel.where({$doc -eq $doc})
$newfile | Export-Excel "C:\$doc.xlxs"
}
It just opens the file, but nothing happens.
It would be great if some coder could have a look at the code or provide a working one.
Thanks in advance.
Following is a working code that will iterate through unique elements in column one and make a copy of it in a new spreadsheet and save it.
Function Create-Excel-Spreadsheet {
Param($NameOfSpreadsheet)
# open excel
$excel = New-Object -ComObject excel.application
$excel.visible = $true
# add a worksheet
$workbook = $excel.Workbooks.Add()
$xl_wksht= $workbook.Worksheets.Item(1)
$xl_wksht.Name = $NameOfSpreadsheet
return $workbook
}
$objexcel = New-Object -ComObject Excel.Application
$wb = $objexcel.WorkBooks.Open("C:\Temp\Test.xlsx") # Changing path for test.xlsx file.
$objexcel.Visible = $true
$objexcel.DisplayAlerts = $False
$ws = $wb.Worksheets.Item(1)
$usedRange = $ws.UsedRange
$usedRange.AutoFilter()
$totalRows = $usedRange.Rows.Count
$rangeForUnique = $usedRange.Offset(1, 0).Resize($UsedRange.Rows.Count-1)
[string[]]$UniqueListOfRowValues = $rangeForUnique.Columns.Item(1).Value2 | sort -Unique
for ($i = 0; $i -lt $UniqueListOfRowValues.Count; $i++) {
$newRange = $usedRange.AutoFilter(1, $UniqueListOfRowValues[$i])
$workbook = Create-Excel-Spreadsheet $UniqueListOfRowValues[$i]
$wksheet = $workbook.Worksheets.Item(1)
$range = $ws.UsedRange.Cells
$range.Copy()
$wksheet.Paste($wksheet.Range("A1"))
$workbook.SaveAs("C:\temp\" + $UniqueListOfRowValues[$i], $xlFixedFormat)
$workbook.Close()
}
Reason nothing is happening is because you are iterating over $docs which does not contain any elements. It is currently null.
When you make a reference to look up the data, you are using $objexcel, but thats your excel application.. not the worksheet that you want to iterate over. Use $as for accessing the worksheet.
You need to iterate over Cells of your $ws and take the data when cells.Item(x, 0) and create a new file based on that with values in other two columns.
Link to example on SO -> Create and Update excel file
I am new to Powershell and I have an excel sheet that contains a list of subnets in column E for different store numbers 1 - 2500, store numbers are held in column B.
I want to read the store number from user and output the subnet from COLUMN E to a variable.
This is what I have so far..
$FilePath = "C:\temp\IP.xlsx"
$SheetName = "STORE SUBNET MASK"
$Excel = New-Object -ComObject Excel.Application
$WorkBook = $Excel.Workbooks.Open($FilePath)
$WorkSheet = $WorkBook.sheets.item($SheetName)
$num = Read-Host "Store number"
$Range = $Worksheet.Range("B1").EntireColumn
$Search = $Range.find($num)
$Search.value() = "2"
$WorkBook.Close()
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
What I am hoping to achieve is user inputs for example store 10 .. powershell checks column B for 10 and assigns what is in column E for that row to a variable.
Remove your code $Search.value() = "2" since it doesn't do anything.
Place Write-Host $search.offset(0,3).Text after $Search = $Range.find($num)
I am currently working on a script where I use several arrays to lookup inventory lists in Excel. After running a few tests I can get my script to read the contents of each cell (thanks to some research from this site!) but I can't use the contents of the cell in a variable. I receive an "Invalid Index" error when I try to switch to a worksheet using contents from one of the cells being read. I've also added an example of how the data is arranged.
#Test array
$array = "Dog", "Cat", "Mouse", "Tiger"
#Location of the Excel file to edit
$FileLoc = "Q:\Cutsheet.xlsx"
#Create Excel Com Object, and display it
$excel = new-object -com Excel.Application
$excel.visible = $true
#Open Workbook
$workbooks = $excel.workbooks.Open($FileLoc)
$worksheets = $workbooks.Worksheets
$worksheet = $worksheets.item("DATA")
#opens inventory workbook
$source = $excel.workbooks.Open("Q:\inventory.xlsx")
$sourceSheets = $source.Worksheets
<#
#This loop will search for match element of the array with a corresponding cell on an excel spreadsheet.
#That cell is grouped with several names of inventory worksheet names. The script will copy each inventory
#and append it to the existing cutsheet.
#>
foreach($element in $array) {
for ($i = 9; $i -lt 20; $i++) {
if ($worksheet.Cells.Item($i, 1).Text -eq $element) {
$j = 2
while ($worksheet.Cells.Item($i, $j).Text -ne "") {
Write-Host $worksheet.Cells.Item($i, $j).Value2
$name = $worksheet.Cells.Item($i, $j).Value2
$sourceSheet = $sourceSheets.Item($name)
$sourceSheet.Copy([system.type]::missing, $worksheets)
$j++
}
}
}
}
Example spreadsheet