Template for generating column equates for ABC browse

Tags: #<Tag:0x00007f31d151a4f0> #<Tag:0x00007f31d151a338>

Instead of using hard-coded numeric constants for column numbers in code for manipulating your list control columns, it is better to use an equate for the column number.
Hard-coded column numbers can become incorrect when new columns are added or columns deleted or reordered in the list format.
I have uploaded a small example template that automatically generates equates for the columns in your list control. Using the use equates means your code won’t need to be updated when the order of your list control columns change.
So instead of coding something like this:

IF BRW1.ILC.GetControl(){Prop:Column} = 3
  !! do something
END

instead use

IF BRW1.ILC.GetControl(){Prop:Column} = BRW1:FieldNo:CUS:LastName
  !! do something
END

You can get the template code on GitHub:

4 Likes

A Clarion limitation of PROP and PROPLIST is you cannot get to the #FIELD() or FROM(Q) at runtime. A template like yours could generate User Defined properties (added 10/27/2015 in C10.11975) with that information. E.g. given this LIST:

LIST,AT(9,7,668,179),USE(?BrowseEmpTypes),FROM(Queue:Browse)
#FIELDS(TYP:Code,TYP:Desc,TYP:NormalHrsPerDay,TYP:CertifiedPersonnel,TeacherSub,TYP:TrsJobCategory)

Template can generate these properties

?BrowseEmpTypes{'#Field',1}='TYP:Code'
?BrowseEmpTypes{'#Field',2}='TYP:Desc'
?BrowseEmpTypes{'#Field',3}='TYP:NormalHrsPerDay'
?BrowseEmpTypes{'#Field',4}='TYP:CertifiedPersonnel'
?BrowseEmpTypes{'#Field',5}='TeacherSub'
?BrowseEmpTypes{'#Field',6}='TYP:TrsJobCategory'

?BrowseEmpTypes{'#FldUse',1}=Address(TYP:Code)
?BrowseEmpTypes{'#FldUse',2}=Address(TYP:Desc)
?BrowseEmpTypes{'#FldUse',3}=Address(TYP:NormalHrsPerDay)
?BrowseEmpTypes{'#FldUse',4}=Address(TYP:CertifiedPersonnel)
?BrowseEmpTypes{'#FldUse',5}=Address(TeacherSub)
?BrowseEmpTypes{'#FldUse',6}=Address(TYP:TrsJobCategory)

?BrowseEmpTypes{'#From'}='Queue:Browse'
?BrowseEmpTypes{'#FromUse'}=Address(Queue:Browse)

Might need to know the Parents:

?BrowseEmpTypes{'#FieldParent',3}='TYP:Record'
?BrowseEmpTypes{'#FldParentUse',3}=ADDRESS(TYP:Record)

I tested the above code showing a message:

 Message(?BrowseEmpTypes{'#Field',4} &'<9>'&  ?BrowseEmpTypes{'#FldUse',4} & |
         '||'&?BrowseEmpTypes{'#From'} &'<9>'&  ?BrowseEmpTypes{'#FromUse'} ) 

The UDFs are nice because the scope is for any code that can see the Window so beyond the main any Routines and Classes. If we can agree on the {‘Names’} then any template or class code can use them. A name of {"#FIELD"} seems obvious and logical. I think we need the USE Address to be able to assign an ANY and operate on the variable.

So just an idea…

1 Like

Similar to Bruce’s NAME() attribute thread.

I remember back in the 90s, there was talk on the CI$ forum about creating an EVENT repository, but managing 3rd Party folks is like herding kittens. :slight_smile:

FWIW,on a semi-related note,
I use WHERE() when writing hand coded PROP:Formats

For example (scroll to the right in the source below)

SELF.ListFEQ{PROP:Format} =                                                                                                     |         
                '11L'     &  'FIY' &                                 '@[email protected]' & '#' & WHERE(SELF.Q, SELF.Q.Tag          ) & '#' |
        &       '20C'     & '|Y'  & '~Area~'              & 'L'    & '@[email protected]?'  & '#' & WHERE(SELF.Q, SELF.Q.Wall_Area    ) & '#' |
        &       '37C'     & '|IY' & '~Shape~'             &          '@[email protected]'   & '#' & WHERE(SELF.Q, SELF.Q.Shape        ) & '#' |
        &       '145L(1)' & '|FY' & '~Wall Description~'  & 'C(0)' & '@[email protected]'  & '#' & WHERE(SELF.Q, SELF.Q.Description  ) & '#' |
        & '[' &  '5C'     &  '*Y'                                  & '@[email protected]'   & '#' & WHERE(SELF.Q, SELF.Q.Out_BoxTrans ) & '#' |
        &       '47L(1)'  & '|Y'  & '~Outside~'           & 'L(0)' & '@[email protected]'  & '#' & WHERE(SELF.Q, SELF.Q.Outside      ) & '#' |
        & ']'             & '|'                                                                                           &     |
        & '[' &  '5C'     &  '*Y'                                  & '@[email protected]'   & '#' & WHERE(SELF.Q, SELF.Q.In_BoxTrans  ) & '#' |
        &       '47L(1)'  & '|Y'  & '~Inside~'            & 'L(0)' & '@[email protected]'  & '#' & WHERE(SELF.Q, SELF.Q.Inside       ) & '#'

I like that a lot for flexibility in designing Q versus List.

Too bad the ## has to be numeric. An idea for you to use the LIST formatter would be to stick your #Where()# code into the Default Tip then in your final code change the Q’‘xxx’’ to #xxx#. But… the Q’’ currently breaks the window previewer, it stops generating Q fields. I have reported to SV.

 FORMAT('21C|M~Code~L(3)@[email protected]''WHERE(SELF.Q, SELF.Q.Tag)''' &|
        '140L(3)|~Employee Type~L(4)@[email protected]''WHERE(SELF.Q, SELF.Q.Wall_Area)'''     &|
        '27R(3)|*~Normal<0DH,0AH>Hours~C(0)@[email protected]''WHERE(SELF.Q, SELF.Q.Shape)''' &|

After S&R :

 FORMAT('21C|M~Code~L(3)@[email protected]#'& WHERE(SELF.Q, SELF.Q.Tag) &'#' &|
        '140L(3)|~Employee Type~L(4)@[email protected]#'& WHERE(SELF.Q, SELF.Q.Wall_Area) &'#'     &|
        '27R(3)|*~Normal<0DH,0AH>Hours~C(0)@[email protected]#'& WHERE(SELF.Q, SELF.Q.Shape) &'#' &|
        '29C|[email protected]@'                               &|

Seems more logical to use PROPList:FieldNo rather than mess around with the FORMAT string like that.