Created
February 19, 2025 10:27
-
-
Save jhoneill/d9ddfea5ba0b5b499973defaa18e613a to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using namespace System.Windows.Forms.DataVisualization.Charting | |
using namespace System.Windows.Forms | |
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PsUseShouldProcessForStateChangingFunctions','',Justification='False positive. New-object does not change system state ')] | |
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectUsageOfAssignmentOperator','',Justification='False positive. New-object does not change system state ')] | |
param() | |
Add-Type -AssemblyName System.Windows.Forms | |
Add-Type -AssemblyName System.Windows.Forms.DataVisualization | |
function New-FormWithSave { | |
[outputType([System.Windows.Forms.Form])] | |
param ( | |
[Alias('Width')] | |
$FormWidth = 1280, | |
[alias('Height')] | |
$FormHeight = 720, | |
[parameter(ValueFromPipeline=$True)] | |
[System.Windows.Forms.Control]$Control | |
) | |
begin { | |
$form = New-Object -TypeName System.Windows.Forms.Form -Property @{Width = $FormWidth; Height = $FormHeight} | |
$SaveButton = New-Object -TypeName System.Windows.Forms.Button -Property @{Left = ($FormWidth - 140); Top = ($FormHeight - 70); Text = "Save"; Anchor = ([ System.Windows.Forms.AnchorStyles]::Bottom -bor [ System.Windows.Forms.AnchorStyles]::Right)} | |
$SaveButton.add_click({ | |
$FileTypes = [enum]::GetNames('System.Windows.Forms.DataVisualization.Charting.ChartImageFormat').ForEach({"*.$_"}) | |
$SaveFileDlg = New-Object -TypeName system.Windows.Forms.SaveFileDialog -property @{ | |
DefaultExt='PNG'; Filter="Image Files ($($FileTypes))|$($FileTypes)|All Files (*.*)|*.*"} | |
if ($SaveFileDlg.ShowDialog() -eq 'OK') { | |
$chart = $this.Parent.Controls.where({$_ -is [chart]}) | |
$Chart.SaveImage($SaveFileDlg.FileName, ($SaveFileDlg.FileName -replace 'tif$','Tiff' -replace 'jpg$','jpeg' -replace '.*\.(.*)','$1')) | |
} | |
}) | |
$Form.Controls.Add($SaveButton) | |
$Form.Add_Shown({$this.Activate()}) | |
} | |
process { | |
foreach ($c in $Control) { | |
if ($form.width -lt ($c.width + 2* $c.left)) {$form.width = $c.width + 2* $c.left} | |
if ($form.height -lt ($c.height + $c.top + 80)) {$form.height = $c.height + $c.top + 80} | |
$Form.Controls.Add($c) | |
} | |
} | |
end { return $form } | |
} | |
function New-FormJob { | |
param( | |
[parameter(ValueFromPipeline=$True)] | |
[system.windows.forms.form]$Form | |
) | |
process { | |
$newRunspace = [RunspaceFactory]::CreateRunspace() | |
$newRunspace.ApartmentState = 'STA' #Otherwise some things - like save dialog - hang the process. | |
$newRunspace.Open() | |
$newRunspace.SessionStateProxy.SetVariable('Form', $form) | |
$PSCmd = [PowerShell]::Create().AddScript({ | |
Add-Type -AssemblyName System.Windows.Forms | |
Add-Type -AssemblyName System.Windows.Forms.DataVisualization | |
[void]$Form.ShowDialog() | |
}) | |
$PSCmd.runspace = $newRunspace | |
[void]$psCmd.BeginInvoke() | |
$pscmd | |
} | |
} | |
function New-Chart { | |
param ( | |
[parameter(Mandatory=$True,ValueFromPipeline=$True)] | |
$InputObject, | |
[Alias('Title')] | |
[string]$ChartTitle, | |
[System.Windows.Forms.DataVisualization.Charting.SeriesChartType] | |
$ChartType = 'Line', | |
$width =1240, | |
$Height = 630, | |
[string]$XField, | |
[string]$XAxisTitle, | |
[string]$xAxisNumberFormat, | |
[int]$xAxisLabelAngle, | |
[System.Windows.Forms.DataVisualization.Charting.DateTimeIntervalType] | |
$XDateTimeIntervalType = "Days", | |
[parameter(Mandatory=$True)] | |
[string[]]$YFields, | |
[string]$YAxisTitle, | |
[string]$YAxisNumberFormat, | |
[string[]]$SeriesColors = @('Blue'), | |
[string[]]$YAxis2Fields, | |
[string]$YAxis2Title, | |
[string]$YAxis2NumberFormat, | |
[string[]] | |
$YAxis2SeriesColors = @('Red'), | |
[string]$TitleFontName = 'Calibri', | |
[float]$TitleFontSize = 12, | |
[System.Drawing.FontStyle] | |
$TitleFontStyle = 'Bold', | |
[switch]$Enable3D, | |
[switch]$Legend | |
) | |
begin {$chartData = @() } | |
process {$chartData += $InputObject} | |
end { | |
$titleFont = New-Object System.Drawing.Font -ArgumentList $TitleFontName, $TitleFontSize, $TitleFontStyle | |
$Chart = New-object Chart -Property @{ Width = $width; Height = $Height; Left = 10; Top = 10; BorderColor = 'Black'; | |
BorderDashStyle = 'Solid'; Anchor = ([System.Windows.Forms.AnchorStyles]15) } #15 is top + bottom + left + right | |
$Chart.ChartAreas.Add((New-Object ChartArea )) | |
If ($Enable3D) { | |
$chart.ChartAreas[0].Area3DStyle.Enable3D = $true | |
$chart.ChartAreas[0].Area3DStyle.Inclination = 45 | |
} | |
#region get data labels / x-values; handle datetime as x axis values. Set axis titles and number formats and legend/title | |
if ($XField) { | |
$xAxisLabels = $Chart.ChartAreas[0].axisx.LabelStyle | |
if ($xValues = $chartData.$XField -as [datetime[]]) { | |
$dtFormats = (Get-Culture).DateTimeFormat | |
$xAxisLabels.IntervalOffsetType = $XDateTimeIntervalType | |
$xAxisLabels.IntervalType = $XDateTimeIntervalType | |
$xAxisLabels.Angle = $xAxisLabelAngle | |
if ($xAxisNumberFormat) { | |
$xAxisLabels.Format = $xAxisNumberFormat | |
} | |
else { | |
$xAxisLabels.Format = switch ($XDateTimeIntervalType) { | |
Hours {$dtFormats.ShortTimePattern} | |
Minutes {$dtFormats.LongTimePattern} | |
Seconds {$dtFormats.LongtTimePattern} | |
Milliseconds {$dtFormats.LongtTimePattern +".fff"} | |
Days {$dtFormats.ShortDatePattern + " " + $dtFormats.ShortTimePattern } | |
Default {$dtFormats.ShortDatePattern } | |
}} | |
} | |
else { | |
$xValues = $chartData.$XField | |
# $Measured = $xValues | Measure-Object -Minimum -Maximum | |
# $Chart.ChartAreas[0].axisx.Maximum = $Measured.Maximum | |
# $Chart.ChartAreas[0].axisx.Minimum = $Measured.Minimum | |
$xAxisLabels.Format = $xAxisNumberFormat | |
$xAxisLabels.Angle = $xAxisLabelAngle | |
} | |
} | |
if ($YAxisNumberFormat) { | |
$chart.ChartAreas[0].axisy.LabelStyle.Format = $YAxisNumberFormat | |
} | |
if ($YAxis2NumberFormat) { | |
$chart.ChartAreas[0].AxisY2.LabelStyle.Format = $YAxis2NumberFormat | |
} | |
if ($XAxisTitle) { | |
$Chart.ChartAreas[0].axisx.Title = $XAxisTitle | |
$Chart.ChartAreas[0].axisx.TitleFont = $titleFont | |
} | |
if ($YAxisTitle) { | |
$Chart.ChartAreas[0].axisy.Title = $YAxisTitle | |
$Chart.ChartAreas[0].axisy.TitleFont = $titleFont | |
} | |
if ($YAxis2Title) { | |
$Chart.ChartAreas[0].axisy2.Title = $YAxis2Title | |
$Chart.ChartAreas[0].axisy2.TitleFont = $titleFont | |
# $chart.chartAreas[0].TitleForeColor = [System.Drawing.Color]::DarkBlue | |
# $chart.chartAreas[0].axisy2.LineColor = [System.Drawing.Color]::DarkBlue | |
# $chart.chartAreas[0].axisy2.MajorGrid.LineColor = [System.Drawing.Color]::DarkBlue | |
# $chart.chartAreas[0].axisy2.LabelStyle.ForeColor = "Darkblue" | |
} | |
if ($Legend) {$Chart.Legends.Add((New-Object Legend -Property @{IsEquallySpacedItems = $True; BorderColor = 'Black'}))} | |
if ($ChartTitle) {$Chart.Titles.Add( (New-Object Title -Property @{Text = $ChartTitle; Font=$titleFont}))} | |
#endregion | |
#region add series to chart split between primary and secondary y-axis | |
$i = 0 | |
foreach ($f in $YFields) { | |
$Series = New-Object -TypeName Series -Property @{ChartType = $ChartType; Name=$f; BorderWidth = 2} | |
if ($SeriesColors[$i]) {$Series.Color = $SeriesColors[$i]} | |
if ($xValues) {$Series.Points.DataBindXY($xValues, $chartData.$f)} | |
else {$Series.Points.DataBindY( $chartData.$f)} | |
$chart.Series.Add($Series) | |
$i ++ | |
} | |
$i = 0 | |
foreach ($f in $YAxis2Fields) { | |
$Series = New-Object -TypeName Series -Property @{ChartType = $ChartType; Name=$f; BorderWidth = 2; YAxisType = 'Secondary'} | |
if ($YAxis2SeriesColors[$i]) { | |
$Series.Color = $YAxis2SeriesColors[$i]} | |
if ($xValues) {$Series.Points.DataBindXY($xValues, $chartData.$f)} | |
else {$Series.Points.DataBindY( $chartData.$f)} | |
$chart.Series.Add($Series) | |
$i ++ | |
} | |
#endregion | |
return $Chart | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment