1

I am working on an apex trigger. I have a list that I need to sort by a date field, do some processing, then sort by another date field, and do more processing etc 5 times. When I do the initial SOQL query I can sort by Date1 using ORDER BY. I can even sort by Date2 by using a wrapper class as outlined in the apex help documentation here. But I'm not sure how to then a Date3, Date4, Date5 etc.

I'm thinking I need to modify the wrapper class so that it will accept some inputs and output different types of sorts, but I'm not sure how to do this.

The wrapper class where I tried making the field to be sorted on an input

global class CustomWrapper implements Comparable {

public Custom_Object__c CO1;
public String sortField;

public CustomWrapper(Custom_Object__c CO) {
    CO1 = CO;
}

global Integer compareTo(Object compareTo) {
    CustomWrapper compareToOppy = (CustomWrapper)compareTo;

    Integer returnValue = 0;
    if(sortField=='Date1'){       
        if (CO1.Date1 == compareToOppy.CO1.Date1) {
            returnValue = 0;
        } else if (CO1.Date1 > compareToOppy.CO1.Date1) {
            returnValue = 1;
        } else if (CO1.Date1 < compareToOppy.CO1.Date1) {
            returnValue = -1;
        }
    }
    //...More of the same for different sortFields
    return returnValue; 

}
}
  • 1
    you are sorting in Apex, right? where exactly are you displaying the data? in a visulaforce page? do you have the option to sort Client side? Also, if you can include what and how you are attempting to do so (Codewise) it will be easier to provide assistance. Thanks – glls Jul 14 '18 at 18:48
  • This is for bulk processing in a trigger. I've also added the code I'm working on where I try to make the field to be sorted by an input – denvergreene Jul 14 '18 at 19:13
2

A fully plug-and-play solution would need a more powerful Sortable class, which I've written once or twice before. This should be a top-level class, because you ultimately want some static variables to make life easier for yourself. Here goes.


public class Sortable implements Comparable {
    // interface to compare
    public interface SortMethod {
        Integer compareTo(Object a, Object b);
    }

    // Example: Date interface
    public class DateFieldSort implements SortMethod {
        Boolean sortAsc;
        SObjectField field;

        public DateFieldSort(SObjectField sortField) {
            this(sortField, true);
        }
        public DateFieldSort(SObjectField sortField, Boolean sortAsc) {
            this.sortAsc = sortAsc;
            field = sortField;
        }
        public Integer compareTo(Object a, Object b) {
            SObject left = (SObject)a, right = (SObject)b;
            Date v1 = (Date)left.get(field), v2 = (Date)right.get(field);
            if(v1 == null) {
                v1 = Date.newInstance(0, 0, 0);
            }
            if(v2 == null) {
                v2 = Date.newInstance(0, 0, 0);
            }
            return
                (sortAsc ? 1: -1) * (
                (v2.year() << 9 | v2.month() << 5 | v2.day()) -
                (v1.year() << 9 | v1.month() << 5 | v2.day())
                );
        }
    }

    // set this value before calling sort
    public static SortMethod compareMethod;

    // Constructor accepting a value
    public Sortable(Object value) {
        this.value = value;
    }

    // Private storage
    Object value;

    // Get value back
    public Object getValue() {
        return value;
    }

    // implements Comparable
    public Integer compareTo(Object other) {
        return compareMethod.compareTo(this.value, ((Sortable)other).value);
    }
}

Now that you've got this, you're almost ready to sort; it just takes three steps.

Step 1

Convert your records to Sortable items:

Sortable[] values = new Sortable[0];
for(Sobject record: Trigger.new) {
  values.add(new Sortable(record));
}

Step 2

Specify your sorting method.

Sortable.compareMethod = new Sortable.DateFieldSort(Opportunity.CloseDate);

Step 3

Sort your list.

values.sort();

You can repeat steps 2 and three as frequently as you like. If you don't like the getValue part, you could also just make your Object variable public. To implement new sort methods, you just need to add more implements SortMethod classes as you desire.

Don't worry about the << and | parts if you don't fully understand them, we're basically converting the dates into bitmaps and subtracting them; the result is that the number will either be positive, negative, or 0, and the sort algorithm will take care of the rest.

In case your curious, the bitmap looks like this:

          Year              Month  Day
___________________________||___||_____
|                          ||   ||    |
0000 0000 0000 0000 0000 0000 0000 0000
| improve this answer | |
  • Thanks so much @sfdcfox. I realized I had a datetime, so I had to change a few things, but otherwise it works! I couldn't get the bitmap to work even by adding down to the milliseconds so I went back to comparing the values directly like in my original question. – denvergreene Jul 14 '18 at 23:22
  • I loop through the values collection and can even get the individual record, but I can't figure out how to do anything with it. I keep getting "Value does not exist" errors when trying to get the specific ID out no matter how I try it. @sfdcfox – denvergreene Jul 15 '18 at 13:38
  • @denvergreene You might want to ask a different question regarding that, because it sounds like we're going to need to see some code, which isn't easy to read in a comment. – sfdcfox Jul 15 '18 at 13:39
  • It's based on Step 1 in your solution. After sorting I loop through the values sObject collection, but I'm not sure how to pull out any of the fields from the sObject. – denvergreene Jul 15 '18 at 13:51
  • 1
    @denvergreene You have to "cast" it back into a variable (e.g. Opportunity opp = (Opportunity)values[index].getValue(); – sfdcfox Jul 15 '18 at 13:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.