Transpose.ps1
#Requires -Version 4 <#PSScriptInfo .VERSION 0.2 .GUID 5d99dc80-0976-499d-824e-4143a64e7724 .AUTHOR Sam Boutros .COMPANYNAME Public Domain .COPYRIGHT Public Domain .TAGS Transpose .LICENSEURI https://opensource.org/licenses/MIT .PROJECTURI https://superwidgets.wordpress.com/2014/11/30/powershell-script-to-transpose-rows-into-column .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES https://gallery.technet.microsoft.com/scriptcenter/Powershell-Script-to-7c8368be .PRIVATEDATA #> <# .DESCRIPTION Script to transpose input data converting Server/Property/Value columns into rows where each server is a column and each property is a row. Script by Sam Boutros v0.1 - 11/30/2014 - Original release on the Microsoft Script Center Repository https://gallery.technet.microsoft.com/scriptcenter/Powershell-Script-to-7c8368be v0.2 - 11 October 2021 - rewrite, publish in the PowerShell Gallery For more information see https://superwidgets.wordpress.com/2014/11/30/powershell-script-to-transpose-rows-into-column #> #region Input [CmdletBinding(ConfirmImpact='Low')] Param( [Parameter(Mandatory=$false)]$SourceCSVFile = '.\table1.csv', [Parameter(Mandatory=$false)]$TransposeBy = 'Property', [Parameter(Mandatory=$false)]$GroupBy = 'Server' ) #endregion function Write-Log { <# .SYNOPSIS Function to log input string to file and display it to screen .DESCRIPTION Function to log input string to file and display it to screen. Log entries in the log file are time stamped. Function allows for displaying text to screen in different colors. .PARAMETER String The string to be displayed to the screen and saved to the log file .PARAMETER Color The color in which to display the input string on the screen Default is White 16 valid options for [System.ConsoleColor] type are Black Blue Cyan DarkBlue DarkCyan DarkGray DarkGreen DarkMagenta DarkRed DarkYellow Gray Green Magenta Red White Yellow .PARAMETER LogFile Path to the file where the input string should be saved. Example: c:\log.txt If absent, the input string will be displayed to the screen only and not saved to log file .EXAMPLE Write-Log -String "Hello World" -Color Yellow -LogFile c:\log.txt This example displays the "Hello World" string to the console in yellow, and adds it as a new line to the file c:\log.txt If c:\log.txt does not exist it will be created. Log entries in the log file are time stamped. Sample output: 2014.08.06 06:52:17 AM: Hello World .EXAMPLE Write-Log "$((Get-Location).Path)" Cyan This example displays current path in Cyan, and does not log the displayed text to log file. .EXAMPLE "$((Get-Process | select -First 1).name) process ID is $((Get-Process | select -First 1).id)" | Write-Log -color DarkYellow Sample output of this example: "MDM process ID is 4492" in dark yellow .EXAMPLE Write-Log 'Found',(Get-ChildItem -Path .\ -File).Count,'files in folder',(Get-Item .\).FullName Green,Yellow,Green,Cyan .\mylog.txt Sample output will look like: Found 520 files in folder D:\Sandbox - and will have the listed foreground colors .EXAMPLE Write-Log (Get-Volume | sort DriveLetter | Out-String).Trim() Cyan .\mylog.txt Sample output will look like (in Cyan, and will also be written to .\mylog.txt): DriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus SizeRemaining Size ----------- ------------ -------------- --------- ------------ ----------------- ------------- ---- Recovery NTFS Fixed Healthy OK 101.98 MB 450 MB C NTFS Fixed Healthy OK 7.23 GB 39.45 GB D Unknown CD-ROM Healthy Unknown 0 B 0 B E Data NTFS Fixed Healthy OK 26.13 GB 49.87 GB .LINK https://superwidgets.wordpress.com/2014/12/01/powershell-script-function-to-display-text-to-the-console-in-several-colors-and-save-it-to-log-with-timedate-stamp/ .NOTES Function by Sam Boutros v1.0 - 6 August 2014 v1.1 - 1 December 2014 - added multi-color display in the same line v1.2 - 8 August 2016 - updated date time stamp format, protect against bad LogFile name v1.3 - 22 September 2017 - Re-write: Error handling for no -String parameter, bad color(s), and bad -LogFile without errors Add Verbose messages v1.4 - 27 March 2020 - Update to skip writing to file if LogFile parameter is not provided v1.5 - 15 May 2020 - Update to fix bug related to colors (thanks Stephen) #> [CmdletBinding(ConfirmImpact='Low')] Param( [Parameter(Mandatory=$false, ValueFromPipeLine=$true, ValueFromPipeLineByPropertyName=$true, Position=0)] [String[]]$String, [Parameter(Mandatory=$false,Position=1)][String[]]$Color, [Parameter(Mandatory=$false,Position=2)][String]$LogFile, [Parameter(Mandatory=$false,Position=3)][Switch]$NoNewLine ) if ($String) { #region Write to Console $i=0 foreach ($item in $String) { try { Write-Host "$item " -ForegroundColor $Color[$i] -NoNewline -EA 1 } catch { Write-Host "$item " -NoNewline } $i++ } if (-not $NoNewLine) { Write-Host ' ' } #endregion #region Write to file if ($LogFile) { try { "$(Get-Date -format 'dd MMMM yyyy hh:mm:ss tt'): $($String -join ' ')" | Out-File -Filepath $Logfile -Append -ErrorAction Stop } catch { Write-Warning "Write-Log: Bad LogFile name ($LogFile). Will not save input string(s) to log file.." } } else { Write-Verbose 'Write-Log: Missing -LogFile parameter. Will not save input string(s) to log file..' } #endregion } else { Write-Verbose 'Write-Log: Missing -String parameter - nothing to write or log..' } } #region Read input if (Test-Path $SourceCSVFile) { try { $InputTable = Import-Csv $SourceCSVFile -EA 1 $ColumnList = ($InputTable | Get-Member -MemberType NoteProperty).Name if ($TransposeBy -notin $ColumnList) { Write-Log 'Transpose Error: TransposeBy column',$TransposeBy,'not found in input file',$SourceCSVFile Magenta,Yellow,Magenta,Yellow; break } if ($GroupBy -notin $ColumnList) { Write-Log 'Transpose Error: GroupBy column',$GroupBy,'not found in input file',$SourceCSVFile Magenta,Yellow,Magenta,Yellow; break } } catch { Write-Log 'Transpose Error: unable to read input file',$SourceCSVFile Magenta,Yellow Write-Log $_.Exception.Message break } } else { Write-Log 'Input file',$SourceCSVFile,'not found, building sample file' Magenta,Yellow,Green $SourceCSVFile = '.\table1.csv' $TransposeBy = 'Property' $GroupBy = 'Server' @' Server,Property,Value Srv1,Memory,4GB Srv1,Processes,135 Srv1,Storage,120GB Srv2,Memory,8GB Srv2,Processes,234 Srv2,Storage,120GB Srv3,Memory,16GB Srv3,Processes,239 Srv3,Storage,160GB Srv4,Memory,10GB Srv4,Processes,219 Srv4,Storage,100GB '@ | Out-File $SourceCSVFile -Force } $InputTable = Import-Csv $SourceCSVFile $ColumnList = ($InputTable | Get-Member -MemberType NoteProperty).Name Write-Log 'Read',$InputTable.Count,'rows from input table from',$SourceCSVFile,'- columns:',($ColumnList -join ', ') Green,Cyan,Green,Cyan,Green,Cyan #endregion #region Transpose # Value = intersection of $TransPoseBy X $GroupBy $OutputTable = foreach ($TransposeByItem in $InputTable.$TransposeBy | Select -Unique) { $Props = [ordered]@{ $TransposeBy = $TransposeByItem } foreach ($GroupByItem in $InputTable.$GroupBy | Select -Unique){ $Value = ($InputTable.where({ $_.$GroupBy -eq $GroupByItem -and $_.$TransposeBy -eq $TransposeByItem })).Value $Props += @{ $GroupByItem = $Value } } New-Object -TypeName PSObject -Property $Props } Write-Log 'Transposed',"$($ColumnList.Count)/$($InputTable.Count)",'columns/rows into',"$(($OutputTable | Get-Member -MemberType NoteProperty).Count)/$($OutputTable.Count)",'columns/rows' Green,Cyan,Green,Cyan,Green $OutputTable #endregion |