Sorted array collections are a dynamically sized, sorted collection of components that can be located by indexing. Indexing is always relative to 1.
In this example a form invokes a reusable part that returns a an array collection that has been sorted into the order you requested. The example also uses an employee reusable part which is used to store employee details.
Type in the name of the field on which you want the list sorted and then click the "Get List" Push button to display the sorted list. The fields you can sort by are EMPNO, SURNAME, GIVENAME, POSTCODE, SALARY, and DEPTMENT.
Define the Collection and Adding Items to It
A sorted array collection is defined In the reusable part used to sort the employees. Employee details are retrieved from file PSLMST, #SortedEmployee objects are created based on the #Employee object and assigned the retrieved employee details. The collection is then filled with the #SortedEmployee objects:
Set_Ref Com(#SortedEmployeeList) To(*Create_as #Prim_SACO<#Employee>)
Select Fields(#EMPNO #GIVENAME #SURNAME #DEPTMENT #SALARY #POSTCODE) From_File(PSLMST)
Set_Ref Com(#SortedEmployee) To(*Create_as #Employee)
Set Com(#SortedEmployee) Pempno(#Empno) Pgivename(#GiveName) Psurname(#Surname) Psalary(#Salary) Pdepartment(#Deptment) Ppostcode(#PostCode)
Invoke Method(#SortedEmployeeList.Insert) Item(#SortedEmployee)
Endselect
As every item is added to the collection, the Compare event is triggered. This event is used to provide the logic for sorting the collection. #ObjectEmployee and #SubjectEmployee objects are created to be used as the Object and #Subject parameters to compare the employees:
Evtroutine Handling(#SortedEmployeeList.Compare) Object(#Object) Subject(#Subject) Result(#Result)
Define_Com Class(#Employee) Name(#ObjectEmployee) Reference(*Dynamic)
Define_Com Class(#Employee) Name(#SubjectEmployee) Reference(*Dynamic)
* Cast the object and subject objects to the Employee object
Set_Ref Com(#ObjectEmployee) To(*Dynamic #Object)
Set_Ref Com(#SubjectEmployee) To(*Dynamic #Subject)
* Now compare the objects based on the current #R_OrderBy value
Case Of_Field(#R_ORDERBY)
When Value_Is('= GiveName')
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pGiveName) Subject(#SubjectEmployee.pGiveName) Result(#Result)
When Value_Is('= Surname')
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pSurName) Subject(#SubjectEmployee.pSurName) Result(#Result)
When Value_Is('= Deptment')
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pDepartment) Subject(#SubjectEmployee.pDepartment) Result(#Result)
When Value_Is('= Salary')
Invoke Method(#Com_Owner.CompareNumeric) Object(#ObjectEmployee.pSalary) Subject(#SubjectEmployee.pSalary) Result(#Result)
When Value_Is('= PostCode')
Invoke Method(#Com_Owner.CompareNumeric) Object(#ObjectEmployee.pPostCode) Subject(#SubjectEmployee.pPostCode) Result(#Result)
Otherwise
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pEmpNo) Subject(#SubjectEmployee.pEmpNo) Result(#Result)
Endcase
Endroutine
Retrieve the Items in the Collection
The form retrieves the values in the sorted collection by defining a reference to the employee list and then invoking the method in the reusable part to get the employees.
Define_Com Class(#Prim_SACO<#Employee>) Name(#ReturnedList) Reference(*Dynamic)
Invoke Method(#LCOL00002.GetEmployees) Employeelist(#ReturnedList) Orderby(#Sort_By_Field)
The collection is iterated through to add the entries to the visible #Emp_List:
For Each(#EmployeeObject) In(#ReturnedList)
Change Field(#EMPNO) To('#EMPLOYEEOBJECT.PEMPNO')
Change Field(#GIVENAME) To('#EMPLOYEEOBJECT.PGIVENAME')
Change Field(#SURNAME) To('#EMPLOYEEOBJECT.PSURNAME')
Change Field(#POSTCODE) To('#EMPLOYEEOBJECT.PPOSTCODE')
Change Field(#DEPTMENT) To('#EMPLOYEEOBJECT.PDEPARTMENT')
Change Field(#SALARY) To('#EMPLOYEEOBJECT.PSALARY')
Add_Entry To_List(#EMP_LIST)
Endfor
Source for Sorted Array Collection Example
Employee Object
Create this object as a reusable part. In this example it is named #Employee.
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_OBJT)
* ----------------------------
* This is an "Employee" object
* ----------------------------
* Define the member variables that define an "Employee" object ....
Define_Com Class(#Empno)
Define_Com Class(#GiveName)
Define_Com Class(#SurName)
Define_Com Class(#Deptment)
Define_Com Class(#Salary)
Define_Com Class(#PostCode)
* Publish the properties that an "Employee" exposes .....
Define_Pty Name(pEmpno) Get(*Auto #Empno) Set(*Auto #Empno)
Define_Pty Name(pGiveName) Get(*Auto #GiveName) Set(*Auto #GiveName)
Define_Pty Name(pSurName) Get(*Auto #SurName) Set(*Auto #SurName)
Define_Pty Name(pDepartment) Get(*Auto #Deptment) Set(*Auto #Deptment)
Define_Pty Name(pSalary) Get(*Auto #Salary) Set(*Auto #Salary)
Define_Pty Name(pPostCode) Get(*Auto #PostCode) Set(*Auto #PostCode)
End_Com
Reusable Part For Sorting The List
In this example this component is named #LCOL00002.
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_OBJT)
Define_Com Class(#Prim_SACO<#Employee>) Name(#SortedEmployeeList) Reference(*Dynamic)
Define Field(#R_ORDERBY) Reffld(#STD_TEXTS)
* This method is passed an OrderBy() parameter set to EMPNO, SURNAME, GIVENAME,
* SALARY, DEPTMENT or ZIPCODE. It extracts a list of all employees in the PSLMST
* table and returns their details as a sorted array colelction of employee objects.
Mthroutine Name(GetEmployees)
Define_Map For(*Output) Class(#Prim_SACO<#Employee>) Name(#EmployeeList) Pass(*By_Reference)
Define_Map For(*input) Class(#Std_Texts) Name(#OrderBy)
* Define an Employee object reference
Define_Com Class(#Employee) Name(#SortedEmployee) Reference(*Dynamic)
* Make the requested order by parameter visible to the #SortEmployeeList.Compare routine
Change Field(#R_ORDERBY) To('#ORDERBY.VALUE')
* Dynamically create a new sorted array list to contain the employee objects
Set_Ref Com(#SortedEmployeeList) To(*Create_as #Prim_SACO<#Employee>)
* Fill the sorted array collection list with employee objects
Select Fields(#EMPNO #GIVENAME #SURNAME #DEPTMENT #SALARY #POSTCODE) From_File(PSLMST)
Set_Ref Com(#SortedEmployee) To(*Create_as #Employee)
Set Com(#SortedEmployee) Pempno(#Empno) Pgivename(#GiveName) Psurname(#Surname) Psalary(#Salary) Pdepartment(#Deptment) Ppostcode(#PostCode)
Invoke Method(#SortedEmployeeList.Insert) Item(#SortedEmployee)
Endselect
* Return a refernence to the list that was created
Set_Ref Com(#EmployeeList) To(#SortedEmployeeList)
* Drop the reference in this component as this list is finished with
Set_Ref Com(#SortedEmployeeList) To(*null)
Endroutine
* This routine is invoked to compare the employees in #SortEmployeeList as they are added
* by the GetEmployees method above.
Evtroutine Handling(#SortedEmployeeList.Compare) Object(#Object) Subject(#Subject) Result(#Result)
Define_Com Class(#Employee) Name(#ObjectEmployee) Reference(*Dynamic)
Define_Com Class(#Employee) Name(#SubjectEmployee) Reference(*Dynamic)
* Cast the object and subject objects to the Employee object
Set_Ref Com(#ObjectEmployee) To(*Dynamic #Object)
Set_Ref Com(#SubjectEmployee) To(*Dynamic #Subject)
* Now compare the objects based on the current #R_OrderBy value
Case Of_Field(#R_ORDERBY)
When Value_Is('= GiveName')
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pGiveName) Subject(#SubjectEmployee.pGiveName) Result(#Result)
When Value_Is('= Surname')
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pSurName) Subject(#SubjectEmployee.pSurName) Result(#Result)
When Value_Is('= Deptment')
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pDepartment) Subject(#SubjectEmployee.pDepartment) Result(#Result)
When Value_Is('= Salary')
Invoke Method(#Com_Owner.CompareNumeric) Object(#ObjectEmployee.pSalary) Subject(#SubjectEmployee.pSalary) Result(#Result)
When Value_Is('= PostCode')
Invoke Method(#Com_Owner.CompareNumeric) Object(#ObjectEmployee.pPostCode) Subject(#SubjectEmployee.pPostCode) Result(#Result)
Otherwise
Invoke Method(#Com_Owner.CompareAlpha) Object(#ObjectEmployee.pEmpNo) Subject(#SubjectEmployee.pEmpNo) Result(#Result)
Endcase
Endroutine
* Alpha compare routine
Mthroutine Name(CompareAlpha)
Define_Map For(*input) Class(#Std_TextL) Name(#Object)
Define_Map For(*input) Class(#Std_TextL) Name(#Subject)
Define_Map For(*output) Class(#Std_Texts) Name(#Result)
If Cond('#Subject.Value < #Object.Value')
Set Com(#Result) Value(Less)
Else
If Cond('#Subject.Value > #Object.Value')
Set Com(#Result) Value(Greater)
Else
Set Com(#Result) Value(Equal)
Endif
Endif
Endroutine
* Numeric compare routine
Mthroutine Name(CompareNumeric)
Define_Map For(*input) Class(#dem_dptot) Name(#Object)
Define_Map For(*input) Class(#dem_dptot) Name(#Subject)
Define_Map For(*output) Class(#Std_Texts) Name(#Result)
If Cond('#Subject.Value < #Object.Value')
Set Com(#Result) Value(Less)
Else
If Cond('#Subject.Value > #Object.Value')
Set Com(#Result) Value(Greater)
Else
Set Com(#Result) Value(Equal)
Endif
Endif
Endroutine
End_Com
The Form
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Clientheight(330) Clientwidth(657) Height(357) Left(219) Top(173) Visualstyle(#VS_NORM) Width(665)
* Define the component that returns the sorted employee number list
Define_Com Class(#PRIM_LTVW) Name(#Emp_LIst) Componentversion(1) Displayposition(1) Fullrowselect(True) Height(233) Left(27) Parent(#COM_OWNER) Showsortarrow(True) Tabposition(1) Top(72) Width(606)
Define_Com Class(#PRIM_LVCL) Name(#LVCL_1) Displayposition(1) Parent(#Emp_LIst) Source(#EMPNO) Width(12)
Define_Com Class(#PRIM_LVCL) Name(#LVCL_2) Displayposition(2) Parent(#Emp_LIst) Source(#SURNAME) Width(20)
Define_Com Class(#PRIM_LVCL) Name(#LVCL_3) Displayposition(3) Parent(#Emp_LIst) Source(#GIVENAME) Width(20)
Define_Com Class(#PRIM_LVCL) Name(#LVCL_4) Displayposition(4) Parent(#Emp_LIst) Source(#POSTCODE) Width(20)
Define_Com Class(#PRIM_LVCL) Name(#LVCL_5) Displayposition(5) Parent(#Emp_LIst) Source(#SALARY) Width(20)
Define_Com Class(#PRIM_LVCL) Name(#LVCL_6) Displayposition(6) Parent(#Emp_LIst) Source(#DEPTMENT) Width(20) Widthtype(Remainder)
Define_Com Class(#STD_OBJ.Visual) Name(#Sort_By_Field) Caption('Get List Sorted by Field Named') Displayposition(2) Height(19) Labeltype(Caption) Left(24) Parent(#COM_OWNER) Tabposition(2) Top(24) Width(233)
Define_Com Class(#PRIM_PHBN) Name(#PHBN_Get_List) Caption('Get List') Displayposition(3) Left(272) Parent(#COM_OWNER) Tabposition(3) Top(24)
* Define the component that builds the sorted employee lists
* (in this example it is called #LCOL00002, change it to the name you have
* given to the reusable part)
Define_Com Class(#LCOL00002)
* Handle form initialization
Evtroutine Handling(#com_owner.Initialize)
Set Com(#Sort_By_Field) Value(SALARY)
Endroutine
Evtroutine Handling(#PHBN_Get_List.Click)
* Define a reference to the employee list that will be returned
Define_Com Class(#Prim_SACO<#Employee>) Name(#ReturnedList) Reference(*Dynamic)
* Invoke the method that returns the sorted list of employees
Invoke Method(#LCOL00002.GetEmployees) Employeelist(#ReturnedList) Orderby(#Sort_By_Field)
* Now go through the returned list and add the entries to the visible #Emp_List
Clr_List Named(#EMP_LIST)
For Each(#EmployeeObject) In(#ReturnedList)
Change Field(#EMPNO) To('#EMPLOYEEOBJECT.PEMPNO')
Change Field(#GIVENAME) To('#EMPLOYEEOBJECT.PGIVENAME')
Change Field(#SURNAME) To('#EMPLOYEEOBJECT.PSURNAME')
Change Field(#POSTCODE) To('#EMPLOYEEOBJECT.PPOSTCODE')
Change Field(#DEPTMENT) To('#EMPLOYEEOBJECT.PDEPARTMENT')
Change Field(#SALARY) To('#EMPLOYEEOBJECT.PSALARY')
Add_Entry To_List(#EMP_LIST)
Endfor
Endroutine
End_Com