Summary: Use Windows PowerShell to create custom objects prior to data export.
Microsoft Scripting Guy, Ed Wilson, is here. It is nice and cool this morning so I decided to walk over to the neighborhood coffee and tea shop to have a cup of tea. I can sit outside and enjoy the day. There is free wireless Internet, so I brought my Surface Pro 3 to check my email sent to scripter@microsoft.com, hang out on Facebook and Twitter, and generally do all the things I do in my day-to-day life as the Scripting Guy.
Today, I want to look at creating custom objects from Windows PowerShell as a way of outputting the data that I groomed nicely throughout the week. Because I planned on getting to this point in my script from the very outset, it will be pretty easy to put the pieces together to groom my data. I transformed the date, addresses, and names (see Use PowerShell to Normalize Names Before Data Import), so I expect there to be three sections for these. However, in the end, transforming the date was so easy (see Use PowerShell to Fix Date from CSV File) that I decided to code it directly in the portion of the script that creates the custom object.
Also, because I knew I would be putting everything together, I used the same sorts of variables. So the first portion of the script, which reads the CSV file and walks through the collection is the same:
$datain = import-csv C:\DataIn\DataDump.csv
Foreach ($d in $datain)
{
Now, I define a region for the name. To do this, I use the #region and #endregion tags. Now, I copy the script that I created earlier to normalize names, and I assign it to a region. This is shown here:
#region Name
If($d.name -match ',')
{
$name = (Get-Culture).textinfo.ToTitleCase($d.name).Split(',').trim()
$ln = $name[0]
$fn = $name[1]
}
ELSE {
$name = $d.Name.Split().trim()
$fn = $name[0]
$ln = $name[1]
}
#endregion
Now I add the region for the address. Once again, I copy the essential transforming code from the script I wrote earlier (see Use PowerShell to Fix Address Issues Prior to Export).
I also create an address region so it makes the script easier to read and troubleshoot. The command is shown here:
#region Address
$a = $d.address.split(',')
$str = $a[0] -replace '(Street|street)','ST'
$city = If($a[1] -match 'dwpt') {"Dewpoint"} ELSE {$a[1]}
$state = if($a[2] -match 'South Carolina') {"SC"} ELSE {$a[2]}
$zip = If($a[3].trim().Length -gt 5) {"Error for $a"} ELSE {$a[3]}
#endregion
To create and output the custom object, I use the [PSCustomObject] type accelerator, and I assign a hash table to the [PSCustomObject]. Each element in the hash table is in the form of "property name equals value."Almost every value I need is assigned via a variable. The exception is the date. I decided to do this as a single line of code, as shown here:
Date = [datetime]("{0}/{1}/{2}" -f $d.month, $d.day, $d.year)
I also call the ToUppermethod on the strings that are stored in the Street and City properties of the object:
Street = $str.ToUpper()
City = $city.ToUpper()
The last thing I do is clean up the state property. I trim it to remove any leading or trailing spaces. I choose only two letters (beginning at the first position), and I make them capital letters. Here is that command:
State = $state.Trim().Substring(0,2).ToUpper()
And that is it. Here is the complete CreateCustomObjectsFromData.ps1 script:
$datain = import-csv C:\DataIn\DataDump.csv
Foreach ($d in $datain)
{
#region Name
If($d.name -match ',')
{
$name = (Get-Culture).textinfo.ToTitleCase($d.name).Split(',').trim()
$ln = $name[0]
$fn = $name[1]
}
ELSE {
$name = $d.Name.Split().trim()
$fn = $name[0]
$ln = $name[1]
}
#endregion
#region Address
$a = $d.address.split(',')
$str = $a[0] -replace '(Street|street)','ST'
$city = If($a[1] -match 'dwpt') {"Dewpoint"} ELSE {$a[1]}
$state = if($a[2] -match 'South Carolina') {"SC"} ELSE {$a[2]}
$zip = If($a[3].trim().Length -gt 5) {"Error for $a"} ELSE {$a[3]}
#endregion
#region Create Custom Object
[PSCustomObject]@{
Lname = $ln
Fname = $fn
Date = [datetime]("{0}/{1}/{2}" -f $d.month, $d.day, $d.year)
Street = $str.ToUpper()
City = $city.ToUpper()
State = $state.Trim().Substring(0,2).ToUpper()
Zip = $zip }
#endregion
}
And here is the output from the script:
That's it for Data Manipulation Week. I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy