Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Friday Fun with Formatting

Posted on May 30, 2014August 19, 2015

PowerShell is very adept at retrieving all sorts of information from computer systems in your network. Often the data is in a format that is hard to digest at a glance. For example, when you see a value like 1202716672 is that something in MB or GB? What if you need to view that value as KB? I don't know about you but I'm not good at making those conversions in my head and on-the-fly. Instead, we often resort to commands like this.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!
PS C:\> get-ciminstance win32_computersystem | select Name,Number*,@{Name="MemGB";Expression={$_.totalphysicalmemory/1gb -as [int]}},Manufacturer


Name                      : WIN81-ENT-01
NumberOfLogicalProcessors : 4
NumberOfProcessors        : 1
MemGB                     : 8
Manufacturer              : LENOVO

That is much easier than seeing a value of 8589934592. The same thing applies when it comes to calculating percentages. Again, we're back to using custom hashtables with Select-Object. Of course, you can go the extra mile and create custom format and type extensions. But sometimes, at least speaking for myself, you want something in between. So I created two functions, Format-Value and Format-Percent and packaged them as a module.

Function Format-Percent {

<#
.Synopsis
Calculate a percent
.Description
This command calculates a percentage of a value from a total, with the formula (value/total)*100. The default is to return a value to 2 decimal places but you can configure that with -Decimal. There is also an option to format the percentage as a string which will include the % symbol.
.Parameter Value
The numerator value. The parameter has aliases of X and Numerator.
.Parameter Total
The denominator value. The parameter has aliases of Y and Denominator.
.Parameter Decimal
The number of decimal places to return between 0 and 15.
.Parameter String
Format the percentage as a string which will include the % symbol. This is done using the -f operator.
.Example
PS C:\> Format-Percent 1234 5000
24.68
.Example
PS C:\> get-ciminstance win32_operatingsystem -computer chi-dc04 | select PSComputername,TotalVisibleMemorySize,@{Name="PctFreeMem";Expression={ Format-Percent $_.FreePhysicalMemory $_.TotalVisibleMemorySize  }}

PSComputerName             TotalVisibleMemorySize           PctFreeMem
--------------             ----------------------           ----------
chi-dc04                                  1738292                23.92
.Example
PS C:\> get-ciminstance win32_operatingsystem -computer chi-dc04 | select PSComputername,TotalVisibleMemorySize,@{Name="PctFreeMem";Expression={ Format-Percent $_.FreePhysicalMemory $_.TotalVisibleMemorySize -asString  }}
PSComputerName             TotalVisibleMemorySize           PctFreeMem
--------------             ----------------------           ----------
chi-dc04                                  1738292           23.92%


.Notes
Last Updated: May 30, 2014
Version     : 1.0

#>

[cmdletbinding(DefaultParameterSetName="None")]
Param(
[Parameter(Position=0,Mandatory,HelpMessage="What is the value?")]
[ValidateNotNullorEmpty()]
[Alias("X","Numerator")]
$Value,
[Parameter(Position=1,Mandatory,HelpMessage="What is the total value?")]
[ValidateNotNullorEmpty()]
[Alias("Y","Denominator")]
$Total,
[ValidateNotNullorEmpty()]
[ValidateRange(0,15)]
[int]$Decimal=2,
[Parameter(ParameterSetName="String")]
[Switch]$AsString
)

Write-Verbose "Calculating percentage from $Value/$Total to $decimal places"
$result = $Value/$Total

if ($AsString) {
    Write-Verbose "Writing string result"
    $pctstring = "{0:p$Decimal}" -f $result
    #remove the space before the % symbol
    $pctstring.Replace(" ","")

}
else {
    Write-Verbose "Writing numeric result"
    [math]::Round( ($result*100),$Decimal)
}

} #end function


Function Format-Value {

<#
.Synopsis
Format a numeric value
.Description
This command will format a given numeric value. By default it will treat the number as an integer. Or you can specify a certain number of decimal places. The command will also allow you to format the value in KB, MB, etc. Or you can let the command autodetect the value and divide by an appropriate value.
.Parameter Unit
The unit of measurement for your value. Valid choices are "KB","MB","GB","TB", and "PB". If you don't specify a unit, the value will remain as is, although you can still specify the number of decimal places.
.Parameter Decimal
The number of decimal places to return between 0 and 15.

.Example
PS C:\> Get-CimInstance -class win32_logicaldisk -filter "DriveType=3" | Select DeviceID,@{Name="SizeGB";Expression={$_.size | format-value -unit GB}},@{Name="FreeGB";Expression={$_.freespace | format-value -unit GB -decimal 2}}

DeviceID                            SizeGB                                      FreeGB
--------                            ------                                      ------
C:                                     200                                      124.97
D:                                     437                                       29.01
E:                                      25                                        9.67
.Example
PS C:\> (get-process chrome | measure ws -sum ).sum | format-value -Autodetect -verbose -Decimal 4
VERBOSE: Formatting 1180504064
VERBOSE: Using Autodetect
VERBOSE: ..as GB
VERBOSE: Reformatting 1.09943008422852
VERBOSE: ..to 4 decimal places
1.0994
.Notes
Last Updated: 5/29/2014
Version     : 1.0


#>

[cmdletbinding(DefaultParameterSetName="Default")]
Param(
[Parameter(Position=1,Mandatory,ValueFromPipeline)]
[ValidateNotNullorEmpty()]
$InputObject,
[Parameter(Position=0,ParameterSetName="Default")]
[ValidateSet("KB","MB","GB","TB","PB")]
[string]$Unit,
[ValidateRange(0,15)]
[int]$Decimal,
[Parameter(ParameterSetName="Auto")]
[switch]$Autodetect
)

Process {
    Write-Verbose "Formatting $Inputobject"
    if ($PSCmdlet.ParameterSetName -EQ "Default") {
    Write-Verbose "..as $Unit"
    Switch ($Unit) {
     "KB" { $value =  $Inputobject / 1KB ; break }
     "MB" { $value =  $Inputobject / 1MB ; break }
     "GB" { $value =  $Inputobject / 1GB ; break }
     "TB" { $value =  $Inputobject / 1TB ; break }
     "PB" { $value =  $Inputobject / 1PB ; break }
     default { 
      #just use the raw value
      $value = $Inputobject 
      }
    } #switch
    }
    else {
      Write-Verbose "Using Autodetect"
      
      if ($InputObject -ge 1PB) {
        Write-Verbose "..as PB"
        $value =  $Inputobject / 1PB
      }
      elseif ($InputObject -ge 1TB) {
        Write-Verbose "..as TB"
        $value =  $Inputobject / 1TB
      }
      elseif ($InputObject -ge 1GB) {
        Write-Verbose "..as GB"
        $value =  $Inputobject / 1GB
      }
      elseif ($InputObject -ge 1MB) {
        Write-Verbose "..as MB"
        $value =  $Inputobject / 1MB
      }
      elseif ($InputObject -ge 1KB) {
        Write-Verbose "..as KB"
        $value =  $Inputobject / 1KB
      }
      else { 
        Write-Verbose "..as bytes"
        $value = $InputObject
      }

    }
    Write-Verbose "Reformatting $value"
    if ($decimal) {
        Write-Verbose "..to $decimal decimal places"
        [math]::Round($value,$decimal)
    }
    else {
        Write-verbose "..as [int]"
        $value -as [int]
    }
} #process
} 

Set-Alias -Name fv -Value Format-Value
Set-Alias -Name fp -value Format-Percent

Export-ModuleMember -Function * -Alias *

Format-Value will take any value and by default round it to an integer. Or you can specify to format the value as a certain unit of measurement such as GB or MB. You can even specify the number of decimal places. Or, you can use the -Autodetect parameter and the function will make the best guess about the 'size' of your value. Use -Verbose if you want to know what unit it detects.

I did a similar thing with percentages. All you have to do is specify a value and a total and the function does the rest. Again, you can specify the number of decimal places. By default, the function writes a numeric value to the pipeline which I find makes it easier if you want to sort. But you can also specify to get a percentage as a string which will use the -f operator. The string will include the % symbol. I take an extra step to remove the space between the value and symbol.

With the function, my PowerShell expressions become a little easier to write.

Get-CimInstance -class win32_logicaldisk -filter "DriveType=3" |
Select DeviceID,
@{Name="SizeGB";Expression={$_.size | fv -unit GB}},
@{Name="FreeGB";Expression={$_.freespace | fv -unit GB -decimal 2}},
@{Name="PctFree";Expression={fp -x $_.freespace -y $_.size}}

In the code sample I'm using the function and parameter aliases. But I like the result.
formatfunctions

Download FormatFunctions.zip extract it to your modules directory and you should be good to go. I've set the minimum PowerShell version to 3.0 although there's nothing I can think of that would prevent these commands from working on v2. But I'd like to drive you to at least 3 anyway.

I hope you'll let me know what you think and what other types of data formatting you'd like to see added to the module.

NOTE: An update has been posted at http://bit.ly/1PzSnJa


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “Friday Fun with Formatting”

  1. Pingback: BPOTW 2014-05-30 | SQL Notes From The Underground

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d