{"id":764,"date":"2014-08-29T00:01:00","date_gmt":"2014-08-29T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2014\/08\/29\/creating-custom-powershell-objects\/"},"modified":"2014-08-29T00:01:00","modified_gmt":"2014-08-29T00:01:00","slug":"creating-custom-powershell-objects","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/creating-custom-powershell-objects\/","title":{"rendered":"Creating Custom PowerShell Objects"},"content":{"rendered":"<p><b style=\"font-size:12px\">Summary<\/b><span style=\"font-size:12px\">: Use Windows PowerShell to create custom objects prior to data export.<\/span><\/p>\n<p>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&nbsp;3 to check my email sent to <a href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, hang out on Facebook and Twitter, and generally do all the things I do in my day-to-day life as the Scripting Guy.<\/p>\n<p>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.&nbsp;<span style=\"font-size:12px\">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 <\/span><a href=\"\/b\/heyscriptingguy\/archive\/2014\/08\/27\/use-powershell-to-normalize-names-before-data-import.aspx\" target=\"_blank\" style=\"font-size:12px\">Use PowerShell to Normalize Names Before Data Import<\/a><span style=\"font-size:12px\">), so I expect there to be three sections for these. However, in the end, transforming the date was so easy (see <\/span><a href=\"\/b\/heyscriptingguy\/archive\/2014\/08\/26\/use-powershell-to-fix-date-from-csv-file.aspx\" target=\"_blank\" style=\"font-size:12px\">Use PowerShell to Fix Date from CSV File<\/a><span style=\"font-size:12px\">) that I decided to code it directly in the portion of the script that creates the custom object.<\/span><\/p>\n<p>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:<\/p>\n<p style=\"margin-left:30px\">$datain = import-csv C:\\DataIn\\DataDump.csv<\/p>\n<p style=\"margin-left:30px\">Foreach ($d in $datain)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; {<\/p>\n<p>Now, I define a region for the name. To do this, I use the <b>#region<\/b> and <b>#endregion<\/b> tags. Now, I copy the script that I created earlier to normalize names, and I assign it to a region. This is shown here:<\/p>\n<p style=\"margin-left:30px\">#region Name<\/p>\n<p style=\"margin-left:30px\">&nbsp;If($d.name -match&nbsp; &#039;,&#039;)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $name = (Get-Culture).textinfo.ToTitleCase($d.name).Split(&#039;,&#039;).trim()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ln = $name[0]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $fn = $name[1]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ELSE {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $name = $d.Name.Split().trim()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $fn = $name[0]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ln = $name[1]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">#endregion<\/p>\n<p>Now I add the region for the address. Once again, I copy the essential transforming code from the script I wrote earlier (see <a href=\"\/b\/heyscriptingguy\/archive\/2014\/08\/28\/use-powershell-to-fix-address-issues-prior-to-export.aspx\" target=\"_blank\">Use PowerShell to Fix Address Issues Prior to Export<\/a>).<\/p>\n<p>I also create an address region so it makes the script easier to read and troubleshoot. The command is shown here:<\/p>\n<p style=\"margin-left:30px\">#region Address<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $a = $d.address.split(&#039;,&#039;)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $str = $a[0] -replace &#039;(Street|street)&#039;,&#039;ST&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $city = If($a[1] -match &#039;dwpt&#039;) {&quot;Dewpoint&quot;} ELSE {$a[1]}<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $state = if($a[2] -match &#039;South Carolina&#039;) {&quot;SC&quot;} ELSE {$a[2]}<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $zip = If($a[3].trim().Length -gt 5) {&quot;Error for $a&quot;} ELSE {$a[3]}<\/p>\n<p style=\"margin-left:30px\">#endregion<\/p>\n<p>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 &quot;property name equals value<i>.<\/i>&quot;<i> <\/i>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:<\/p>\n<p style=\"margin-left:30px\">Date = [datetime](&quot;{0}\/{1}\/{2}&quot; -f $d.month, $d.day, $d.year)<\/p>\n<p>I also call the <b>ToUpper<\/b><i> <\/i>method on the strings that are stored in the Street and City properties of the object:<\/p>\n<p style=\"margin-left:30px\">Street = $str.ToUpper()<\/p>\n<p style=\"margin-left:30px\">City = $city.ToUpper()<\/p>\n<p>The last thing I do is clean up the <b>state<\/b> 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:<\/p>\n<p style=\"margin-left:30px\">State = $state.Trim().Substring(0,2).ToUpper()<\/p>\n<p>And that is it. Here is the complete CreateCustomObjectsFromData.ps1 script:<\/p>\n<p style=\"margin-left:30px\">$datain = import-csv C:\\DataIn\\DataDump.csv<\/p>\n<p style=\"margin-left:30px\">Foreach ($d in $datain)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; {<\/p>\n<p style=\"margin-left:30px\">#region Name<\/p>\n<p style=\"margin-left:30px\">&nbsp;If($d.name -match&nbsp; &#039;,&#039;)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $name = (Get-Culture).textinfo.ToTitleCase($d.name).Split(&#039;,&#039;).trim()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ln = $name[0]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $fn = $name[1]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ELSE {<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $name = $d.Name.Split().trim()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $fn = $name[0]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $ln = $name[1]<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<\/p>\n<p style=\"margin-left:30px\">#endregion<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">&nbsp;#region Address<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $a = $d.address.split(&#039;,&#039;)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $str = $a[0] -replace &#039;(Street|street)&#039;,&#039;ST&#039;<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $city = If($a[1] -match &#039;dwpt&#039;) {&quot;Dewpoint&quot;} ELSE {$a[1]}<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $state = if($a[2] -match &#039;South Carolina&#039;) {&quot;SC&quot;} ELSE {$a[2]}<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; $zip = If($a[3].trim().Length -gt 5) {&quot;Error for $a&quot;} ELSE {$a[3]}<\/p>\n<p style=\"margin-left:30px\">#endregion<\/p>\n<p>&nbsp;<\/p>\n<p style=\"margin-left:30px\">#region Create Custom Object<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp; [PSCustomObject]@{<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Lname = $ln<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Fname = $fn<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Date = [datetime](&quot;{0}\/{1}\/{2}&quot; -f $d.month, $d.day, $d.year)<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Street = $str.ToUpper()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; City = $city.ToUpper()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; State = $state.Trim().Substring(0,2).ToUpper()<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Zip = $zip }<\/p>\n<p style=\"margin-left:30px\">#endregion<\/p>\n<p style=\"margin-left:30px\">&nbsp;&nbsp;&nbsp; }&nbsp;<\/p>\n<p>And here is the output from the script:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-29-14-01.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-8-29-14-01.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>That&#039;s it for Data Manipulation Week. I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><span style=\"font-size:12px\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>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 [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[529,530,3,4,45],"class_list":["post-764","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-comma-and-other-delimited-files","tag-data","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/764","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=764"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/764\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=764"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=764"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=764"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}