2

I have a table that lists out two different objects in descending order. The issue is that the list is returning all of one object and then all of the second object. It is still in one table but the dates will restart half way down the list. How do I get all of the objects to list together in one fluid descending order list? If I don't put the descending filter on it, all of the objects are listed together. So what is it about the descending filter that is causing an issue? The issue seems to start once I use .sort().

    ....
    tasksAndNotes = new List<SObject>();
    t = [Select Date_Activity_Logged__c From Task WHERE Status = 'Completed' AND (AccountId = :actId OR WhatId = :actId OR WhoId = :actId)];
    n = [Select CreatedDate From Note WHERE ParentId =: actId];
    tasksAndNotes.addAll(t);
    tasksAndNotes.addAll(n);

    System.debug('before sorting list: ' + tasksAndNotes);

    tasksAndNotes.sort();
    finalList = new List<SObject>();
    for(Integer i = tasksAndNotes.size()-1; i>=0;i--)
    {
        finalList.add(tasksAndNotes.get(i));
        //insert finalList;
    }
    tasksAndNotes = finalList; 

    System.debug('after sorting: ' + finalList); 

VisualForce Page

  <apex:column headerValue="Date Activity Logged">
     <apex:variable var="field" value="{!IF(BEGINS(record.Id, '002'), 'CreatedDate', 'Date_Activity_Logged__c')}" />
     <apex:outputField value="{!record[field]}" />
  </apex:column>
6

The default sorting algorithm doesn't work like that. You need to implement Comparable to do what you want. See Sorting Lists of sObjects:

Default Sort Order of sObjects

The List.sort method sorts sObjects in ascending order and compares sObjects using an ordered sequence of steps that specify the labels or fields used. The comparison starts with the first step in the sequence and ends when two sObjects are sorted using specified labels or fields. The following is the comparison sequence used:

  • The label of the sObject type.
    For example, an Account sObject will appear before a Contact.

  • The Name field, if applicable.
    For example, if the list contains two accounts named A and B respectively, account A comes before account B.

  • Standard fields, starting with the fields that come first in alphabetical order, except for the Id and Name fields. For example, if two accounts have the same name, the first standard field used for sorting is AccountNumber.

  • Custom fields, starting with the fields that come first in alphabetical order. For example, suppose two accounts have the same name and identical standard fields, and there are two custom fields, FieldA and FieldB, the value of FieldA is used first for sorting.

Note that the label of the sObject type is applied first.


If you want to do a custom sort, you need to implement Comparable.

Custom Sort Order of sObjects

To implement a custom sort order for sObjects in lists, create a wrapper class for the sObject and implement the Comparable interface. The wrapper class contains the sObject in question and implements the compareTo method, in which you specify the sort logic.

Your wrapper would look something like:

class DateSorter implements Comparable
{
    final SObject record;
    final Datetime value;
    DateSorter(SObject record, SObjectField field)
    {
        this.record = record;
        this.value = (Datetime)record.get(field);
    }
    public Integer compareTo(Object instance)
    {
        DateSorter that = (DateSorter)instance;
        if (this.value == that.value) return 0; // extremely unlikely
        return (this.value < that.value) ? 1 : -1;
    }
}

Then you need to build a List<DateSorter>, sort it, then put the ordered results in your actual List<SObject>.


As for when to return 0, 1, or -1, take a look at Comparable Interface:

Usage
The implementation of this method should return the following values:

0 if this instance and objectToCompareTo are equal
> 0 if this instance is greater than objectToCompareTo
< 0 if this instance is less than objectToCompareTo

Think about this in terms of the list index of a given element. Based on the above example, you can think about it as the relative index of this to that. Here, greater than means a higher list index (later in the list), and less than means a lower index (earlier in the list). So if you want this before that, return a negative index (it goes earlier), and if you want this after that, use a positive index (it goes later). The number doesn't have to be 1, it can be any positive/negative Integer.

  • What happens with the value that is returned? I understand the concept that you are comparing the two IDs/values and then assigning it a 1 or -1. My confusion comes in how to relate this number to sort the list. The documentation on Comparable Interface (developer.salesforce.com/docs/atlas.en-us.apexcode.meta/…) ends the explanation there too. Is it something along the lines of: if the number is a negative we put it at the bottom of the list? – Olivia Jul 25 '16 at 22:06
  • I also want to say thank you for all of your help. You have answered a few on my questions and, as a beginner, it is much appreciated to have someone there. – Olivia Jul 25 '16 at 22:07
  • @Olivia I added some explanation about the compareTo results. – Adrian Larson Jul 26 '16 at 1:05
  • would it be possible to email off this thread? I have taken the advice you have given me but I am not sure if it is possible to compare two different Objects with two different fields. Every which way I try it, I get back an error that Date_Activity_Logged__c is an invalid identifier or type. I am able to compare one Object with two different fields but am struggling with two different Objects. – Olivia Jul 28 '16 at 17:08
  • @Olivia Sure, you actually should have permission to create your own chat rooms, but here's one we can use for this question. – Adrian Larson Jul 28 '16 at 17:10

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.