ADM2 - Sort SmartBrowse by Calculated Field

Posted by Jeff Ledbetter on 08-Mar-2015 18:14

Hi. I have a couple of ideas bouncing around in my brain, but I seem to recall some kind of trick to sorting a SmartBrowse by a calculated field. Has anyone successfully done this? Thanks.

Posted by Håvard Danielsen on 09-Mar-2015 16:38

The ADM2 can have calculated fields in the SmartBrowse or in the SDO.  I don't think it is possible to sort on a calculated field defined in the SmartBrowse as it is is generated as an expression in the browse's DISPLAY statement.  

Unfortunately, it is not supported to sort on a calculated field in the SDO either. This is addressed in issue PSC00261588, which currently is not scheduled. You may call Support and let them know that you need/want this fixed, but be aware that one of the reasons this has not been fixed is that it is very unlikely that we could make it work nicely/seamlessly when batching. But we could fix the SDO to support sort on calculated fields when all the data is on the client.

There are many ways to fix this with code, the simplest is probably to override newQuerySort in the SDO and override the last parameter before the call to super to force it to make the sort local when there is a calculated field as follows.  

function newQuerySort returns character 
  ( input pcQuery as character,
    input pcSort as character,
    input plDBColumns as logical ):
/*------------------------------------------------------------------------------
Purpose: 
 Notes:
------------------------------------------------------------------------------*/
  
  /* This example checks for the calculated column name. This may not be necessary, but there could be some issues 
     if you use a filter or some other action that needs a new server request since the last 
     sort passed through here may be passed to server and it may not be valid on server. So it may be best to 
     limit this to the case that absolutely need it. (this is a theoretical issue and only if your local field has a 
     different name than the db field) */
  if plDbColumns  = true 
  and pcSort begins "Rowobject.calc " 
  /* Ensure that all data is in the SDO. Cannot sort local if we are batching, cannot sort on calc if we are batching */
  and dynamic-function("isDataQueryComplete") then 
       plDbColumns = false.
       
  return super( input pcQuery, input pcSort, input plDBColumns ).

end function. 


 

All Replies

Posted by Håvard Danielsen on 09-Mar-2015 16:38

The ADM2 can have calculated fields in the SmartBrowse or in the SDO.  I don't think it is possible to sort on a calculated field defined in the SmartBrowse as it is is generated as an expression in the browse's DISPLAY statement.  

Unfortunately, it is not supported to sort on a calculated field in the SDO either. This is addressed in issue PSC00261588, which currently is not scheduled. You may call Support and let them know that you need/want this fixed, but be aware that one of the reasons this has not been fixed is that it is very unlikely that we could make it work nicely/seamlessly when batching. But we could fix the SDO to support sort on calculated fields when all the data is on the client.

There are many ways to fix this with code, the simplest is probably to override newQuerySort in the SDO and override the last parameter before the call to super to force it to make the sort local when there is a calculated field as follows.  

function newQuerySort returns character 
  ( input pcQuery as character,
    input pcSort as character,
    input plDBColumns as logical ):
/*------------------------------------------------------------------------------
Purpose: 
 Notes:
------------------------------------------------------------------------------*/
  
  /* This example checks for the calculated column name. This may not be necessary, but there could be some issues 
     if you use a filter or some other action that needs a new server request since the last 
     sort passed through here may be passed to server and it may not be valid on server. So it may be best to 
     limit this to the case that absolutely need it. (this is a theoretical issue and only if your local field has a 
     different name than the db field) */
  if plDbColumns  = true 
  and pcSort begins "Rowobject.calc " 
  /* Ensure that all data is in the SDO. Cannot sort local if we are batching, cannot sort on calc if we are batching */
  and dynamic-function("isDataQueryComplete") then 
       plDbColumns = false.
       
  return super( input pcQuery, input pcSort, input plDBColumns ).

end function. 


 

Posted by Håvard Danielsen on 09-Mar-2015 16:42

Note that reference to "Rowobject.calc  " is assuming a calculated field named calc.  This must be changed to the  name of the calculated field in your case. (The SDO have a method to retrieve the calculated fields if you wanted to write a general fix/workaround)

Posted by Jeff Ledbetter on 09-Mar-2015 16:45

Cook, thanks. We will give that a try. In this case, all the data would have been fetched in a single batch so this may work.
 
Jeff Ledbetter
skype: jeff.ledbetter
 
[collapse]
From: Håvard Danielsen [mailto:bounce-hdaniels@community.progress.com]
Sent: Monday, March 9, 2015 4:39 PM
To: TU.OE.Development@community.progress.com
Subject: RE: [Technical Users - OE Development] ADM2 - Sort SmartBrowse by Calculated Field
 
Reply by Håvard Danielsen

The ADM2 can have calculated fields in the SmartBrowse or in the SDO.  I don't think it is possible to sort on a calculated field defined in the SmartBrowse as it is is generated as an expression in the browse's DISPLAY statement.  

Unfortunately, it is not supported to sort on a calculated field in the SDO either. This is addressed in issue PSC00261588, which currently is not scheduled. You may call Support and let them know that you need/want this fixed, but be aware that one of the reasons this has not been fixed is that it is very unlikely that we could make it work nicely/seamlessly when batching. But we could fix the SDO to support sort on calculated fields when all the data is on the client.

There are many ways to fix this with code, the simplest is probably to override newQuerySort in the SDO and override the last parameter before the call to super to force it to make the sort local when there is a calculated field as follows.  

function newQuerySort returns character 
  ( input pcQuery as character,
    input pcSort as character,
    input plDBColumns as logical ):
/*------------------------------------------------------------------------------
Purpose: 
 Notes:
[/collapse]

Posted by Håvard Danielsen on 11-Mar-2015 10:01

Some more info:

This is only tested in a dynamic browse.

1. The ColumnsSortable property in the browse must be set to true (default is false) before it is initialized to utilize the adm2 sort support.  

2. The SDO must be set up to not batch, (BatchSize= 0  - this is not default)  to be able to sort on calculated fields.

3. It is also necessary to override the browser showSort to make the sort marker show up. This can be done in a custom browser class or  directly in the dynamic adm2/dynbrowser.w rendering procedure.  (keep your own version in an adm2 directory of your own ) as follows:

function showSort returns logical 
  ( /* parameter-definitions */ ):
/*------------------------------------------------------------------------------
 Purpose:
 Notes:
------------------------------------------------------------------------------*/
    define variable lok         as logical no-undo. 
    define variable hDataSource as handle no-undo.
    define variable cSort       as character no-undo.
    define variable cSortColumn as character no-undo.
    define variable lDesc       as logical no-undo.
    define variable hColumn     as handle no-undo.
    define variable iColumn     as integer no-undo.
    define variable cFields     as character no-undo.
    define variable cHandles    as character no-undo.
    
    lok = super( ).
    if not lok then 
    do:
        {get DataObjectHandle hDataSource}.
        if valid-handle(hDataSource) then 
        do:
            {get QuerySort cSort hDataSource}.
            if cSort > "" then
            do on error undo, throw:
                {get DisplayedFields cFields}.
                {get FieldHandles cHandles}.
                assign
                    cSortColumn = entry(1,cSort,'':U)
                    entry(1,cSort,'':U) = '':U 
                    lDesc = left-trim(cSort + ' ':U) begins 'DESCENDING ':U
                    iColumn = lookup(cSortColumn,cFields)
                    hColumn = widget-handle(entry(iColumn,cHandles))
                    hColumn:sort-ascending = not lDesc.
               catch e as Progress.Lang.Error :
                   /* error handling here */		
               end catch.
            end.
        end. 
    end.    
  
end function.


Posted by Jeff Ledbetter on 11-Mar-2015 13:25

Thanks Havard! I think that this will do the trick.

This thread is closed