You are on page 1of 6

Build an enquiry with a Nofile

When you can't use standard conversion and calculation functions to get what you need, you still
have a programming solution. It occurs typically when you need data spreaded in multiple tables,
because ENQUIRY tool is single-table by essence. You can use links to other tables when you
have foreign keys in the requested table, but no more. Using a subroutine, you access to any kind
and number of extra tables.

The concept is:


1. Drive the enquiry to a virtual table called a NOFILE and named NOFILE.xxx depending on
the business context.
2. Declare a call of a subroutine in one field of this NOFILE.xxx, through its dictionary
(STANDARD.SELECTION).
3. The subroutine will select all needed data and broadcast it through a huge return field that
incudes delimiters.
4. In the ENQUIRY, you get all needed data by extracting values between each delimiter.

Example :

1. ENQUIRY

ENQUIRY........... DX.CLOSEOUT.FINAL.FUT.HIS

1 PAGE.SIZE ........ 4,19


2 FILE.NAME......... NOFILE.DX.CLOSEOUT

2. STANDARD SELECTION

FILE.NAME......... NOFILE.DX.CLOSEOUT

15. 1 USR.FIELD.NAME. RET.ID


16. 1 USR.TYPE....... D
17. 1. 1 USR.FIELD.NO 0
20. 1 USR.DISPLAY.FMT 1000L
24. 1 USR.SINGLE.MULT S
25. 1 USR.LANG.FIELD. N
15. 2 USR.FIELD.NAME. RTN.CALL
16. 2 USR.TYPE....... R
17. 2. 1 USR.FIELD.NO E.NOFILE.DX.CLOSEOUT
20. 2 USR.DISPLAY.FMT 10L
24. 2 USR.SINGLE.MULT S
25. 2 USR.LANG.FIELD. N

3. SUBROUTINE E.NOFILE.DX.CLOSEOUT(RETURN.ARRAY)
(...)
TEMP.DATA = POS.KEY : "*" : POS.DATE : "*" : POS.CONTRACT : "*" :
POS.MATURITY : "*" : POS.CURR : "*" etc...
RETURN.ARRAY<-1> = TEMP.DATA

4. ENQUIRY

ENQUIRY........... DX.CLOSEOUT.FINAL.FUT.HIS
---------------------------------------------------
1 PAGE.SIZE ........ 4,19
2 FILE.NAME......... NOFILE.DX.CLOSEOUT
3. 1 FIXED.SELECTION RTN.CALL NE NULL
11. 1 FIELD.NAME..... RET.ID
12. 1. 1 OPERATION... RET.ID
14. 1 LENGTH.MASK.... 1000L
32. 1 SINGLE.MULTI... S
11. 2 FIELD.NAME..... POS.KEY
12. 2. 1 OPERATION... F RET.ID
13. 2 COLUMN......... 1
15. 2. 1 CONVERSION.. F *,1,1
19. 2. 1 GB FIELD.LBL Key
32. 2 SINGLE.MULTI... S
11. 3 FIELD.NAME..... POS.DATE
12. 3. 1 OPERATION... F RET.ID
15. 3. 1 CONVERSION.. F *,2,1

top

Selection fields in an enquiry targeting a Nofile


If you need to give users the ability to filter the enquiry results, you must declare selection fields
in the SS and take them in consideration in the subroutine.
Inside the routine, by adding the library for enquiries (I_ENQUIRY.COMMON), you will be
able to process selection fields with following common variables:
D.FIELDS : contains the selection fields separated by a FM
D.LOGICAL.OPERANDS : contains selection operators using following equivalences:

1 = EQ
2 = RG
3 = LT
4 = GT
5 = NE
6 = LK
7 = UL
8 = LE
9 = GE
10 = NR
D.RANGE.AND.VALUE : contains values of selection input by the user.

Detailed explanations :

1) Declare selection fields in the Standard Selection of the NOFILE.


15. 3 USR.FIELD.NAME. SELECTION.FIELD.1
16. 3 USR.TYPE....... S
18. 3. 1 USR.VAL.PROG IN2D
20. 3 USR.DISPLAY.FMT 12L

Then in the routine called by the NOFILE:


2) Add the library I_ENQUIRY.COMMON

3) Process selection fields specified by end-user

Y.SEL.CRITERIA = ''
Y.FIELD = 'SELECTION.FIELD.1'
GOSUB BUILD.CRITERIA.CMD
Y.FIELD = 'SELECTION.FIELD.2'
GOSUB BUILD.CRITERIA.CMD
Y.FIELD = 'SELECTION.FIELD.3'
GOSUB BUILD.CRITERIA.CMD

Y.SORT.CONDITION = 'BY WHATEVER'

4) BUILD.CRITERIA.CMD:

LOCATE Y.FIELD IN D.FIELDS<1> SETTING POS ELSE RETURN

Y.OPERAND = D.LOGICAL.OPERANDS<POS>
Y.RANGE.AND.VALUE = D.RANGE.AND.VALUE<POS>

Y.I = 0

BEGIN CASE
CASE Y.OPERAND = 1 ; * EQual to ALL.
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' EQ'
LOOP
Y.I += 1
Y.X = Y.RANGE.AND.VALUE<1,1,Y.I>
WHILE Y.X
Y.SEL.CRITERIA := ' ':Y.X
REPEAT
CASE Y.OPERAND = 2 ; * RanGe
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' GE ':Y.RANGE.AND.VALUE<1,1,1>
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' LE ':Y.RANGE.AND.VALUE<1,1,2>
CASE Y.OPERAND = 3 ; * Less Than
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' LT ':Y.RANGE.AND.VALUE<1,1>
CASE Y.OPERAND = 4 ; * Greater Than
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' GT ':Y.RANGE.AND.VALUE<1,1>
CASE Y.OPERAND = 5 ; * Not Equal to
LOOP
Y.I += 1
Y.X = Y.RANGE.AND.VALUE<1,1,Y.I>
WHILE Y.X
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' NE ':Y.X
REPEAT
CASE Y.OPERAND = 6 ; * LiKe
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' LIKE'
LOOP
Y.I += 1
Y.X = Y.RANGE.AND.VALUE<1,1,Y.I>
WHILE Y.X
Y.SEL.CRITERIA := ' ':Y.X
REPEAT
CASE Y.OPERAND = 7 ; * UnLike
LOOP
Y.I += 1
Y.X = Y.RANGE.AND.VALUE<1,1,Y.I>
WHILE Y.X
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' UNLIKE ':Y.X
REPEAT
CASE Y.OPERAND = 8 ; * Less than or Equal
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' LE ':Y.RANGE.AND.VALUE<1,1>
CASE Y.OPERAND = 9 ; * Greater than or Equal
Y.SEL.CRITERIA := ' AND ':Y.FIELD:' GE ':Y.RANGE.AND.VALUE<1,1>
CASE Y.OPERAND = 10
Y.SEL.CRITERIA := ' AND (':Y.FIELD:' LT ':Y.RANGE.AND.VALUE<1,1,1>
Y.SEL.CRITERIA := ' OR ':Y.FIELD:' GT ':Y.RANGE.AND.VALUE<1,1,2>:')'
*
END CASE

RETURN

5) Then add the selection fields in the SELECT command

SEL.CMD = 'SELECT ' : FN.TARGET.FIELD.NAME : ' WITH @ID NE "" '


SEL.CMD := ' ':Y.SEL.CRITERIA
SEL.CMD := ' ':Y.SORT.CONDITION

That's all folks. top

Compute a difference between two dates


You have first to convert the two dates to be compared to the julian format.

11.19 FIELD.NAME..... LAST.TRADE


12.19. 1 OPERATION... IDESC LAST.TRADE
14.19 LENGTH.MASK.... 12L
15.19. 1 CONVERSION.. JULIAN

11.20 FIELD.NAME..... COMPANY


12.20. 1 OPERATION... PORTFOLIO
14.20 LENGTH.MASK.... 18L
15.20. 1 CONVERSION.. L SEC.ACC.MASTER,CO.CODE
32.20 SINGLE.MULTI... S

11.21 FIELD.NAME..... TODAY


12.21. 1 OPERATION... F COMPANY
15.21. 1 CONVERSION.. L DATES,TODAY
15.21. 2 CONVERSION.. JULIAN

11.22 FIELD.NAME..... DAYS.TO.MAT


12.22. 1 OPERATION... C LAST.TRADE - TODAY
13.22 COLUMN......... 7
19.22. 1 GB FIELD.LBL Days to Mat.
32.22 SINGLE.MULTI... S

top

Example of date formatting

12. 3. 1 OPERATION... DATE.TIME


13. 3 COLUMN......... 35
14. 3 LENGTH.MASK.... 10L
15. 3. 1 CONVERSION.. E 1,6
15. 3. 2 CONVERSION.. I D
15. 3. 3 CONVERSION.. O D2/E

top

Display very first inputter of a record

12. 7. 1 OPERATION... INPUTTER


13. 7 COLUMN......... 52
14. 7 LENGTH.MASK.... 28L
15. 7. 1 CONVERSION.. V 1
15. 7. 2 CONVERSION.. F _,2

top
Call a subroutine
Usage description:
You can call a subroutine from an enquiry field. You have to invoke it using @
E.Subroutine.Name in the Conversion field. The argument to be processed by the enquiry must
be set in the Operation field. Inside the subroutine, the argument will be transmitted in a
dedicated variable named O.DATA. This is defined in the I_ENQUIRY.COMMON library.

Example :

We are displaying an historical transaction ID in an enquiry. We need to get the latest trans ID if
exists.

In the enquiry, it will give:

11.16 FIELD.NAME..... LATEST.TRANS


12.16. 1 OPERATION... F TRANS.ID
13.16 COLUMN......... 12
14.16 LENGTH.MASK.... 20L
15.16. 1 CONVERSION.. @ E.DX.GET.LATEST.TRANS

In the subroutine, it will give:

SUBROUTINE E.DX.GET.LATEST.TRANS

$INSERT I_COMMON
$INSERT I_EQUATE
$INSERT I_ENQUIRY.COMMON

IN.R.DX.TRANS.KEYS = ""
IN.DX.TRADE.ID = FIELD(O.DATA,".",1)
IN.CUST.PORT = FIELD(O.DATA,".",2)
IF (IN.CUST.PORT # "") THEN
CALL DX.GET.LATEST.TRANSACTION.ID( IN.R.DX.TRANS.KEYS, IN.DX.TRADE.ID,
IN.CUST.PORT, LAST.TXN.ID)
O.DATA = LAST.TXN.ID
END
RETURN
END

You might also like