Hey, Scripting Guy! Event 4 *Solutions* from Expert Commentators (Beginner and Advanced; the high jump)

Hey, Scripting Guy! Event 4 *Solutions* from Expert Commentators (Beginner and Advanced; the high jump)

  • Comments 2
  • Likes

  

(Note: These solutions were written for Event 4.)   

Beginner Event 4: The High Jump

In the high jump event, you must soar to new heights as you read a database containing high jumpers training data in order to predict who will win on gameday.

Guest commentator: Bruno Terkaly

Image of guest commentator Bruno Terkaly

Bruno Terkaly is a Microsoft developer evangelist who covers Northern California. He has been a presenter and instructor in 10 countries, including Asia, Canada, Latin America, and Europe as well as cities too numerous to list throughout the U.S. Bruno is an expert at finding fast food at airports and navigating his way to the car-rental agencies, as well as always requesting the aisle seat on airplanes. Previously, Bruno also has experience as a Rapid Response Engineer at Microsoft where he helped Premier Customers with Advanced Debugging techniques and performed overnight, emergency fixes to production systems under massive pressure. Bruno has coded in many languages, SDKs, Frameworks, and operating systems, including DOS, Linux, UNIX, and of course, Windows. Bruno still finds time to use VI as his editor when he is not coding in Visual Studio.


VBScript solution

The code below executes a query that calculates the average of a jumper's best personal jump height and season’s best jump height. Based on the highest average jump, a winner is predicted. To make things easy, I decided to use Microsoft Office Access to build the query. This is seen here.

Image of using Office Acces to build the query


The completed BeginnerEvent4Solution.vbs script is seen here.

BeginnerEvent4Solution.vbs

'*********Declare Variables************
dim connectString
dim objConnection
dim objRecordSet
'*********Setup and Init Variables*****
connectString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=HighJumperDatabase.mdb;User Id=admin;Password=;"
'*********Main Code********************
wscript.echo "Opening Database.."
call OpenDatabase()

wscript.echo "Executing Query.."
call ExecQuery()

'*********Sub Routines****************
sub OpenDatabase()
  on error resume next
  Set objConnection = CreateObject("ADODB.Connection")
  call CheckForError("Creating connection")
  Set objRecordSet = CreateObject("ADODB.Recordset")
  call CheckForError("Creating recordset")
  objConnection.Open "Provider = Microsoft.Jet.OLEDB.4.0; " & _
                        "Data Source = HighJumperDatabase.mdb"
  call CheckForError("Openening Connection")
  wscript.echo "Database opened successfully..."
end sub


sub ExecQuery()
   on error resume next
   objRecordSet.ActiveConnection = objConnection
  
   strSQL = "SELECT [High Jumper Data Query].Name, [High Jumper Data Query].Country, " & _
            "[High Jumper Data Query].[Personal Best], [High Jumper Data Query].[Season Best], " & _
            "(([High Jumper Data Query].[Personal Best]+[High Jumper Data Query].[Season Best])/2) as JumpAverage " & _
            "FROM [High Jumper Data Query] " & _
            "ORDER BY ([High Jumper Data Query].[Personal Best]+[High Jumper Data Query].[Season Best]/2) DESC;"

  
   objRecordSet.Source = strSQL
   objRecordSet.Open
   call CheckForError("Opening recordset...")
  
   Do Until objRecordSet.EOF
      strField1 = objRecordSet.Fields("Name").Value
      strField2 = objRecordSet.Fields("Country").Value
      strField3 = objRecordSet.Fields("JumpAverage").Value
      Wscript.Echo strField1 & "-------" & strField2 & "-------" & strField3
      objRecordSet.MoveNext
   Loop
   wscript.echo "Executed query successfully..."
end sub

sub checkForError(msg)
  if err.number <> 0 then
     wscript.echo "Error encountered for " & msg & ", Error = " & err.description
  end if
end sub

When we run the BeginnerEvent4Solution.vbs script, in CScript, we see the following information displayed.

Image of what's displayed after running the script

Guest commentator: Richard Siddaway

Richard Siddaway is an Infrastructure Technical Architect, and Windows PowerShell MVP. He is the founder and leader of the UK Windows PowerShell User Group. He maintains the Of PowerShell and Other Things blog, and is the author PowerShell in Practice.

Windows PowerShell solution

In the High Jump event, query an Access database and retrieve the name of the high jumper that you expect to win. The expected winner, is the one who has the highest training jumps. This translates to “Read the database, calculate sums, and find out who can jump the highest”

The first thing we do is look at the data to get an idea of what are we dealing with. We find the following fields.

Field

Data Type

ID

AutoNumber

Name

Text

Country

Text

Personal Best

Number

Season Best

Number

 

We can ignore the ID field as it is just an identifier for the row in the data table. The Country field isn’t important for this task. We definitely need the Name and the two types of scores. Having two numeric fields is going to complicate matters a bit but Windows PowerShell can easily handle this situation.

Let us look at how we can solve this. The first thing I do after the header rows is to clear the screen. I always do this in the scripting games. You cannot guarantee how the previous script left things and I do not want my display lost in among everything else.

To read the database, we use ADO.NET. This is because we do not have a cmdlet built into Windows PowerShell. ADO.NET supplies a number of classes for reading databases. You can track them down on MSDN as they are all in the System.data namespace. Because we  mustread an Office Access database, we use the OleDb classes.

We have to start by connecting to the database. This is not much more complicated than using the Get-Content cmdlet. We must create a connection by using the System.Data.OleDb.OleDbConnection class. This needs a connection string. There is a wonderful site called ConnectionStrings.Com that answers our needs. The site is worth remembering because it has connection strings for all the data stores you can imagine plus a few more. Our connection string is fairly simple. We just supply the provider (type of database) and the path to the database. If this was a production script we would use Test-Path before this line to make sure it exists. After creating the connection, we can open it. I assume the database is in the c:\scripts folder. This is shown here.

$conn = New-Object System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Scripts\HighJumperDatabase.mdb")
$conn.Open()

Now we can read the data. We must create a by command using SQL and our connection. I have just selected all the data in the table with this command. Notice that the name of the table is in brackets []. That is because it has spaces in the name. The command will fall apart and error without the brackets []. We could actually answer the whole question at this point by writing a piece of SQL that is a bit more complicated. This is a Windows PowerShell competition rather than a SQL competition, so Iwill behave and save that for a blog posting.

Having created the command we can run it against the database by using the ExecuteReader method. This will pull back all records that match the SQL command into a DataReader object. This is seen here.

$cmd = New-Object System.Data.OleDb.OleDbCommand("Select * FROM [High Jumper Data]", $conn)
$data = $cmd.ExecuteReader()

Now that we have our data what are we going to do with it? We could keep playing with ADO.NET, but Windows PowerShell is the name of the game so we will turn it into objects we can work with. We deal with bunches of objects by using arrays, so we had better create one. We then loop through the DataReader by using a while loop. It will keep looping while there are still records in the reader pulling back the next record at each loop.

We can create a new object to hold the data. This could be just given as New-Object PSObject but it does not hurt to see the whole name. We can then use Add-Member to add the data as properties to the object. We don’t bother with the first column on data, the ID. We could have dropped it altogether by just putting the columns we needed in the select string but that’s more typing. At the end of the loop, the object is added to the array. This is shown here.

$jumpers = @()
while ($data.read()) {
         
          $jump = New-Object -TypeName System.Management.Automation.PSObject
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "Name" -Value $data.GetValue(1)
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "Country" -Value $data.GetValue(2)
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "PersonalBest" -Value $data.GetValue(3)
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "SeasonBest" -Value $data.GetValue(4)
         
          $jumpers += $jump

}

It is now time to close the connection to the database. This step is not required but it is good practice, especially if you have several connection going to the database. You will eventually use up all the connections if you do not close them. To close the connection, call the close method as seen here.

$conn.Close()

A title is written via Write-Host and then we create a sorted version of the array. I decided to sort on season-best jump and use personal best as a tie breaker as the expected winner should be the one who is jumping best at the moment. The sorted list of jumpers is displayed with Format-Table as seen here.

#$jumpers | sort PersonalBest -Descending | Format-Table -AutoSize

As a cosmetic touch I decide to swap the name so it appears as first-name last-name for readability. A quick split and then string substitution is used in the final Write-Host to predict the winner. When substituting into the Write-Host string, I have had to use a subexpression  e.g. $($names[1]) $($names[0]). This forces the inner expression to be evaluated and passed into the substitution. Play around with this a bit as it can get very interesting. The completed BeginnerEvent4Solution.ps1 script is seen here.

BeginnerEvent4Solution.ps1


cls
## open database connection
##  Assuming that the database should be
##  in C:\Scripts as in previous years
$conn = New-Object System.Data.OleDb.OleDbConnection("Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Scripts\HighJumperDatabase.mdb")
$conn.Open()

## read the data
$cmd = New-Object System.Data.OleDb.OleDbCommand("Select * FROM [High Jumper Data]", $conn)
$data = $cmd.ExecuteReader()

## create an array
$jumpers = @()
while ($data.read()) {
         
          $jump = New-Object -TypeName System.Management.Automation.PSObject
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "Name" -Value $data.GetValue(1)
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "Country" -Value $data.GetValue(2)
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "PersonalBest" -Value $data.GetValue(3)
          Add-Member -InputObject $jump -MemberType NoteProperty -Name "SeasonBest" -Value $data.GetValue(4)
         
          $jumpers += $jump

}
## close the connection
$conn.Close()

#$jumpers | sort PersonalBest -Descending | Format-Table -AutoSize

Write-Host "The current results are:"

$order = $jumpers | sort SeasonBest, PersonalBest -Descending
$order | Format-Table -AutoSize

$names = ($order[0].Name).Split(",")

Write-Host "`n The expected winner is:- $($names[1]) $($names[0]) of $($order[0].Country)"

When the BeginnerEvent4Solution.ps1 script is run, it displays the output shown here:

Image of the script's output


Advanced Event 4: The High Jump

The high jump event is an event in which participants jump over a horizontal bar that is placed at different heights. For this event, you will be given the results of a series of jumps and be asked to draw a graph that indicates the trend of the jumps.

Guest commentator: Rajesh Ravindranath

Image of guest commentator Rajesh Ravindranath


Rajesh is a Software Development Engineer at Microsoft where he works on the Remote Desktop Services (RDS) team. He mainly focuses on management aspects of RDS. He was on the team that implemented Remote Desktop Services Management through Windows PowerShell. He is currently working on Windows PowerShell scripts to ease the management of Remote Desktop Services. For information related to Remote Desktop Services Management through Windows PowerShell visit Terminal Services Team Blog.

VBScript solution

How do we solve this problem? By reading the problem statement, we can infer that there are three major tasks to perform.

· Read statistics from the results file.

· Populate the data read into Excel application.

· Draw a chart from the data populated.

A look into the contents of the statistics file reveals that we have a list of N line separated entries for N participants. Each entry has a comma-separated list of items, of which, the first two correspond to the participant’s name and rest represent the score or height of the jump in each attempt.

To start with, we create an instance of the Excel.Application object and add a workbook to it. A workbook can be compared with a ledger with three worksheets in it by default. Because our task can be accomplished with a single worksheet we, will work with the first worksheet and name it “High Jump Data”. To make the script run in a cleaner fashion, the application instance is set to invisible mode until the data is populated and chart is plotted. This is shown here.

Set xlApp = CreateObject("Excel.Application")

xlApp.Visible = False                        ' Hide the application till the graph is plotted.
xlApp.workbooks.add                          ' Add a workbook to work upon.
xlapp.Worksheets(1).Name = "High Jump Data"  ' Name the first sheet

The next step is to read the data and populate this worksheet. To open the file, we create an instance of Scripting.FileSystemObject and invoke its OpenTextFile method. Here we specify the open mode to be ReadOnly, as we only need to read the data in the file. This is seen here.

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile (".\High Jump Stats_Adv4.txt", FileOpenMode)

Once we have a handle to the file, we read it line by line. This is the same as reading each participant’s record one at a time. The process is repeated until you read to the the end of file for all the participants. We use the Readline method as seen here.

strNextLine = objFile.Readline 

As previously stated, each string is a comma-separated list of values. This list is obtained by splitting the string on a comma. This is shown here.

arrScores = Split(strNextLine, ",")

The participant’s name is constructed from the first two entries of the arrScores array. These elements represent the first and last name respectively. The rest of the entries in the array represent the person’s scores for the event. Here we build the participant’s name.

strName = arrScores(0) & arrScores(1)

There are two variables, rowNumber and colNumber, that are used to maintain the location of the current row and column to be updated. In the activesheet (the first worksheet), we set the first column to the name of the participant. The particpant’s scores are entered in subsequent cells, one entry per cell and for every read record. The colNumber variable is set to 1, to refer to the first column. This is seen here.

        colNumber = 1                              
        xlApp.activesheet.cells(rowNumber, colNumber) = strName           
        For i = LBound(arrScores) + 2 To UBound(arrScores)                
            colNumber = colNumber + 1
            xlApp.activesheet.cells(rowNumber, colNumber) = arrScores(i)           
        Next

Now that the data has been ported to Office Excel, our final task is to draw the chart with the data. From the different charts that one can choose from, for a scenario such as this, the Line Chart would be a good choice. To know what the chart depicts and what are its axes represents, we must label them appropriately.

Coming back to the scripting part, once the file read is complete, the row and column counters point to the last row and the last column. Because the rowNumber is always updated in advance, the actual last cell is one less than the current value of the rowNumber variable (rownumber - 1). The data range in our case goes from the first cell 1, 1 to the last cell (rowNumber-1, colNumber). The confusing issue is that Excel refers to cells by a combination of letters and numbers. But when using Excel automation, you only use numbers.

We add a chart with the chart type set to Line Chart (value = 4), assign titles for the chart and axes, provide the data range and specify the chart to be created in new sheet. This newly added chart is an ActiveChart. This is seen here.

xlApp.Charts.Add                                    ' add a chart to the workbook
With xlapp.ActiveChart
    .ChartType = xlChartType                        ' specify the chart to be line chart
    .HasTitle = True                                ' chart has a title
    .ChartTitle.Text = "High Jump Statistics"       ' set the chart title
    .Location xlNewSheet                            ' create the chart in new sheet of the workbook
   
    .SetSourceData xlapp.Sheets("High Jump Data").Range(rangeString)       ' specify the data range
    .Axes(xlXAxisID, xlPrimaryAxis).HasTitle = True                        ' X-Axis has the title
    .Axes(xlXAxisID, xlPrimaryAxis).AxisTitle.Text = "Attempt #"           ' X-Axis is attempt number

    .Axes(xlYAxisID, xlPrimaryAxis).HasTitle = True                        ' Y-Axis has title
    .Axes(xlYAxisID, xlPrimaryAxis).AxisTitle.Text = "Score / Height"   ' Y-Axis is score/height

End With

Once the chart configuration is completed, the application is visible.

xlApp.Visible = True

The complete AdvancedEvent4Solution.vbs script is shown here.

AdvancedEvent4Solution.vbs

' 2009 Scripting Games - Event 4 - Rajesh B R

Const FileOpenMode  = 1                             ' Opening mode of the file, read-only here
Const xlChartType   = 4                             ' Line Chart ID
Const xlXAxisID     = 1                             ' X-Axis ID
Const xlYAxisID     = 2                             ' Y-Axis ID
Const xlPrimaryAxis = 1                             ' Primary axis group ID
Const xlNewSheet    = 1                             ' Create chart in new sheet


Set xlApp = CreateObject("Excel.Application")

xlApp.Visible = False                        ' Hide the application till the graph is plotted.
xlApp.workbooks.add                          ' Add a workbook to work upon.
xlapp.Worksheets(1).Name = "High Jump Data"  ' Name the first sheet

rowNumber = 1                                       ' Initialize counters to track cell to be updated
colNumber = 1

' Open the statistics file in read-only mode

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile (".\High Jump Stats_Adv4.txt", FileOpenMode)

Do Until objFile.AtEndOfStream                      ' Read all records, till the end is reached
    strNextLine = objFile.Readline                  ' Read a record
   
    If strNextLine <> "" Then  
        arrScores = Split(strNextLine, ",")         ' split the record string on comma
        strName = arrScores(0) & arrScores(1)       ' participant name: irst 2 entries of the list
        colNumber = 1                               ' foreach new record, re-initialize counter to 1
        xlApp.activesheet.cells(rowNumber, colNumber) = strName            ' first column is name

        For i = LBound(arrScores) + 2 To UBound(arrScores)                 ' add scores to cells
            colNumber = colNumber + 1
            xlApp.activesheet.cells(rowNumber, colNumber) = arrScores(i)           
        Next
       
        rowNumber = rowNumber + 1                   ' once record is processed, update row counter

    End If
Loop
objFile.Close                                       ' close the file

' Get the range in Excel Row and Column format. Range here is from first cell (1, 1) to last cell (rowNumber - 1, colNumber)
rangeString = "A1:" & xlApp.activesheet.cells(rowNumber - 1, colNumber).Address(RowAbsolute = True, ColumnAbsolute = True)

xlApp.Charts.Add                                    ' add a chart to the workbook
With xlapp.ActiveChart
    .ChartType = xlChartType                        ' specify the chart to be line chart
    .HasTitle = True                                ' chart has a title
    .ChartTitle.Text = "High Jump Statistics"       ' set the chart title
    .Location xlNewSheet                            ' create the chart in new sheet of the workbook
   
    .SetSourceData xlapp.Sheets("High Jump Data").Range(rangeString)       ' specify the data range
    .Axes(xlXAxisID, xlPrimaryAxis).HasTitle = True                        ' X-Axis has the title
    .Axes(xlXAxisID, xlPrimaryAxis).AxisTitle.Text = "Attempt #"           ' X-Axis is attempt number

    .Axes(xlYAxisID, xlPrimaryAxis).HasTitle = True                        ' Y-Axis has title
    .Axes(xlYAxisID, xlPrimaryAxis).AxisTitle.Text = "Score / Height"   ' Y-Axis is score/height

End With

xlApp.Visible = True                               ' make the app visible

Once the AdvancedEvent4Solution.vbs script is run, this output is displayed:

Image of the script's output


Guest commentator: Richard Norman

Image of guest commentator Richard Norman


Richard has worked in programming and Web development for 25 years. Currently, he works for Microsoft as a Development/Debugging engineer primarily specializing in SharePoint technologies. In addition to this work, he has been involved with DBA application integration tools such as Tibco and Biztalk. Recently, he began branching out to ISA server and CardSpace security technologies.

Windows PowerShell solution

For the advanced high jump event, I had to produce a chart or graph of a series of jumps. LogParser is one tool that I could use; however the script is dependent that tool is available on the system. Another tool that could be useful would be Office Excel through COM Automation. But once again, we must ensure that Excel is installed on the system, and the installation of Microsoft Office products is not supported on server operating systems except in very specific circumstances. For this script, I decided to use the new Charting Controls for .NET 3.5 SP1 (examples). With these charting controls, I have some flexibility of data imported and an advanced way to manipulate the charts that are produced.

The data file is a CSV file so Import-CSV is an option, but because the file does not have headers, Import-CSV will not work without cleaning up the CSV file first. The Import-CSV cmdlet assumes that in the first line of the file is the headers associated with the columns. Since this is not the case, I used string parsing with the Split”method to get a list of rows and columns from the file. This is shown here.

$resultlst = get-content "$($Env:USERPROFILE)\Documents\High Jump Stats_Adv4.txt"
$results=@(); $resultlst | foreach-object {$results+=,($_.split(","))}

After this step, the rest of the script then takes the data and adds it to the chart control. The chart control is used to finally export the chart to a Portable NetworkGraphics (PNG) file. The first thing we need to do is to load the DataVisualization namespace into Windows PowerShell because it is not loaded by default. In Windows PowerShell 2.0, we can use the Add-Type cmdlet, but in Windows PowerShell 1.0, we must use Reflection. I am using the strong name to load the class, because it is the recommended way to ensure you get the exact version of the assembly. This is seen here (note it is a single line of code).

[Reflection.Assembly]::load("System.Windows.Forms.DataVisualization, Version=3.5.0.0,Culture=Neutral, PublicKeyToken=31bf3856ad364e35")

Now we must create an instance of the charting object, and set the width and height. This is seen here.


$Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart
$Chart.Width = 500
$Chart.Height = 400

Once the chart object has been created, we create the chart area, the legend objects. We then add them to the chart object. This is seen here.


$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
$Legend = New-Object System.Windows.Forms.DataVisualization.Charting.Legend
$Chart.ChartAreas.Add($ChartArea)
$chart.Legends.add($Legend)

Now it is time to add the data to the data series, and to set up the legend. This is seen here.

foreach ($result in $results)
{
    $Chart.Series.Add("$($result[1].trim()) $($result[0].trim())")
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].Points.DataBindXY(1..$([int]$result.length-2), $result[2..[int]$result.length])
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Line
   $Chart.Series["$($result[1].trim()) $($result[0].trim())"].LegendText ="$($result[1].trim()) $($result[0].trim())"
}

We now must save the chart. To do this, we use the SaveImage method, and specify both the name of the script and the type. For this event, we are saving it as a PNG file. After we have saved the chart, we release the objects by calling the Dispose method. This is shown here.

$Chart.SaveImage($Env:USERPROFILE + "\Documents\demo\Total High Jump Chart.png", "PNG")
$ChartArea.Dispose()
$Legend.Dispose()
$Chart.Dispose()

The second half of the script creates an individual chart for each person in the file by using the same process above. We will not cover that portion of the script here because it is a similar process.

The completed AdvancedEvent4Solution.ps1 script is seen here.

AdvancedEvent4Solution.ps1

#============================================================
# Load the data into PowerShell for analysis
# The data file is a CSV file with last name, First name,
# and the rest are the results.
$resultlst = get-content "$($Env:USERPROFILE)\Documents\High Jump Stats_Adv4.txt"
#============================================================
# Parse each column so that the values are in their own "cells"
$results=@(); $resultlst | foreach-object {$results+=,($_.split(","))}
#============================================================
# load the charting assembly into PowerShell
# in V2 I could have used Add-Type with the type name below
[Reflection.Assembly]::load("System.Windows.Forms.DataVisualization, Version=3.5.0.0,Culture=Neutral, PublicKeyToken=31bf3856ad364e35")
#============================================================
# Creae a new Charting object
$Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart
#============================================================
# Set the Chart Height and width
$Chart.Width = 500
$Chart.Height = 400
#============================================================
# Setup the area for the chart
$ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
#============================================================
# Setup the Legend for the chart
$Legend = New-Object System.Windows.Forms.DataVisualization.Charting.Legend
#============================================================
# Add the chart location and the Legend to the chart
$Chart.ChartAreas.Add($ChartArea)
$chart.Legends.add($Legend)
#============================================================
# For each result, add the data to the data series
# and set up the legend information
foreach ($result in $results)
{
    #============================================================
    # Add a new data series named like the person
    $Chart.Series.Add("$($result[1].trim()) $($result[0].trim())")
    #============================================================
    # Add the data through a DataBind for this data series.
    # X is 1-number of items; Y is the values
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].Points.DataBindXY(1..$([int]$result.length-2), $result[2..[int]$result.length])
    #============================================================
    # Change the chart type to a line chart
    # There are several other types, documented on MSDN
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Line
    #============================================================
    # Add the text for this data series to the legend.
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].LegendText ="$($result[1].trim()) $($result[0].trim())"
}
#============================================================
# Save an image of the chart to a folder.
$Chart.SaveImage($Env:USERPROFILE + "\Documents\Total High Jump Chart.png", "PNG")
#============================================================
# Dispose of objects now that I am done.
$ChartArea.Dispose()
$Legend.dispose()
$Chart.dispose()
#============================================================
# In this area, I am going to create a chart using the
# same set of results instead of a single chart.
# Each chart will be an individual chart for each person.
# In this case I don't need to reload the data again since
# I have already done the parsing.
foreach ($result in $results)
{
    #============================================================
    # Creae a new Charting object
    $Chart = New-object System.Windows.Forms.DataVisualization.Charting.Chart
    #============================================================
    # Set the Chart Height and width
    $Chart.Width = 500
    $Chart.Height = 400
    #============================================================
    # Setup the area for the chart
    $ChartArea = New-Object System.Windows.Forms.DataVisualization.Charting.ChartArea
    #============================================================
    # Setup the Legend for the chart
    $Legend = New-Object System.Windows.Forms.DataVisualization.Charting.Legend
    #============================================================
    # Add the chart location and the Legend to the chart
    $Chart.ChartAreas.Add($ChartArea)
    $chart.Legends.add($Legend)
    #============================================================
    # Add a new data series named like the person
    $Chart.Series.Add("$($result[1].trim()) $($result[0].trim())")
     #============================================================
    # Add the data through a DataBind for this data series.
    # X is 1-number of items; Y is the values
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].Points.DataBindXY(1..$([int]$result.length-2), $result[2..[int]$result.length])
    #============================================================
    # Change the chart type to a line chart
    # There are several other types, but I can set this for
    # each series I want
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].ChartType = [System.Windows.Forms.DataVisualization.Charting.SeriesChartType]::Line
    #============================================================
    # Add the text for this data series to the legend.
    $Chart.Series["$($result[1].trim()) $($result[0].trim())"].LegendText ="$($result[1].trim()) $($result[0].trim())"
    #============================================================
    # Save an image of the chart to a folder.
    $Chart.SaveImage($Env:USERPROFILE + "\Documents\$($result[1].trim()) $($result[0].trim()) High Jump Chart.png", "PNG")
    #============================================================
    # Dispose of objects now that I am done.
    $ChartArea.Dispose()
    $Legend.dispose()
    $Chart.dispose()
} #end script

When the AdvancedEvent4Solution.ps1 script runs, it creates a chart that looks like the following:

Image of the chart produced by the script

Very cool, everyone. Thank you, Bruno, Richard, Rajesh, and Richard for your hard work on the shot put events. We have picked up some new techniques that we just cannot wait to try out. Join us tomorrow as we unveil the details for Event 9, the javelin throw. Make sure you check out the 2009 Summer Scripting Games forum for discussion of the events and for answers to questions if they arise while you are working on the Scripting Games. Follow us on Twitter for all the latest Scripting Games information.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • All the Scripting Games links in one location! Let the learning begin. (We will update this page every

  • I did the expert commentary for this one – it can be read here http://blogs.technet.com/heyscriptingguy