Archive for January, 2010

Flex: Stacked column chart – programmatically in actionscript

January 27, 2010

I was looking for ages for an example of a dynamically generated stacked column chart in Flex, but most of the examples were incorporating some MXML, or contained hard-coded series objects.  

The example below is based on Adobe Livedocs, but I show how to generate the series arrays programatically in as3, with no use of mxml code, and apply these series to a column chart (added to panelActionscript as seen in the code below). Also, this could be easily adapted to a barchart.

If youve got any suggestions, let me know.

Flex Stacked Chart

 

<?xml version="1.0" encoding="utf-8"?>
<mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml"
creationComplete="initApp()" width="622" height="660">
  <mx:Script><![CDATA[

  	 import mx.charts.CategoryAxis;
  	 import mx.charts.series.ColumnSeries;
  	 import mx.charts.ColumnChart;
  	 import mx.charts.series.ColumnSet;
     import mx.charts.Legend;
     import mx.charts.BarChart;
     import mx.charts.series.BarSet;
     import mx.charts.series.BarSeries;
     import mx.collections.ArrayCollection;

     [Bindable]
     private var yearlyData:ArrayCollection = new ArrayCollection([
        {month:"January", revenue:120, costs:45,
            overhead:102, oneTime:23},
        {month:"February", revenue:108, costs:42,
            overhead:87, oneTime:47},
        {month:"March", revenue:150, costs:82,
            overhead:32, oneTime:21},
        {month:"April", revenue:170, costs:44,
            overhead:68},
        {month:"May", revenue:250, costs:57,
            overhead:77, oneTime:17},
        {month:"June", revenue:200, costs:33,
            overhead:51, oneTime:30},
        {month:"July", revenue:145, costs:80,
            overhead:62, oneTime:18},
        {month:"August", revenue:166, costs:87,
            overhead:48},
        {month:"September", revenue:103, costs:56,
            overhead:42},
        {month:"October", revenue:140, costs:91,
            overhead:45, oneTime:60},
        {month:"November", revenue:100, costs:42,
            overhead:33, oneTime:67},
        {month:"December", revenue:182, costs:56,
            overhead:25, oneTime:48},
        {month:"May", revenue:120, costs:57,
            overhead:30}
     ]);

     private function initApp():void {

     	// Create a column chart object
        var stackedColumnChart:ColumnChart = new ColumnChart();
        stackedColumnChart.dataProvider = yearlyData;
        stackedColumnChart.showDataTips = true;
 stackedColumnChart.width	= 460;

 // Set the horizontal axix category
        var xAxis:CategoryAxis = new CategoryAxis();
        xAxis.categoryField = "month";
        stackedColumnChart.horizontalAxis = xAxis;

 // ColumnSet.series is an array which contains
 // an array of ColumnSeries objects.
        var columnSet:ColumnSet = new ColumnSet();
        columnSet.type = "stacked";

        // Each item in seriesDetails becomes a different segment of
        // a column in the stacked chart i.e. each item represents a series.
        var seriesDetails:ArrayCollection = new ArrayCollection([
        	{YField:"costs", DisplayName:"Recurring Costs"},
        	{YField:"overhead", DisplayName:"Overhead Costs"},
        	{YField:"oneTime", DisplayName:"One-Time Costs"}
        	]);

        // Create a ColumnSeries, and an array to be
        // populated with dynamically generated columnSeries objects
        var columnSeries:ColumnSeries;
    	var seriesArray:Array = new Array();

    	// Generate an array of ColumnSeries objects
        // which are then be applied to the ColumnSet series.
        for(var i:int = 0; i < seriesDetails.length; i++){
        	columnSeries = new ColumnSeries();
        	columnSeries.yField = seriesDetails[i].YField;
        	columnSeries.displayName = seriesDetails[i].DisplayName;
        	seriesArray.push(columnSeries);
        }
        columnSet.series = seriesArray;

 // c.series could take an array of column sets
 // for displaying mixed charts i.e. c.series = [columnSet1, columnSet2];
 stackedColumnChart.series = [columnSet];

        var legend:Legend = new Legend();
        legend.direction = "horizontal";
        legend.dataProvider = stackedColumnChart;

        panelActionscript.addChild(stackedColumnChart);
        panelActionscript.addChild(legend);

     }

  ]]></mx:Script>
  <mx:VBox height="100%">
    <mx:Panel title="Stacked chart (dynamically created in ActionScript)"
    				id="panelActionscript" width="490">
    </mx:Panel>
  </mx:VBox>
  <mx:Panel title="Same chart created solely in MXML" id="panelMxml" width="490">
    <mx:ColumnChart id="mxmlColumnChart" dataProvider="{yearlyData}"
    				showDataTips="true" width="470">
      <mx:horizontalAxis>
           <mx:CategoryAxis categoryField="month"/>
       </mx:horizontalAxis>
       <mx:series>
           <mx:ColumnSet type="stacked">
               <mx:ColumnSeries
                   yField="costs"
                   displayName="Recurring Costs"/>
               <mx:ColumnSeries
                   yField="overhead"
                   displayName="Overhead Costs"/>
               <mx:ColumnSeries
                   yField="oneTime"
                   displayName="One-Time Costs"/>
           </mx:ColumnSet>
       </mx:series>
    </mx:ColumnChart>
    <mx:Legend dataProvider="{mxmlColumnChart}" direction="horizontal"/>
  </mx:Panel>
</mx:WindowedApplication>

Advertisements

Automatically create Getter Setter in Visual Studio

January 5, 2010

private string directory;

This is your member variable. Highlight and right click on ‘directory’, then choose Refactor/Encapsulate Field.

Produces the following code automatically:

public string Directory
{
get { return directory; }
set { directory = value; }
}

Reading a File to a String in C#, including Tabs and Newlines etc.

January 5, 2010

StreamReader sr = new StreamReader(fileName);
fileAsString= sr.ReadToEnd();
sr.Close();

This is very handy if you want to compare a string that is to be written to a file, with a file that already exists.
Used it for some unit testing.

Closing Excel in C#: always one instance left in task manager

January 5, 2010

There are loads of forum posts on trying to close Excel from within C#. In my case, when opening a number of workbooks, no matter how I tried, there was always one Excel instance left open in the Task Manager, even if I specificially used .quit or any other of the 10’s of methods I tried. This is how I finally solved the problem:

With just one excelApp instance:
Excel.Application excelApp = new Excel.Application();

Search through the Excel files and open the ones you want:

workbook = excelApp.Workbooks.Open(name, false, true, missing etc);

Make sure to close the workbook when finished with it:
//end the workbook session, checking if has been assigned
//a workbook object successfully first
if (workbook != null)
{
workbook.Close(false, Type.Missing, Type.Missing);
excelApp.Workbooks.Close();
Marshal.ReleaseComObject(workbook);
}

Finally, Kill the excel app. I dont use the word Kill lightly, because it was a
very annoying problem:

excelApp.Quit();
GC.Collect();
Marshal.FinalReleaseComObject(excelApp);

Done and dusted.