Reputation: 413
I'm trying to write a script in Powershell to automatically print the contents of a text file. However, my tab characters are removed when printing making the final output hard to read.
I've provided an MWE to illustrate the issue.
Contents of MWE.txt (encoded in ANSI; a →
represents a tab character):
FOO→1,23→4,56
My powershell script:
$fname = "C:\MWE.txt"
Get-Content $fname | Out-Printer -name "Microsoft XPS Document Writer"
I'm using the XPS writer to avoid wasting paper, but in the end this will be changed to a real printer. The output on real paper is identical, I've ruled that out too.
Problem is that the in the print output, the tab characters are just erased, yielding:
FOO1,234,56
However, If I instead change the Out-Printer
to Out-String
, the console displays the file contents correctly. What on earth am I doing wrong? The file displays correctly with tabs in both notepad and notepad++, and I've tried UTF-8 encoding as well.
Content structure of the file I'm trying to print, which is automatically generated by a system and put on a web server for which I have no access. For clarity, I've used →
to denote the tab character and ·
to denote a space:
MWE·-·TestFile·:·
0)→Time
1)→Temperature·1
2)→Humidity
3)→Pressure·A-B
4)→Pressure·A-C
5)→Pressure·D-C
0)···················→1)→2)→3)→4)→5)→
2018-07-04 12:00:00→22,03→5,34→18,93→23,10→10,10
2018-07-04 13:00:00→21,99→5,22→18,75→23,56→10,00
2018-07-04 14:00:00→21,99→5,17→18,55→23,54→10,15
2018-07-04 15:00:00→22,03→5,25→18,73→23,41→8,33
Upvotes: 1
Views: 2841
Reputation: 437418
I have no explanation - the symptom sounds like a bug (that also affects the Microsoft Print To PDF
printer) and it seems to be specific to tab characters, whereas spaces work fine.
However, I can offer a workaround - assuming that the end goal is to create aligned output columns and that it isn't necessary to use tabs specifically to achieve that:
Get-Content "C:\MWE.txt" | ForEach-Object {
# Construct a custom object whose properties contain the
# tab-separated tokens on the input line.
$obj = New-Object PSCustomObject; $i = 0
foreach ($val in $_ -split "`t") {
Add-Member -InputObject $obj -NotePropertyName ('col' + ++$i) -NotePropertyValue $val
}
$obj
} | Format-Table -Property (1..6 | % { 'col' + $_ }) -HideTableHeaders |
Out-Printer -Name "Microsoft XPS Document Writer"
The ForEach-Object
script block splits each input line into tokens by tabs and constructs a custom object with properties containing the individual tokens.
Format-Table
creates table output with columns that use spaces for alignment; -HideTableHeaders
suppresses output of a table header, which would normally display the (autogenerated) property names.
-FormatTable
has to be instructed explicitly as to which columns to display, which is what (1..6 | % { 'col' + $_ })
does: it creates an array of all the auto-generated column names based on the assumption that at most 6 columns can be present, which is true of your sample input - adjust that number as needed. (To be safe, you may also specify a higher number, say, 20
, but that will slow processing down.Piping Format-Table
's output to Out-Printer -Name "Microsoft XPS Document Writer"
seems to result in the desired tabular output with aligned columns.
...
), you need to tweak the Format-Table
call, such as with custom column widths - see this answer of mine.Running this against your sample input yields the following 6-column layout in the console, and the output XPS document renders similarly:
MWE·-·TestFile·:·
0) Time
1) Temperature·1
2) Humidity
3) Pressure·A-B
4) Pressure·A-C
5) Pressure·D-C
0)··················· 1) 2) 3) 4) 5)
2018-07-04 12:00:00 22,03 5,34 18,93 23,10 10,10
2018-07-04 13:00:00 21,99 5,22 18,75 23,56 10,00
2018-07-04 14:00:00 21,99 5,17 18,55 23,54 10,15
2018-07-04 15:00:00 22,03 5,25 18,73 23,41 8,33
Upvotes: 1
Reputation: 21418
You're close, and you stumbled onto a workaround yourself - the use of Out-String
. You can add Out-String
to the pipeline before sending the content to the printer:
Get-Content $fname | Out-String | Out-Printer -Name "Microsoft XPS Document Writer"
If the above isn't working for you you can try processing the tab character yourself:
( Get-Content $fname -Raw ).Split( "`t" ) -Join "`t"
If that displays the output as you're expecting, you can pipe that to Out-Printer
(Out-String
isn't necessary because -Join
concatenates into a string):
( Get-Content $fname -Raw ).Split( "`t" ) -Join "`t" |
Out-Printer -Name "Microsoft XPS Document Writer"
However, this seems like it may be a bug with Out-Printer
, as comments and other answers have yielded varying success rates. The workarounds above are known to work on at least Windows 10.0.15063.0
(the version I'm currently running and tested with), but may have stopped working in later versions.
You may try converting the tabs to spaces as a workaround:
# This is set to 5 spaces here, but can be any number of
# spaces you want to represent a tab character
$replaceTabString = " "
( Get-Content $fname -Raw ).Replace( "`t", $replaceTabString ) |
Out-Printer -Name "Microsoft XPS Document Writer"
Upvotes: 2