I am trying to create an nicely formatted Txt file (has to be Txt cannot be CSV) from a hashtable.
Here is the code that I have that creates the text file
$hashTable.GetEnumerator() | Sort-Object Name |
ForEach-Object {"{0} `t`t: {1} `t`t: {2} `t`t: {3} `t`t: {4}" -f $_.DisplayName,$_.EmployeeNo,$_.Email, $_.SamName,$_.Upn}|
Add-Content $textFilePath
As you can see - when someone is input into the Txt file with a long name it messes up the formatting because the tabs just get shifted along.
I'm looking for a solution that dynamically sets the width of the columns in a text file.
Use PowerShell's output-formatting system, whose Format-Table
cmdlet produces human-readable, column-aligned representations, but note that these are generally not suitable for later programmatic processing:
($hashTable.GetEnumerator() | Sort-Object Name).Value |
Format-Table -AutoSize -Property DisplayName, EmployeeNo, Email, SamName, Upn |
Out-File $textFilePath -Encoding Utf8 -Width 1024
$hashTable.GetEnumerator() | Sort-Object Name
enumerates the hashtable entries as System.Collections.DictionaryEntry
entries and sorts them by their .Name
(.Key
) property.
.GetEnumerator()
call is necessary to sort the hash table entries by their key (name); without it, the hash table as a whole would be sent as a single object through the pipeline, in which case the Sort-Object
would effectively be a no-op - by definition, there's nothing to sort if there's only one object; compare the output from:@{ zach = 1; moe = 2; aardvark = 0 } | Sort-Object Name
@{ zach = 1; moe = 2; aardvark = 0 }.GetEnumerator() | Sort-Object Name
Sort-Object
call has no effect..Value
then extracts the entries' values (this could also be done in streaming fashion with ... | ForEach-Object Value
).
The values appears to be Active Directory user objects, so you can just pass a list of the desired property names to Format-Table
, which form the output-table column names, whereas the corresponding property values form the column values.
Note that Out-File
rather than Add-Content
(Set-Content
) is used, because only it automatically converts the formatting objects that Format-Table
outputs to their intended string representations, as you would see in the console (terminal).
-Width 1024
ensures that the table lines aren't truncated based on whatever the width of the current console window happens to be; adjust as needed.-Encoding Utf8
is used as an example to control the output encoding; note that Windows PowerShell defaults to "Unicode" (UTF-16LE), whereas the default is BOM-less UTF-8 in PowerShell [Core] v6+. See this answer for more information about default character encodings in Windows PowerShell vs. PowerShell [Core].