Ed is quite right.
1: I just did it for simplicity in the example.
2: @SENTENCE, without a wrapper: you have do get ReTrieve to ignore
part of the sentence. I've never come up with a good way to do that
other than via EVAL. Anyone?
3. EVAL: Yes, it is a way to pass run-time parameters!
I tend to forget about it because I - personally - don't like it in
production.
EVAL means dictionaries can't be read-only.
And they tend to permanently leave "temporary" I-descriptors scattered
in the dicts if & when something terminates abnormally.
RetrieVe rudely spits the EVAL compilation report into the output, too.
If you have multiple associated columns, & if your usage gets fancy
(that (future) option is a reason for this approach), then your EVAL may
need ASSOC, ASSOC.WITH, MULTIVALUED keywords, besides AS, FMT, COL.HDG.
Other than that, I love EVAL.
On 7/3/2012 11:08 AM, Ed Clark wrote:
There are 3 ways I can think of offhand to tell the subroutine what date range
to use. I like #3 the best:
1: use common variables, which is what the example function MARKH does. The
downside is that you have to assign the common variables before you run the
query.
2: You could use @SENTENCE in the function and parse out the date range. That
could be easy or hard depending on how many people write queries and what odd
contortions of syntax they use. But both #1 and #2 could be simplified by
writing a wrapper program. An example command line would look like:
QLAUNCH "06/01/2012" "06/30/2012" ~ LIST MYFILE INRANGE
QLAUNCH parses arguments before the '~` delimiter and puts them into a common.
The INRANGE attribute calls the function MARKH which uses the common.
3: use the function directly from the command line with EVAL:
LIST MYFILE EVAL "SUBR('MARKH','06/01/2012','06/30/2012')" AS "MYCOL" COL.HDG
"WHATEVER" FMT "11L"
It's wordier, but you have very fine-grained control over what comes out on the
report. COL.HDG, and FMT are optional and AS is optional in this case. You
would us it if you wanted to sort or break on the EVAL column.
On Jul 3, 2012, at 9:55 AM, Charles Stevenson wrote:
What Brian said, except don't replace LIST!
Rather, write your subroutine to be called from an I-descriptors:
MARKH
0001 FUNCTION MARKH( INARG )
0002 COMMON /MARKH/ START.IDT, END.IDT, PREV.ID, VLIST
0003 *
0004 * Assumes common has been initialized properly before this function
0005 * is called from i-descriptors
0006 *
0007 IF @ID = PREV.ID ELSE
0008 IDTS = @RECORD< 10 >
0009 VLIST = ""
0010 VMC = 0
0011 VMAX = DCOUNT( IDTS, @VM )
0012 FOR V = 1 TO VMAX
0013 IDT = IDTS<1,V>
0014 IF IDT >= START.IDT THEN IF IDT <= END.IDT THEN VLIST<-1> = V
0015 NEXT V
0016 END
0017 *
0018 OUTARG = ""
0019 MORE = LEN( VLIST ) ; * true/false
0020 LOOP WHILE MORE
0021 REMOVE V FROM VLIST SETTING MORE
0022 OUTARG<1,-1> = INARG<1, V >
0023 REPEAT
0024 SETREM 0 ON VLIST
0025 *
0026 RETURN( OUTARG )
0027 END
An example using it is below.
It's more flexible and maintainable in the long run than tossing RETRIEVE
altogether.
(Actually, I do think it can be done with the mv-handling functions but an
I-descriptor subroutine will be more maintainable.)
Your sub should limits the output to the values you want. If every value is out
of range, your subr returns null. It can be called for various associated
fields, and the 1st time called for a given @ID it figures out the value range,
and saves to labeled common what vals you want for that record. Subsequent
calls to the sub, as long as @ID hasn't changed, gets the already calculated
value range from common, and applies it to the field you pass it.
The only trick is feeding your subroutine the date range you won't know until runtime. I don't
know a good way to feed an I-descriptor command line parameters such as ">= 6/1/2012
&<= 6/30/2012"
You'll need to set them in a control record or, better, in @USER1, @USER2, or
in your labeled common before the LIST is executed.
Use the I-descriptors that call your subroutine as output criteria and not WITH
or WHEN selection criteria. The guts of the subr will do the selection limits.
That may not be altogether clear. Here's an example.
1st the relevant dict entries then an example:
DICT RTAG 09:45:22am 03 Jul 2012 Page 1
Field......... Type & Field........ Conversion.. Column......... Output Depth &
Name.......... Field. Definition... Code........ Heading........ Format Assoc..
Number
LOC D 3 12L S
EVENT.CODE D 8 Event 4L M EVENT
.ASSOC
Code
EVENT.DT D 10 D2/ Event 8R M EVENT
.ASSOC
Date
PRINTER D 13 15L S
MARKH.CODE I SUBR( Event 4L M MARKH
'MARKH', .ASSOC
EVENT.CODE )
Code
MARKH.DT I SUBR( D2/ Event 8R M MARKH
'MARKH', .ASSOC
EVENT.DT )
Date
MARKH.ASSOC PH MARKH.LINO
MARKH.CODE
MARKH.REF
MARKH.DT
MARKH.TM
MARKH.WHO
MARKH.DTM
7 records listed.
RUN CDS.BP MARKH.INIT 4/1 4/30
LIST RTAG LOC PRINTER EVENT.CODE EVENT.DT MARKH.CODE MARKH.DT
LIST RTAG LOC PRINTER EVENT.CODE EVENT.DT MARKH.CODE MARKH.DT 09:46:05am 03
Jul 2012 PAGE 1
Return.. LOC......... PRINTER........ Event Event... Event Event...
Tag..... Code. Date.... Code. Date....
5137176 TPAWHSE-IN ZEBRATPA PRINT 02/08/12
NEW 11/04/11
10009741 EROCWHSE-OUT PI 04/26/12 PI 04/26/12
NEW 04/26/12 NEW 04/26/12
5135103 PROCWHSE-DEF REQ 12/30/11
REQ 12/30/11
ASGN 12/30/11
FREE 11/03/11
5134267 EROCDPO-DIN ZEBRATPA I 03/01/12
PRINT 02/08/12
REQ 12/09/11
ASGN 12/09/11
FREE 11/03/11
10010396 DFWWHSE PI 05/22/12
NEW 05/22/12
5119929 SI 04/10/12 SI 04/10/12
NEW 09/20/11
10004562 CROCWHSE-OUT ZEBRAEROC PRINT 04/04/12 PRINT 04/04/12
PRINT 01/31/12
PRINT 01/24/12
PRINT 01/20/12
Press any key to continue...
Finally:
LIST RTAG LOC PRINTER MARKH.CODE MARKH.DT
LIST RTAG LOC PRINTER MARKH.CODE MARKH.DT 09:50:29am 03 Jul 2012 PAGE 1
Return.. LOC......... PRINTER........ Event Event...
Tag..... Code. Date....
5137176 TPAWHSE-IN ZEBRATPA
10009741 EROCWHSE-OUT PI 04/26/12
NEW 04/26/12
5135103 PROCWHSE-DEF
5134267 EROCDPO-DIN ZEBRATPA
10010396 DFWWHSE
5119929 SI 04/10/12
10004562 CROCWHSE-OUT ZEBRAEROC PRINT 04/04/12
Here's the rudimentary common init:
MARKH.INIT
0001 PROGRAM MARKH.INIT
0002 COMMON /MARKH/ START.IDT, END.IDT, PREV.ID, VLIST
0003 GET(ARG.) START.ODT THEN
0004 START.IDT = ICONV( START.ODT, 'D' )
0005 IF STATUS() THEN START.IDT = @DATE
0006 END ELSE
0007 START.IDT = @DATE
0008 END
0009 GET(ARG.) END.ODT THEN
0010 END.IDT = ICONV( END.ODT, 'D' )
0011 IF STATUS() THEN END.IDT = @DATE
0012 END ELSE
0013 END.IDT = @DATE
0014 END
0015 PREV.ID = @IM ; * something impossible.
0016 RETURN
0017 END
On 7/2/2012 10:03 AM, Brian Leach wrote:
Mark
Took me a couple of times reading through the post to understand the issue
..
I think you're going to have to call a subroutine rather than use a LIST.
Brian
_______________________________________________
U2-Users mailing list
U2-Users@listserver.u2ug.org
http://listserver.u2ug.org/mailman/listinfo/u2-users