Hi all
After recurring issues with the sequencing of objects in a report (table does not correspond to graph) and having tried out several solutions (x/y-sort, geometric sort, recursive function to get graph sequence), it turned out that none of these really brought results I had been looking for.
The easiest way to get the sequence right seems to be the get/setSequenceNumber()-function of the object Occurrences (ObjOcc). That way the modelers can set their sequence in the way the want to have it...
The only problem I face now is that the "Define Order" functionality is only available for SAP models (because it's used the context of the synchronisation to SAP). For all the non-SAP models, I can't see a possibility to set the order. Does anybody know how to call the corresponding dialog from a report? Or has anybody built such a dialog from scratch or at least an idea how to do so?
Thank you very much in advance!
I have not used the get/setSequenceNumber() functions, but have you tried Model.BuildGraph() and its corresponding methods (BFSGetFirstNode, BFSNextNode(), etc.) to build your sequence?
You may still have to tweak it when you are splitting and joining with rules, but it is the best I have found for outputting the sequence correctly. It can also be used in any model type (besides Matrix, I assume), so you don't have the problem of not being able to use it with non-SAP models.
Thank you for your your answer. I have to say that I did exactly what you proposed but, the report's recipients weren't satisfied by the results because sometimes they preferred to have one branch before the other... I'm aware that this actually shoudn't be such a big issue. But, to get the buy-in of the poeple, those small things can make the difference.
(If you happened to be interested in my solution, I'd send it to you. It's capable of dealing with rules and sifting out undesired object symbol types).
Best regards
The sequencing of objects in reports seems to be a common problem. I publish the function I wrote to get the objects in sequence of the graph.
A few word to the code:
- It's designed to deal with horizontal models (simply change the sort order to y/x to adapt it for vertical models. This is mainly used to get the start event).
- There are more elegant ways to check whether a node has already been "visited". A possibility is the .MarkVisited() - function.
- The script only covers processes which are connected to the start event. If there is more than one flow in a model, only the first one is considered.
- The resulting array is filtered by symboltypes. That way, it's possible to get only SAP functions (for example). Pass the desired symboltypes as array to the function getObjsInGraphSequence().
You're invited to take the code an adapt it to your needs.
Best regards
(Sorry, for some reasons the code-snipped editor doesn't work...)
/******************************************************************************************* Name: getObjsInGraphSequence Version: 1.0 Date: 20.01.2010 Author: PH / Santrade ltd. Description: The function returns a list object occurrences in a model sorted along the sequence in the process graph. The sequence always starts with the event-object which is top-left-most. Parameters: model: [Model]. Any model whose occurring objects are returned as an Array listOfSymbols: Array of Symboltypes which are returned. If null, all objects occurring in the model are returned. Return Value: Array containing all objects of the defined object types which occur in model. History version 1.01 Corrected procedure to filter objects along the defined set of symbols. ********************************************************************************************/ function getObjsInGraphSequence(model, listOfSymbols) { // Parameter 1: Model {Model} : Model whose object occurrences shall be returned in the sequence of the graph // Parameter 2: listOfSymbols {Int[]}: List of Symbolconstants which shall be considered for the sequence// global Array for results var glblResult = new Array();
// call recursive sort function //glblResult = getConnectedObjOccs(model, getStartEvent(model.ObjOccListFilter(Constants.OT_EVT)), listOfSymbols, glblResult) glblResult = getConnectedObjOccs(model, getStartEvent(model.ObjOccList()), listOfSymbols, glblResult) // Get start event
// remove all unnecessary objects from array var filterObj = new Array();
if (listOfSymbols != null) { for (var i=0;i<glblResult.length;i++) { for (j=0;j<listOfSymbols.length;j++) { // Check if symbolnumber of objOcc is contained in the ListOfSymbols try { if (glblResult[i].getSymbol() == listOfSymbols[j]) { filterObj = filterObj.concat(glblResult[i]) j = listOfSymbols.length } // if } catch (err) { Dialogs.MsgBox(err) } } // for } // for return filterObj } else { return glblResult }
function getStartEvent(objOccurrences) { /* returns first event in terms of x/y coordinates Parameters: objOccurrences {ObjOcc[]) : Unsorted Array containing the objoccs of a model
Return value: {ObjOcc} : first event in terms of x/y from objOccurrences[] */
var sortedList = new Array(); sortedList = ArisData.sort(objOccurrences,Constants.SORT_X, Constants.SORT_Y, nLocale) for (var i=0;i<sortedList.length;i++) { if (sortedList[i].ObjDef().TypeNum() == Constants.OT_EVT) { return sortedList[i] i = sortedList.length } } // f0r } // function // recGetConnectedObjOccs function getConnectedObjOccs(model, startObject, ListOfSymbols, previousResults) { // Returns an array of objects in the sequence they occur in the graph. // parameter 1: model (type: model) Model to be analysed // parameter 2: startEvent (type: object) startEvent: Object to start analysis with // parameter 3: ListOfSymbols (type: Array of int): Resulting array contains only objects in list. If parameter is empty, all obejcts are returned. // parameter 4: previousResults (type: Array of objects): Array to pass on the results of the functions
var localConnObjOccs = new Array(); // get immediately connected objOccs sorted by y/x localConnObjOccs = ArisData.sort(startObject.getConnectedObjOccs(null, Constants.EDGES_OUT),Constants.SORT_Y,Constants.SORT_X, nLocale) var returnArray = new Array(); //add startobject to array to return if (isInArray(previousResults, startObject)<0) { previousResults.push(startObject) for (var i=0;i<localConnObjOccs.length;i++) { // call me for each connected objOcc if not yet in Array getConnectedObjOccs(model,localConnObjOccs[i], listOfSymbols, previousResults) } // for } return previousResults }
function isInArray(searchArray,searchObj) { // returns the position of the first occurrence of searchObj // if not found: return -1 var retValue = -1 for (var i=0;i<searchArray.length;i++) { if (searchArray[i].ObjDef().Identifier(nLocale) == searchObj.ObjDef().Identifier(nLocale)) { retValue = i i = searchArray.length } } return retValue } }
Hi Ms Curran,
unfortunately, having checked the WYSIWYG editor, I don't see a possibility to select this sorting option. In Aris out of the box, I have to say, even in the script engine I haven't even found a predefined sort algorithm which would have satisfied the needs we had in our company.
Hi All,
There is another simple solution that you can use to allow the modeler to control the output sequence without impacting the re-use of the object. If you use a model attribute, the problem comes up where a function is used in two models, the attribute comes up in both models. When a function is step 5 in Process A does not mean it will be Step 5 for process B too.
We found that you can number the incomming connection and adding an attribute on it works well for that purpose without affecting the object attributes and the reusability of objects on the models
Rgs,
Francois
Hi Francois!
That really sounds good. And how do you specify the query within the WISYWIG editor? I really would be thankful for this hint, because we are dealing with this since about 3 years. Do you go for object definitions? And how do you regard the connection attributes?
Best regards!
Markus