Hey everyone, wouldn't usually post but I feel your pain on this one. I managed to make it work in a roundabout way. Will try to explain as best I can! The issue is the subforms are sorted by their created time so I've managed to get my subform to sort in the following way....
To give you some context, my subform is being used for sorting a hierarchical task list. I needed to be able to order the tasks but also allow extra tasks to be put in between as and when they were needed.
You'll need;
- The original subform - ORIGINAL SUBFORM
- An exact copy of the subform you want to sort (doesn't need to be exact buy it makes the workflow code easier to write). - ORDERED SUBFORM
FIELD TO CONTROL THE SUBFORM ORDER - Within each subform, there needs to be a field you want to sort by, I sorted my field via a lookup field to a form that only contains numbers, this is because I didn't want my users to type numbers in but select them from a drop-down. I think I could have just used a dropdown for this but I wanted users to be able to edit the database of numbers without editing the form.
*BOTH HAVE A BOOLEAN FIELD TO CONFIRM IF A RECORD IS NEW OR NOT - called 'boolean' in code below
*BOTH HAVE A LOOKUP FIELD LINKED TO THE ORIGINAL FORM - called 'lookup' in code below
*BOTH HAVE A LOOKUP FIELD LINKED TO EACH OTHER - called 'lookuplink' in code below
How it works;
1. So basically we want to hide the original subform and use the new subform for editing the record. The user will add and edit records via the new subform.
(the rest is all done in workflow code)
2. On every edit, in the workflow code, new records will be added to the original subform and old records will be fetched and updated. This is where it helps to make an exact copy as you need to map all the fields across. A boolean field is used here to confirm if a record is new or not, this decides if a copy is made, once the copy is made the boolean is updated to true.
3. All the records in the subform copy are deleted.
4. Fetch the records from the original subform and use the sort function, sorting by the field you want to order with.
5. Finally, use the add record function again to create all new records in the subform copy using the sorted collection of records in step 4. As you have sorted by that chosen field they will be created in that order, thereby sorting the subform just as you wanted.
It's worth noting that there are a few other solutions out there that don't use a secondary subform but do something similar. I've had mixed results with these. Also, I needed to keep the original subform ID the same as its reference in other forms via lookups (for time sheets related to tasks etc.) It was very important for me that I had a subform where ID remained the same but also a subform where it was sorted.
So in code it looks something like this (replace Original_Subform with yours, and Ordered_Subform with your copy subform used to order the records);
ON ADD - ON SUCCESS
//first we just need to make sure there's a copy record created so it exists in both subforms
//
for each <myvariable> in Ordered_Subform
{
//the copy record is created and the boolean marked true to confirm copy is made
<variable> = insert into Original_Subform
[
<field> = <expression>
<field> = <expression>
<field> = <expression>
boolean=true
lookup=input.ID
lookuplink=myvariable.ID
];
//the copied record boolean is marked true to confirm copy is made
<myvariable>.boolean = true;
}
ON EDIT - ON SUCCESS
//this is where it gets a bit complicated.
//
for each <myvariable> in Ordered_Subform
{
if(<myvariable>.boolean == false)
{
//this will create the copy of any new records and put them into the original subform
<variable> = insert into Original_Subform
[
<field> = <expression>
<field> = <expression>
<field> = <expression>
boolean=true
lookup=input.ID
lookuplink=myvariable.ID
];
//the copied record boolean is marked true to confirm copy is made
<myvariable>.boolean = true;
}
//This will update existing subform records with any changes, record is fetched based on the lookuplink lookup field. Then all fields are mapped over
if(<myvariable>.boolean == true)
{
<variable> = Original_Subform [ lookuplink == myvariable.ID ];
<variable>.<field> = <expression> ;
}
}
//
//delete all tasks from Ordered_Subform
for each <variable> in Ordered_Subform
{
delete from Ordered_Subform[ID != null];
}
//
//fetch Original_Subform records linked to parent form record and sort by field, collected in a variable called ordered tasks
orderedtasks = Original_Subform [ lookup == input.ID ] sort by <field>;
//
//
for each <variable> in ordered tasks
<variable> = insert into Ordered_Subform
[
<field> = <expression>
<field> = <expression>
<field> = <expression>
boolean=true
lookup=input.ID
lookuplink=myvariable.ID
];
//the ordered subform is now sorted by the field you defined
I hope this helps people!!