Usage Tracking Spreadsheet
This example demonstrates how to:
- Download a file from a Web server for inclusion in your workbook.
- Split up the contents of a file and put it into a worksheet.
- Write a simple and easy-to-understand piece of code to generate a column from other columns.
- Display a stacked bar chart.
When you started Resolver One for the first time, it asked you if you were willing to allow us to track your usage (we like to know how many people use our program, how often, and how those figures change).
If you said "yes", then whenever you start Resolver One, the application "phones home". The resulting data is anonymised and aggregated into a secure file with daily totals for Resolver One starts, and for new users.
The example spreadsheet is the one we use to visualise these numbers. The only difference is that the data it fetches is made up :-)
How to run it
Download the file: uses.rsl.
Download the free ZedGraph library.
Locate the package called "zedgraph dll only".
The file you get will be called something like zedgraph_dll_v514_464.zip. This means that it contains two versions of the zedgraph library, 5.14 (for .NET 2.0) and 4.64 (for .NET 1.1). Resolver One is a .NET 2.0 application.
Extract the file ZedGraph.dll from zedgraph_dll_v5.1.4 (or similar) and place it in the same directory as the RSL file.
Run Resolver One and open the RSL file.
Confirm that the file contains two worksheets, "Raw Data" and "Chart". The first contains some numbers, the second (unsurprisingly) a chart.
How it works
The interesting stuff is in the User Code.
Loading the data from the Web server
Pre-constants user code loads the basic data from the Web server. Doing this here, before the constants are applied, allows a user to manually override the values by typing in adjusted values.
In the pre-constants user code, load up the usage data from a Web server. Use basic HTTP authentication to confirm with the server that we have access rights:
from System.IO import StreamReader from System.Net import NetworkCredential, WebRequest uri = 'http://www.resolversystems.com' + '/documentation/examples/usages/usages.csv' request = WebRequest.Create(uri) request.Credentials = NetworkCredential("demouser", "demopassword") response = request.GetResponse() try: reader = StreamReader(response.GetResponseStream()) usageData = reader.ReadToEnd() finally: response.Close()Split the usage data into separate lines. Split each non-blank line into tab-separated values and put these into the "Raw data" sheet, converting them to numbers if possible:
for rowIndex, line in enumerate(usageData.split("\n")): if not line.strip(): continue for colIndex, value in enumerate(line.split("\t")): try: value = float(value) except: pass workbook["Raw data"][colIndex + 1, rowIndex + 1] = value
Adding calculations
The next interesting bit is where we add calculations. We do this in the pre-formulae user code so as to take account of any values that were manually adjusted.
- Work through all of the non-header rows in the raw data, and fill in a new "Existing user runs" column with the difference between the total number of runs and the runs by new users.
for row in workbook["Raw data"].Rows: if row is workbook["Raw data"].HeaderRow: continue row["Existing user runs"] = row["All runs"] - row["New user runs"]Note the use of headers to make the formula easier to understand.
Drawing the graphs
The final bit of code, in the post-formulae user code section, draws the graph.
Load the ZedGraph assembly:
import clr clr.AddReference("ZedGraph")Import various elements for later use:
from System import Array, Math, String from System.Drawing import Bitmap, Graphics, RectangleF from ZedGraph import AxisType, BarType, GraphPane, PointPairList, SymbolType
Create a GraphPane, which will do the graphing, with an appropriate size, title, and X and Y axis labels:
chart = GraphPane( RectangleF(0, 0, 640, 480), "Resolver One Daily Usage", "Date", "Uses" )Generate a list of dates for the X axis, and two lists of values to make up the two halves of each bar:
dates = [] existingRunsList = PointPairList() newRunsList = PointPairList() for row in workbook["Raw data"].Rows: if row is workbook["Raw data"].HeaderRow: continue dates.append(row["Date"]) existingRunsList.Add(row.Index, row["Existing user runs"]) newRunsList.Add(row.Index, row["New user runs"])Pass the values, along with a couple of other configuration parameters, to the GraphPane.
chart.AddBar("Existing runs", existingRunsList, Color.Blue) chart.AddBar("New runs", newRunsList, Color.Red) chart.XAxis.Type = AxisType.Text chart.XAxis.Scale.TextLabels = Array[String](dates) chart.BarSettings.Type = BarType.Stack g = Graphics.FromImage(Bitmap(1, 1)) chart.AxisChange(g)Get the image of the graph from the GraphPane, and create an image worksheet to display it.
And that's it! In a Python environment, tasks like this are straightforward, which is why we made Resolver One a Python environment...
Comments
If you have comments, questions or suggestions about any of the Resolver One documentation, please post them to the Documentation Suggestions Forum.
