Import-Excel only data without header in string - PowerShell - powershell

I have installed Import-Excel Module for PowerShell by dfinke which has a great functionality but I'm facing some troubles with the headers.
I would like to insert only the text into a string array, but instead, it comes with the header even when -NoHeader is declared. According to the documentation it's not its function not insert the header in the variable but I'm looking for a way to do it. So far I came with a newbie solution of $xlsxArray | Format-Table -HideHeaders | Out-File C:\temp\info.txt and then remove the spaces with .Trim() so the file doesn't get written #{P1=ContentofTheCell}.
Is there a better way to accomplish it?
Thank you so far.

You didn't give enough detail about the desired output, but I'll try to give guidance.
Import-Excel will return objects. Normally the column headers become the property names on the objects. When you use -NoHeader, the property names are simply named P1, P2 etc... An object's properties must have names. If you want the data from those properties you may have to process differently. You can access the properties like any other object collection:
$ExcelData = Import-Excel "C:\Temp\Some.xlsx"
$ExcelData.PropertyName
The PropertyName would be the column header from the file. So let's say I had a colum named Balance in that file, then the example would something like:
$ExcelData = Import-Excel "C:\Temp\Some.xlsx"
$ExcelData.balance
Output:
7254.74
4268.16
3051.32
64.77
323.22
146.62
14798.83
Note: these are pretty simple examples. Obviously things can get more complex.

Related

Using Powershell and HTMLBody.Replace how do I replace values inside an existing table?

I have an existing email template file for Outlook with To, CC, Subject and Body prefilled.
I can replace the values I need on the subject just fine, however, when it comes to the HTMLBody part, it only replaces values outside the table; I've tested this by putting all 15 placeholders outside the table.
In Powershell, I defined an array with the items that will be replaced and another that reads the values from a JSON file, then I loop through both in order to replace the values on the HTMLBody.
This is the code in question:
$emailToreplaceValues=#(
"[DailyReportDate]",
"[DailyReportSuccess]",
"[DailyReportFailure]",
"[DailyReportFailureRate]"
)
$newValues=#(
$valuesJSON.DailyReport.Date,
$valuesJSON.DailyReport.Success,
$valuesJSON.DailyReport.Failure,
$dailyReportFailureRate
)
$reportEmail = $outlookObj.CreateItemFromTemplate("$emailTemplate")
$reportEmail.Subject = $reportEmail.Subject.Replace("[date]", $date)
for($i=0;$i -le $newValues.Count;$i++) {
$reportEmail.HTMLBody = $reportEmail.HTMLBody.Replace($emailToreplaceValues[$i], $newValues[$i])
}
There's more values but for the sake of brevity, I only included a few of the values, from my understanding, the issue is that some of those values are inside a HTML table cell but I don't know if I can access the table or cells directly.
Firstly, do not use MailItem.HTMLBody property as variable - it is expensive to set and read, and it might not be the same HTML you set as Outlook performs some massaging and validation. Introduce an explicit variable, set it to the value of HTMLBody, do all your string replacements in a loop using that variable, then set the MailItem.HTMLBody property once.
You can also try to output the value of that variable to make sure the old values to be replaced are really there and are not broken by HTML formatting or encoding.
For the sake of future reference, the only way I was able to fix this, was by grabbing the html code off the email that I based my email template off.
I organized it so that any tags I want replaced are in their own line without anything else other than the spaces for indentation, then defined it as a variable that goes through the replace cycle and gets assigned to the MailItem.HTMLBody property after the replace cycle.

Powershell - changing value of returned SQL data variable fails

In Powershell, I am doing a SQL query for a single row of data. Lets say $data for example.
The response from the query a System.Data.DataSet type. Within it, there is a tables property that has the data I need.
$data.Tables
ServerName : Server15
SamAccount : Admin-Server15
LastPWDReset : 1/15/2019 12:00:00 AM
LastPWDResetAttempt :
I don't intend to write this data back out of anything. Instead, I want to display it, and convert the empty "LastPWDResetAttemp" to "NONE" where it is blank.
I thought it would be done like this:
$data.Tables.lastPWDResetAttempt = "None"
but that gives me an error The property 'lastPWDResetAttempt' cannot be found on this object. Verify that the property exists and can be set.
I can't help but think I am missing some conversion from "Dataset" to "String".
I've tried to-string but in doing so, I ended up with just a string of data and not the headings. Nothing I could update, or easily use to build my eventual table.
My work around:
$webdata = "" | select ServerName,SamAccount,LastPWDReset,LastPWDResetAttempt
$webdata.ServerName = $data.tables.servername
$webdata.SamAccount = $data.tables.samaccount
$webdata.LastPWDReset = $data.tables.LastPWDReset
$webdata.LastPWDResetAttempt = $data.tables.LastPWDResetAttempt
$webdata.LastPWDResetAttempt = "Never"
works. I just can't believe there isn't an easier way, nor do I understand why I can view a list of the data, just to not then be able to set it.
I think it is because Tables is an array and does not have the property LastPWDResetAttempt.
You can try the following instead:
$data.Tables[0].Rows[0].LastPWDResetAttempt = "None"
Also I think your workaround, though it may contain more lines of code, is actually a better solution though.

using get-odbcdsn across all domain computers

So I need to create a report of what odbc-dsns are on computers.
The first hurdle I'm trying to do is get the csv to output correctly on MINE. Then I figure I'll just deploy a runonce group policy with the script set to append.
The problem is that get-odbcdns returns an object. That object has:
Name: the friendly name of the odbc
Attribute : {Description}
I just want to be able to formatlist with the VALUE of the {Description} value inside the Attribute property. I can't figure out how to do that.
Whenever I go | fl name, attribute
it returns 1sl-den-db01 and {description} I would like for it to actually parse out description from Attribute. No idea how. Thoughts?

Arguments passed byReference and/or mutable constant issue

Not sure how I can do a minimal working code example here, but I will at least try to explain what is going on.
I have a utility that processes some text files to extract data, and then provides that data back in various ways depend on commend line options and some data in an XML file. There is a variety of "Processes" I could look for in the data, and I can output the final data in one or more formats (txt, csv, xml), with potentially different "Processes" being output to different file types. And since I am processing potentially hundreds of txt files, I want to multi-three this. So I have created a function, and since the mix of processes to monitor and output types to emit is the same for every txt file, which I then want to compile into a single big data structure at the end, I have created that final data structure as a hash of hashes, but empty of data. Then I use
Set-Variable resultsContainer -option:constant -value:$results
to make a constant, which is empty of data, to hand off to the function. the idea being I can hand the function an empty container plus the path of a txt file, and it can fill the container and return it, where I can in theory use it to fill the mutable data container. So I do a foreach on the txt files, and pass what SHOULD be an empty container each time, like this.
$journalResults = Invoke-PxParseJournal -journal "$source\$journal" -container $resultsContainer
However, instead of staying empty, as I would expect for a constant, I am effectively passing all the previous journals' data to each successive iteration of the function. I proved this to myself by initializing a counter to 1 and then running this loop after the Invoke-PxParseJournal call.
foreach ($process in $resultsContainer.Keys) {
foreach ($output in $resultsContainer.$process.Keys) {
foreach ($item in $resultsContainer.$process.$output) {
Write-Host "$(Split-Path $journal -leaf) $process $output $item$('!' * $count)"
}
}
}
After the first Invoke the loop produces nothing, but from there everything is appended. So I see results like this
journal.0002.txt Open_Project csv Gordon,1/20/2017 12:08:43 AM,Open an existing project,.\RFO_Benchmark - previous.rvt,0:00:22.012!!
journal.0003.txt Open_Project csv Gordon,1/20/2017 12:08:43 AM,Open an existing project,.\RFO_Benchmark - previous.rvt,0:00:22.012!!!
journal.0004.txt Open_Project csv Gordon,1/20/2017 12:08:43 AM,Open an existing project,.\RFO_Benchmark - previous.rvt,0:00:22.012!!!!
Identical repeats each time. Even odder, if I rerun the script in the console I WILL get an error saying
Set-Variable : Cannot overwrite variable resultsContainer because it is read-only or constant.
But still the results are data being appended. Now, my first thought was that because I was using the same variable name in the function as in the root script I was dealing with some scoping problem, so I changed the name of the variable in the function and gave it an alias, like this.
[Alias('container')]$parseJournal
I then populate and return the $parseJournal variable.
No change in behavior. Which now has me wondering if I just don't understand how parameters are passed. I had thought it was ByVal, but this is acting like it is ByReference, so even with the name change I am in fact just adding to the same data structure in memory each time.
Is there something obvious here that I am missing? FWIW< I am in PS 2.0 at the moment. I don't have a Win10 VM I can spin up easily at the moment to test there.

Get binary data from registry key

I am trying to get the data from each registry entry into a variable in Powershell. I have a For statement that allows me to parse through the names, with another For statement under it that parses through the properties. Where I am stumped is how to get the actual binary value for the property? I don't see, or am overlooking something.
For the Names, I use Key[$i]. For the properties, I use $Key[$i].Property[$count]. How do I get the binary value for $Key[$i].Property[$count]? Thanks
You could simply use the GetValue() method.
$Key[$i].GetValue($Key[$i].Property[$count])
I usually use Get-ItemProperty to get registry values -
$key_path = 'HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Font Management'
(Get-ItemProperty -Path $key_path)."Active Languages"