As part of an example of trying to read data from SharePoint and display it in a Flex/Flash application, I needed to see if I could create pie charts from the data. After figuring out how to get the list data as an xml output, then cleaning up the data to insert it into a ArrayCollection, the next step was to count the number of times a particular value was used in a particular column. If I was using SQL, it would be a straight forward grouping and count. The work around was to filter out the unique values and then filter the ArrayCollection on that value getting the count.
Finding the unique values was simple, because I knew someone had already created the query example for doing so. It was just a matter of searching the web and finding the code.
//takes an AC and the filters out all duplicate entries public static function getUniqueValues (collection:ArrayCollection, propertyName:String):ArrayCollection { var length:Number = collection.length; var dict:Dictionary = new Dictionary(); //this should be whatever type of object you have inside your AC var obj:Object; for(var i:int = 0; i < length; i++){ obj = collection.getItemAt(i); dict[obj[propertyName]] = obj[propertyName]; } //this bit goes through the dictionary and puts data into a new AC var unique:ArrayCollection = new ArrayCollection(); for(var propertyString:String in dict){ unique.addItem(dict[propertyString]); } return unique; }
With the unique values being returned, then I just needed to loop through each value to do a filter on the original ArrayCollection to get the count. There were several examples that I found, but they didn’t work, because they didn’t completely do what I needed. Part of the script had to include the filter function within the overall function. By creating the filter function as a variable, the loop call could use the filter for each filter by value. Since I planned adding an object to the final array of name and value, I used the name part of the array to hold the filter value. Then when the count was returned, but putting the array in to a temporary array and getting the length, I added the count to the object. The final code looks extremely simple.
//Takes an AC of values and finds the number of matching values in another AC to return a count public static function getValueCounts(sourceCollection:ArrayCollection, valueCollection:ArrayCollection, propertyName:String):ArrayCollection { var length:Number = valueCollection.length; var countArray:ArrayCollection = new ArrayCollection(); var filterFunction:Function = function(element:*, index:int, arr:Array):Boolean { return element[propertyName] == this.name; } var thisValue:String; var countObject:Object; for(var i:int = 0; i < length; i++){ countObject = new Object(); countObject.name = valueCollection.getItemAt(i); var tmpCollection:Array = sourceCollection.source.filter(filterFunction, countObject); sourceCollection.refresh(); countObject.value = tmpCollection.length; countArray.addItem(countObject); } return countArray; }
To use this, I simply create a FilterBy array from the original using the column I want to find unique values in, then pass the original, the unique values and the column to the function to get the name/value count array.
FilterValuesArray = getUniqueValues(SourceArrayCollection, "ColumnToFilter"); ValuesCountArray = getValueCounts(SourceArrayCollection, FilterValuesArray , "ColumnToFilter");
I used the final count array to display a pie chart.
About DeanLogic
Dean has been playing around with programming ever since his family got an IBM PC back in the early 80's. Things have changed since BASICA and Dean has dabbled in HTML, JavaScript, Action Script, Flex, Flash, PHP, C#, C++, J2ME and SQL. On this site Dean likes to share his adventures in coding. And since programming isn't enough of a time killer, Dean has also picked up the hobby of short film creation.