The entire OLAP package in Flex has sparse API documentation, but there are several ‘how-to’ examples out in the land of live-docs. This usually doesn’t bode well, because it generally means a tech-writer never talked to the development team to figure out what all the dependencies are on the various properties. We have the source, but chasing it down ourselves sucks.

 

A precursor into what doesn’t work:

  • OLAPAttribute.displayName does NOT work on subsequent dimensions. It will only work on your first dimension which is usually the ROW_AXIS. However, the OLAPLevel.attributeName will always expect to look up the OLAPAttribute.name.
  • The allMemberName even though it’s defined on the OLAPHierarchy, it must be actually set on an OLAPAttribute which is displayed for that dimension.

Now onto the real problem:

Generally to sort your cube, you do a 2-dimensional sort to the original flat dataprovider then assign this to the cube dataprovider.  And in most cases this seems to work OK, until your CATEGORY_AXIS is based on anything to do with Time (which is a lot of the time actually). In most cases you’ll have a two-tier hierarchy of year and month / quarter, but the problem appears to be most prevalent with months. Even though your original source is sorted correctly, some months will be placed out of order, especially if you’re using the allMember level which it builds on the fly in the query.

The Fix:

So the fix involves re-arranging the member IList in building the OLAPQuery to the appropriate OLAPSet. In addition to fixing the sort issue, now is the time to re-arrange the allMember level to where it seems logical for your application. Accounting applications generally read left-to-right, so summary total’s are generally shown on the right hand side.

The way know if you’re working with the allMember level that it created for you in the sort method, is to look for the OLAPMember.hierarchy.allMemberName and compare that to the current OLAPMember.name

The way to correctly resort months involves a bit of kludgery but I haven’t found a more elegant way around it. In the OLAPAttribute for the dimension you specify the dataField to the integer of the month (generally this is string from a formatter), and assign a displayNameFunction to use a DateFormatter to turn this into something meaningful at the UI level. Even though the name of the OLAPMember is a string, it’s actually a string cast of the original value to the dataField (hence the actual integer value). You can then re-cast this back to an int to do a numeric sort (so you don’t end up with 0, 1, 10, 11, 2, 3, etc).

Now you might think an easier way to do this is to just use a SortField, however since you’re original Object is transformed to a flash_proxy and lost in the process relative to the OLAPGrid, the internal numeric sort method to Sort will throw an error that it can’t find the property that you originally wanted to sort on (eg month).

This should get your columns back in the order in which they were meant to be in.

private function getQuery(cube:IOLAPCube):IOLAPQuery
{
… //Setup the rest of the dimensions / sets to associate to the correct axis

var list:ArrayCollection = cube.findDimension(“timeDimension”).findAttribute(“Month”).members as ArrayCollection;
list.sort = new Sort();
list.sort.compareFunction = compareSortMonth;
list.refresh();

var moSet:OLAPSet = new OLAPSet();
moSet.addElements(list);

private function compareSortMonth(a:OLAPMember, b:OLAPMember, fields:Array = null):int
{
if (a.name == a.hierarchy.allMemberName) return 1;
else if (b.name == b.hierarchy.allMemberName) return -1;

var aMonth:int = parseInt(a.name);
var bMonth:int = parseInt(b.name);

if (aMonth < bMonth) return -1;
else if (bMonth < aMonth) return 1;
else return 0;
}