Powershell: get column number from CSV file header - powershell

I need to get the column number from an imported CSV based on a particular column name ($_."Status"). Once I have the correct column number, I can assign it to a variable and use it in a foreach loop to write text to the corresponding cells. $wsSource.cells.item($tr,49) = "Added by xyz)" Note that the column position often varies from file to file.
I already have the index/row number via $tr = $source.IndexOf($row) ...but struggling with the col number.
Thanks in advance,
Jason
Incomplete code from much larger PS script that writes two different excel files in the one loop:
$source = Import-Csv $csvFile
$i = 2
foreach($row in $source.where{$_.Contacted -like "*Invalid"})
{
$tr = ($source.IndexOf($row)+2)
$wsTemp.cells.item($i,4) = $timeStamp
$wsTemp.cells.item($i,10) = $row."Last Name"
$wsSource.cells.item($tr,49) = "Added by xyz)"
$wsSource.cells.item($tr,49).Interior.ColorIndex =19
$i++
}
}
elseif ...

You need to create a Hashtable to map the Excel column names with their index:
# create a hash with Excel column header names and their indices
$colMax = $wsSource.UsedRange.Columns.Count
$xlHeaders = #{}
for ($col = 1; $col -le $colMax; $col++) {
$name = $wsSource.Cells.Item(1, $col).Value() # assuming the first row has the headers
$xlHeaders[$name] = $col
}
Now you can match the column from the Csv with the column index in Excel like
if (!$xlHeaders.ContainsKey('Status')) {
Write-Warning "Excel sheet does not have a column named 'Status'"
}
else {
$xlColumn = $xlHeaders['Status']
$wsSource.Cells.Item($tr, $xlColumn) = "Added by xyz)"
$wsSource.Cells.Item($tr, $xlColumn).Interior.ColorIndex = 19
}

Related

Want to combine data from multiple text files with some logic per line, then output to a csv file

Similar to what I would do with XLS VLOOKUP's, I want to use data from a first imported (text or csv) file, lookup additional data into another imported object, and append data from 2nd object to the available fields in 1st imported file.
Then write it all to a .CSV file.
I'm new to powershell, so any help is welcome.
I started already with this code
cls
#Date
$date = Get-Date -Format yyyyMMddHHmm #ss
#files
$ProductionORderFile = "C:\Mydir\prod-orders.txt"
$UOMFile = "C:\Mydir\uom.txt"
#file_Import
$ProductionOrders = get-content -Path $ProductionOrderFile
$UOMs = import-csv -Path $UOMFile -Delimiter '|' -header UOM_SKU, UOM_UOM, UOM_UOMT, UOM_Qty, UOM_StdUOM, UOM_StdUOMT, UOM_EAN, UOM_kg, UOM_kgT
#main_loop
foreach ($line in $ProductionOrders)
{
$PO_ProdOrder = $line.SubString(0,10)
$PO_ProdOrderSKU = $line.SubString(11,10)
$PO_ProdOrderCust = $line.SubString(21,8)
$UOM_Found = "false"
$DLUOMQTY = 0
foreach ($UOM in $UOMs)
{
If ($PO_ProdOrderSKU = $UOM.UOM_SKU -And $UOM_UOM = "KAR")
{
$UOM_Found = "found"
break
}
if ($UOM_FOUND <> "found")
If ($PO_ProdOrderSKU = $UOM.UOM_SKU -And $UOM_UOM = "LTP")
{
$UOM_Found = "found"
break
}
if ($UOM_FOUND <> "found")
If ($PO_ProdOrderSKU = $UOM.UOM_SKU -And $UOM_UOM = "DIS")
{
$UOM_Found = "found"
break
}
}
if ($UOM_FOUND = "found)
{
$DLUOMQTY = $UOM.UOM_qty
}
$SavePath = "C:\Other\Temp\2207\rapid-sap-uom2" + "_" + $date + ".csv"
So, after this step, I want to save my line with all data from 1st file (prod-orders), preferably by column, and then add some columns from 2nd file uom as per above logic .
How to proceed ?
many thanks in advance for guiding a new user.

PowerShell-How to get values from this JSON file

This is the partial data after removed the confidential information.
{
"WebhookName":"Azure-CustomAlert-Webhook",
"RequestBody":"{\"schemaId\":\"azureMonitorCommonAlertSchema\",\"data\":{\"essentials\":{\"alertId\":\"/subscriptions/XXXXXXXXX/providers/Microsoft.AlertsManagement/alerts/XXXXXXX\",\"alertRule\":\"Low Memory\",\"severity\":\"Sev3\",\"signalType\":\"Log\",\"monitorCondition\":\"Fired\",\"monitoringService\":\"Log Analytics\",\"alertTargetIDs\":[\"/subscriptions/XXXXX/resourcegroups/XXXX-RG/providers/microsoft.operationalinsights/workspaces/workspacename\"],\"configurationItems\":[\"USE2V5TMP9001\"],\"originAlertId\":\"XXXXX\",\"firedDateTime\":\"2022-03-09T17:49:41.4631455Z\",\"description\":\"Triggers an alert for a low memory condition\",\"essentialsVersion\":\"1.0\",\"alertContextVersion\":\"1.1\"},\"alertContext\":{\"SearchQuery\":\"Perf | where ( CounterName == \\\"% Used Memory\\\" or CounterName == \\\"% Committed Bytes In Use\\\" ) | where Computer contains (\\\"TMP\\\") | summarize AggregatedValue = avg(CounterValue) by Computer, bin(TimeGenerated, 5m)\",\"SearchIntervalStartTimeUtc\":\"2022-03-09T17:42:10Z\",\"SearchIntervalEndtimeUtc\":\"2022-03-09T17:47:10Z\",\"ResultCount\":1,\"SeverityDescription\":\"Informational\",\"WorkspaceId\":\"XXXXX\",\"SearchIntervalDurationMin\":\"5\",\"AffectedConfigurationItems\":[\"USE2V5TMP9001\"],\"AlertType\":\"Metric measurement\",\"IncludeSearchResults\":true,\"Dimensions\":[{\"Name\":\"Computer\",\"Value\":\"USE2V5TMP9001\"}],\"SearchIntervalInMinutes\":\"5\",\"SearchResults\":{\"tables\":[{\"name\":\"PrimaryResult\",\"columns\":[{\"name\":\"Computer\",\"type\":\"string\"},{\"name\":\"TimeGenerated\",\"type\":\"datetime\"},{\"name\":\"AggregatedValue\",\"type\":\"real\"}],\"rows\":[[\"USE2V5TMP9001\",\"2022-03-09T17:42:10Z\",38.267662048339851]]}],\"dataSources\":[{\"resourceId\":\"/subscriptions/XXXXX/resourcegroups/XXXX/providers/microsoft.operationalinsights/workspaces/XXXX\",\"region\":\"eastus2\",\"tables\":[\"Perf\"]}]},\"Threshold\":9,\"Operator\":\"Greater Than\",\"IncludedSearchResults\":\"True\"},\"customProperties\":null}}",
"RequestHeader":{
"Connection":"Keep-Alive",
"Expect":"100-continue",
"Host":"xxxx.webhook.eus2.azure-automation.net",
"User-Agent":"IcMBroadcaster/1.0",
"X-CorrelationContext":"RkkKACgAAAACAAAAEADvqM+sXFG+SYkp7Tcy2IZaAQAQAMflO8/GhoFLrHCgd8ILz2o=",
"x-ms-request-id":"8fdd10d2-4a36-43a5-8e65-4eb20f3b9865"
}
}
The above json i got it from the Azure Log Search alert and trying to customize it.
From the above json can i get the values if i refer the column section keys?.
Ex: If i mention computer then i should be able to get value USE2V5TMP9001 and AggregatedValue is 38.267662048339851.
Use the columns array to map the individual row values to the correct type and property name:
$json = #'
<json goes here>
'#
$data = $json |ConvertFrom-Json
$columnDefinitions = $data.columns
$rows = foreach($row in $data.rows){
# prepare dictionary to hold the individual column values
$properties = [ordered]#{}
for($i = 0; $i -lt $row.Length; $i++){
# extract value and column metadata
$value = $row[$i]
$name = $columnDefinitions[$i].name
$type = $columnDefinitions[$i].type
# make sure to translate any type names if necessary
# eg. translate `real` -> `decimal`
if($type -eq 'real'){ $type = 'decimal' }
# convert value to correct type and store in property dictionary
$properties[$name] = $value -as $type
}
# create new object based on the row values
[pscustomobject]$properties
}
$rows will now contain 1 or more objects with the expected values so you can now do:
$rows |ForEach-Object {
# this now resolves `USE2V5TMP9001`
$_.computer
}

How to find a column number in excel sheet with PowerShell

I have a working script that search rows in the specific column but I need to set the number of the column, So before I run the script I am writing =column() in a specific row in that column. I want to know how to get this number according to the columns name. This will give me the option to let the user choose on which column to work.
Open the sheet and search in a specific workbook:
$excel = New-Object -ComObject Excel.Application
$Excel.Visible = $false
$Excel.DisplayAlerts = $False # Disable comfirmation prompts
$workbook = $excel.Workbooks.Open($ExcelFile)
$worksheet = $workbook.Worksheets.Item("VIP List")
Search for a specific row color:
$columnNumber = #
$patches = for ($row = 1; $row -le $rowMax; $row++) {
$val = $worksheet.Cells.Item($row, $columnNumber).Interior.ColorIndex # 2 is column B
if ($val -eq $searchcolorForPatch) {
# output an object with both values from columns A and B
[PsCustomObject]#{Patch = $worksheet.Cells.Item($row, 1).Value2}
}
}
I want to display all the column names in the workbook with his number and let the user to choose.
It is possible?
You can get the names and belonging indices like this:
$colMax = $sheet.UsedRange.Columns.Count
# create a hash with column header names and their indices
$columns = [ordered]#{}
for ($col = 1; $col -le $colMax; $col++) {
$name = $sheet.Cells.Item(1, $col).Value() # assuming the first row has the headers
$columns[$name] = $col
}
You now have an ordered Hashtable of the column names and their indices
For instance:
$columns['FirstColumn'] # --> 1
$columns['SomeColumnInBetween'] # --> 12

PowerShell loop through a CSV column and change the values according to criteria from another CSV

I've been attempting to write a PowerShell script that loops through a CSV column and changes the old values to new values that are mapped to search criteria.
CSV1:
Column1 Column2
TEST ANT = Test Ant,
ALPHA = Alpha,
OMEGA = Omega,
CSV2:
001234-Alpha-Bravo,
TTTTTTTTTT,
DATA:TEST-(RANDOM DATA)ANT,
ere393,
OMEGA-333,
Basically
Import a CSV1 that contains search criteria in column1 mapped to approved values in column2.
Import a CSV2 that contains a column of raw data.
Loop through column1 of search criteria.
For each row in CSV1, I want to determine if that string exists in one or more rows (as a whole string, or as a substring) from the raw data column in CSV2.
If the string exists (whole or substring), then replace the cells raw data with the approved value.
If there is no match, then continue to the next row.
Export a CSV with the new approved values and values that were not changed.
I've searched and tried many of the examples on this site, and each one seems to address a part of the problem I'm trying to solve, but not completely. A hash table seems to be the closest to a solution, but the raw data can be dynamic and can't seem to match the key to any part of the string in the raw data.
One example I've tried
$s = Import-Csv C:\SearchCriteriaCSV.csv
$searchCrit = $($s.Name)
$Imported = Import-Csv 'C:\ImportCSV.csv'
$Output = foreach ($i in $Imported) {
foreach ($c in $searchCrit) {
if ($c.Name -like "*$i*") {
$i.Name = $c.Name
}
}
$i
}
$Output
$Output | Export-Csv 'C:\ExportCSV.csv' -NoTypeInformation
Another example tried:
$RawNameFormatName = #{
"ALPHA" = "Alpha";
"OMEGA" = "Omega"
}
$csv = Import-Csv C:\ImportCSV.csv;
foreach($row in $csv) {
$row.Name = $RawNameFormatName[$row.Name];
}
$csv | Export-Csv "C:\ExportCSV.csv" -NoTypeInformation;
Exported CSV:
Alpha
TTTTTTTTTT
Test Ant
ere393
Omega

Powershell Word Table single row error

I have the following function that I provide 3 arrays as variables
$columnHeaders = #('Ticket ID', 'Date Raised', 'Title', 'Status' )
$columnproperties = #('number', 'opened_at', 'short_description', 'state')
$contents
$contents has multiple rows of data matching the columns above, however sometimes may only have 1 row. When the $contents only has 1 row the below function errors out and doesnt print the data.
Using ISE I traced the issue to the $contents.count not showing a value, why is this? is there a way to get around it?
function TableOutput ($columnHeaders, $columnProperties, $contents){
# Number of columns
$columnCount = $columnHeaders.Count
# Create a new table
$docTable = $Word.ActiveDocument.Tables.Add($Word.Selection.Range,$contents.Count,$columnCount)
# Table style
$doctable.Style = "Adapt Table"
# Insert the column headers into the table
for ($col = 0; $col -lt $columnCount; $col++) {
$cell = $docTable.Cell(1,$col+1).Range
$cell.Font.Bold=$true
$cell.InsertAfter($columnHeaders[$col])
}
$doctable.Rows.Add() > Null
# Load the data into the table
$i = 1
$j = $contents.Count
for($row = 2; $row -lt ($contents.Count + 2); $row++){
if($row -gt 2){
}
for ($col = 1; $col -le $columnCount; $col++){
Write-Progress -Activity "Processing Table Information" -Status "Adding Row entry $i of $j" -PercentComplete (100*$i/$j)
$cell = $docTable.Cell($row,$col).Range
$cell.Font.Name="Calibri"
$cell.Font.Size="10"
$cell.Font.Bold=$FALSE
$cell.Text = $contents[$row-2].($columnProperties[$col-1])
}
$i++
}
$doctable.Columns.AutoFit()
}
any help is greatly appreciated.
Cast $content as an array of strings and see if that doesn't work better for you.
function TableOutput ($columnHeaders, $columnProperties, [string[]]$contents){
Edit: Sorry, my bad, you are passing objects with properties ad descripbed in $columnheaders, so you would need to cast it as an array of objects instead:
function TableOutput ($columnHeaders, $columnProperties, [object[]]$contents){
Tested on my end, it works fine with 1 object being passed to the function, as well as an array of two objects being passed to the function.