Friday, December 7, 2007

Displaying GroupingCollection/HierarchicalData in Charts with drill-down

This example shows how to use GroupingCollection/HierarchicalData as dataProvider to a Chart and how to support drill down and drill up navigation.

Click on any item to drill-down and Ctrl+Click on any item to drill-up. The top chart uses HierarchicalData sample and the second chart uses GroupingCollection to generate a summary information from flat data.

Please note that all data is fictitious and I just cooked it up for the sample.

To get access to parent and children collections a HierarchicalCollectionView is constructed using GC/HD as source. To display a drilled down view the children collection is set as charts dataProvider. For a drill-up operation the clicked items parent collection is set as dataProvider.

The source can be downloaded from here.

I have used the DrillDown, DrillUp effects from Ely's chart drill down sample of XML data. The sample would have looked a bit dull without them. Thanks to Ely!.

25 comments:

jfizer said...

Just what I was looking for, thanks.

core000 said...

Sreenivas, how would I go about creating a summary function other than SUM or COUNT?

I want to be able to assign other values to the higher levels.

THanks

Sreenivas said...

SUM, COUNT, AVG, MIN and MAX are supported out of the box. If you want custom function you can specify a summaryFunction on the SummaryField and compute whatever you want there and return the value.

core000 said...

Can you provide some sample of assigning values to the first or the second levels of the hierarchy? eg. in your sample, how can we find the arrayCollection value of 'World' (level 1) or the 'America', 'Asia', 'Australia', and 'Europe' (level 2)?

Thanks!

Sreenivas said...

I am not clear about what exactly you want to get/do. But I will try to answer from what ever I understood.

The array collection of each node is available from the IHierarchicalCollectionView.getChildren API. I have used it to do the drill down. If can send me more info about what exactly you want to achive I would post a sample for that(if it is possible!)

Kumaresan said...

Sreenivas..!

How can i change this into a Pie Chart?

Plz advice.

-Kumar

Sreenivas said...

This should work even with a pie chart. I think Ely has a sample drill down working on Pie chart too.

Are you facing any problems in using a PieChart?

Kris said...

Is there any way to do a percentage operator for a summaryFunction? In one of your examples you have a drop down box change the grouping of ages and when it does this is calculates the number childnodes at each folder and displays to the right of the folder icon. The percentage operation (instead of COUNT) would calculate what percentage of the parents sum is makes up. I'm talking about having multiple levels of folders, so here is another example.

Folder One (10) 33%
Folder One A (3) 30%
Folder One B (4) 40%
Folder One C (3) 30%
Folder Two (20) 66%
Folder Two A (20) 100%

It seems you would need to know the parent count value and I can't seem to figure out how to access that.

bill p said...

I am trying to do this with an array collection...but I get no results

here is the retrun from php...

[{"tot":"TotalExpense","sec":"Variable","ln":1,"value":102557.6},{"tot":"TotalExpense","sec":"Variable","ln":2,"value":25375},{"tot":"TotalExpense","sec":"Variable","ln":3,"value":-707.8},{"tot":"TotalExpense","sec":"Variable","ln":4,"value":14543.5},{"tot":"TotalExpense","sec":"Variable","ln":5,"value":8831.45},{"tot":"TotalExpense","sec":"Variable","ln":6,"value":82916.4},{"tot":"TotalExpense","sec":"Variable","ln":7,"value":0},{"tot":"TotalExpense","sec":"Variable","ln":8,"value":0},{"tot":"TotalExpense","sec":"Variable","ln":9,"value":0},{"tot":"TotalExpense","sec":"Variable","ln":10,"value":0},{"tot":"TotalExpense","sec":"Personel","ln":11,"value":92000},{"tot":"TotalExpense","sec":"Personel","ln":12,"value":122000},{"tot":"TotalExpense","sec":"Personel","ln":13,"value":0},{"tot":"TotalExpense","sec":"Personel","ln":14,"value":29873.25},{"tot":"TotalExpense","sec":"Personel","ln":15,"value":75319.1},{"tot":"TotalExpense","sec":"Personel","ln":16,"value":29000},{"tot":"TotalExpense","sec":"Personel","ln":17,"value":53966.1},{"tot":"TotalExpense","sec":"Personel","ln":18,"value":89575},{"tot":"TotalExpense","sec":"Personel","ln":19,"value":3546.45},{"tot":"TotalExpense","sec":"SemiFixed","ln":20,"value":13525.8},{"tot":"TotalExpense","sec":"SemiFixed","ln":21,"value":0},{"tot":"TotalExpense","sec":"SemiFixed","ln":22,"value":3348.3},{"tot":"TotalExpense","sec":"SemiFixed","ln":23,"value":39839.1},{"tot":"TotalExpense","sec":"SemiFixed","ln":24,"value":14786.2},{"tot":"TotalExpense","sec":"SemiFixed","ln":25,"value":8205.05},{"tot":"TotalExpense","sec":"SemiFixed","ln":26,"value":19376},{"tot":"TotalExpense","sec":"SemiFixed","ln":27,"value":745.1},{"tot":"TotalExpense","sec":"SemiFixed","ln":28,"value":15000},{"tot":"TotalExpense","sec":"SemiFixed","ln":29,"value":6799.05},

I assign this to flatData like this
var rawArray:Array;
var rawData:String = String(event.result); //Alert.show(rawData);
rawArray = (rawData) as Array;
flatData = new ArrayCollection(rawArray); gc.refresh(); hView2 = new HierarchicalCollectionView(gc);

then the gc has
mx:GroupingField name="tot"
mx:GroupingField name="sec"
mx:GroupingField name="ln"
all with
mx:SummaryField dataField="value" operation="SUM" /

Neither the chart or AdvancedDataGrid is populating

If I change flatData to Array and read in my JSON i get grouping errors

I use ArrayCollection for most of my JSON on datagrids tiles etc but cannot seem to get it working in this context...Is there some gotcha with grouping collections?

bill p said...

My prior issue is resolved...

I do have a new question...

I have a grouping collection that has
3 levels

mx:GroupingField name="tot"
mx:GroupingField name="sec"
mx:GroupingField name="ln"

below ln I have detail with datafield vn

This works perfectly in the advanced data grid but on the chart which uses GroupLabel as the categoryField the Chart does not display the correct vn since there is no grouping done on vn...

The horizontalAxis labels are blank

If i include vn as a GroupingField then in the advanced datagrid there is a sub level to vn that is repetitive...

Any ideas?

Sreenivas said...

I am unable to understand the exact problem. May be a sample would help. I am assuming I can grab the data from your previous comment and use it to see what you are getting and what you need.

bill p said...

Yeah I hacked at it myself and came up with this as a solution

in the Drill up down function called
drillDownUp I added these lines...

child1 = hView2.getNodeDepth(hitItem.item); if
(child1.toString()!="3") { c2.categoryField="GroupLabel"; }
then basically the opposite in the drill down section (without the cntrl key)

So I have answered those questions on my own...Currently I am hacking away at breadcrumbs...I looked the the quietly scheming sample that has breadcrumbs but it is a bit complex...
I have created a more simple version where I have 3 linkbuttons that are visible and not depending on the drill level like this...
child1 = hView2.getNodeDepth(hitItem.item);
if (child1.toString() == "2") { bc1.visible=false; }
Then I have click functions in each breadcrumb but I am having an issue with the dataprovider


The root function works fine
public function clTot():void
{
chart2.mouseChildren = false;
chart2.series[0].setStyle("showDataEffect",effU);
chart2.series[1].setStyle("showDataEffect",effU);
chart2.dataProvider = hView2.source.getRoot();
effU.drillToIndex = 0;
bc1.visible=false;
bc2.visible=false;
bc3.visible=false;
}

but I am getting errors on the other functions on the when setting the dataprovider...
i have tried...
chart2.dataProvider = hView2.source.getData(1);
and
chart2.dataProvider = hView2.source.getData("ld");
and
chart2.dataProvider = hView2.source.getChildren("ld");
and some other things..
It is difficult for me to comminicate these issues in this small box...I appreciate your time on this...

bill p said...

I should ask this question in a different way...

In the example you move up and down the Children and Parents based on HitData...

I am able to use this feature...

I also have the for Breadcrumbs as the CNTRL click method is not acceptable for my users

I created a simple navigation with Link Button that are only visible when a user has clicked to that level or below...

When a user clicks the Link Button that corresponds to the Root Level I call the function I posted previously clTot()

This function works fine but my other functions one for each drill level do not work...I am not able to set the dataprovider without using hitData I beleive that I am just not using the correct syntax...

But I cannot find an example anywhere on the net...You seem to be the most knowledgeable about these drill down charts and grouping collections so...

Since I know what level each LinkButton should be at what is the syntax to take the user to that level

I have tried going down from the root like this...

var root1:Object = hView2.source.getRoot();
var child1:Object = hView2.getChildren(root1);
chart2.dataProvider = hView2.getChildren(child1);

Errors out
Error #1010: A term is undefined and has no properties.

If you want to look at the mxml file send me an email and I will send it...

viper said...

my datagrid generates a chart.i want to plot another chart based on the child nodes of my datagrid,which should come on clicking a bar.
eg.
chart1:
columnchart dataProvider="{dg.dataProvider}" itemClick="DrillDown(event)"

chart2:
columnchart dataProvider="{AC}"

AC should contain the data of the child nodes of a group(that is represented as a bar in chart1)

hope i stated my problem clearly,please suggest your solution.
Thanks in advance

Sreenivas said...

Take a look at drill down charts example on Quietly Scheming site by Ely Greenfield.

Sreenivas said...

Bill, you can send me a sample example at sreenivas.ramaswamy@gmail.com.

bill p said...

Thank you for your help in the past...

I have a question related to grouping collections and Export to Excel...

For my datagrids I am using a modified version of exportexcel.as found here...http://www.saskovic.com/blog/?p=3

But for my grouped advanced datagrids I decided to export using the flatdata set...Now I have a request to export to excel with subtotal lines...when I pass in the advanced datagrid with groups I am not sure how to loop through the elements...

Also I tried passing in the groupingcollection but was not successful in my syntax for looping through the elements...

I think a sample of this type would be helpful to many developers...

Sreenivas said...

To iterate over all items of GroupingCollection create a HierarchicalCollectionView and invoke expandAll. Then use the iterator.

I will try to post a sample soon.

Mitchell said...

Amazing... Thank you so much!

Mark said...

There is a bug in the DrillUpEffect.as code in the play() function. Specifically the first and second IF statements are incorrect. They should read as follows:

if (drillToIndex >= dstRenderData.elementBounds.length)

AND

if (drillToIndex < dstRenderData.elementBounds.length)

The original source code was checking against srcRenderData, which is incorrect.

Mark said...

I am having trouble getting this to work correctly with bubble charts. For some reason, sometimes the wrong bubble is being split apart on the drill-down. Any idea why?

srikanth602 said...

Can anybody let me know it you are able to get the list or collection of grouped data from advanced data grid . I am trying to bind this data to piechart . Any suggestions or code would be so much grateful

shyamal said...

Thanks for the article.very nice.

I guess we need an extra check for drillToIndex value at line 96 of drillupeffect.as file.Something like this

if((drillToIndex < srcRenderData.elementBounds.length) && (drillToIndex >=0))

shyamal said...
This comment has been removed by the author.
Subham Kundu said...

I want only one column chart. So I delete one column chart and Advance Datagrid. Problem is when I delete datagrid code the below error code..

Error #2032: Stream Error. URL: file:///C:/Users/test/Adobe Flash Builder 4.6/DemoDrillDown/bin-debug/mx_4.6.0.23201.swf

but when I don't delete the code and just visible="false" on the datagrid, the application is running fine.

Help me.