Re: WHADDAYMEANYOUCAN'TDOTHAT? Input Array Made Useable
Posted in 1992
OOPS I've had to revise a bit of my statements from yesterday here.. SORRY.. Several months ago I lamblasted input array see subject line "What Do Disney Land, Disney World, And Input Array Have In Common?" "They're all Mickey Mouse Operations" Anyways at the time I had devised a "sneak around" that worked but was awaiting heavy user interaction to be sure I didn't overlook something. I'm happy to say IT SURVIVED THE USERS!!! So now I have the guts to post. The fact that I'm leaving this site (and thereby losing net access has NOTHING to do with it) I'll be outta here after this Fri... If the tone of the notes below seems somewhat pre-skool keep in mind I wrote these notes for my own future reference so thats the "pre-skooler" they are aimed at.... Anyways, heres 2 ways to have conditional inserts/deletes in an INPUT ARRAY Method 1 is the "Informix Approved" one Method 2 is my own madness at work. :-) ----------------------- cut here ------------------------------------------ It seems to be a frequently desired situation to be able to handle conditional DELETE/INSERT (s) within INPUT ARRAY. Of course the capabilities of INPUT ARRAY seem inherently brain-dead, and the task just doesn't seem woth the effort or worse yet not doable.. Well it CAN be done using one (or both) of the methods below.. THINGS TO KEEP IN MIND... An INPUT statement is handled as a "loop" and that a NEXT FIELD acts as an EXPLICIT GOTO within the loop. INPUT also REDISPLAYS the data. In the case of an INPUT ARRAY the cursor will start at the FIRST ROW. *ALWAYS* INPUT ARRAY ONLY controls the rows WITHIN THE CONFINES OF ITS OWN INTERNAL COUNTER. You initialize this counter by calling SET_COUNT() with a numeric value just prior to the INPUT ARRAY stmt. This coun- ter is now LINKED to THAT PROCESS ALONE and can only be incremented/ decremented by some of the "magic" Informix has built into INPUT ARRAY. This is desired as it allows one to open a window from a row in an array and select a validation value from a row from annother array. The DELETE KEY EXPLICITLY decrements the counter. There is NO way to avoid this The INSERT KEY EXPLICITLY increments the counter There is NO way to avoid this ANY rows OUTSIDE the "boundary" of the counter used by the current iteration of INPUT ARRAY is T-R-A-S-H. ALSO the Informix internals does an evaluation upon leaving a row, something like.. IF ARR_CURR() = ARR_COUNT() AND keyval NOT IN "UP | LEFT" THEN LET COUNTER_INTERNAL = COUNTER_INTERNAL + 1 END IF The last item IS CRITICAL to note for solution number two.... Infomix has a tech note on the matter which utilizes a NOENTRY field as the last field on a row in the form. BY DEFAULT when a NEXT FIELD is invoked IF you are in the LAST FIELD on a row (or the last field is NOENTRY) the cursor will DROP down to the row below. Their solution then is to let a variable = ARR_CURR() EXIT the INPUT RESTART INPUT and then using the LOOPING action of the INPUT stmt and the GOTO quality of NEXT FIELD (the non enterable field) drop down to the line that was exited from. The screen will scroll and there is a brief (but noticable) pause as this process begins.. WHATEVER CONDITION SPECIFIED TO ABORT DELETION LET nxtline = arr_curr() EXIT INPUT BEFORE ROW LET cur_line = ARR_CURR() IF nxtline > cur_line THEN NEXT FIELD noentryfield END IF LET nxtline = NULL The above statement works because of the "looping" action of an input stmt, and the NEXT FIELD "goto" quality. The NEXT FIELD causes a new loop of BEFORE ROW and nxtline does NOT get set to NULL until the test nxtline > cur_line FAILS. I've used this syntax to have NEXTPAGE put the user on the first blank row at the END of the data.. ON KEY (NEXTPAGE, Fwhatever, CONTROL-whatever) IF pa_array[cur_line].colval IS NOT NULL THEN CALL count_em() RETURNING arr_size # counts NON NULL rows LET nu_line = arr_size + 1 LET dropflag = TRUE NEXT FIELD "noentryfield" ELSE ERROR "There are no more rows in the direction you are going" END IF The NEXT FIELD STARTS the before row process to roll BEFORE ROW LET cur_ine = ARR_CURR() IF dropflag THEN IF cur_line < nu_line THEN NEXT FIELD noentryfield END IF END IF LET dropflag = FALSE THe above syntax works, it does however have a small performance lag, and lets face it, there are some arrays where you don't have room to add the extra field soo here then is a solution that works WITHIN THE CURRENT ITERATION OF INPUT ARRAY.. It requires A FUNCTION to count NON NULL ROWS as a matter of course I NEVER allow a user to leave a blank row downward to enter data. If they leave the row UP into populated rows let em, otherwise exit input. IF pa_array[cur_line].colval IS NULL THEN IF fgl_lastkey() != fgl_keyval("UP") (EFLASTKEY != 2000 on pre 4.1 versions) THEN EXIT INPUT END IF END IF A backup array A FUNCTION to LET work_array[i].* = backup_array[i].* A FUNCTION to LET backup_array[i].* = work_array[i].* A FUNCTION to redisplay data from scr_line() to "X" When SET_COUNT() is called "pad" the figure Ie: we have 12 rows of data and I'll allow the user 6 aborted delete attempts so I'll call SET_COUNT(12 + 6) THis tells the iteration of INPUT ARRAY it has 18 rows By counting the aborted deletion attempts and not letting them exceed the "pad" figure all rows will remain within control of the INPUT ARRAY statement.. BEFORE DELETE IF abt_flag > 5 THEN EXIT INPUT ELSE LET line_left = arr_curr() # load pa_array[line_left].* into a delete record for deletion # from database after delete (logic permitting) IF { abort logic = TRUE } LET del_flag = TRUE ELSE LET del_flag = FALSE END IF AFTER DELETE IF del_flag THEN # perform delete based on paramaters analysed in # the delete function CALL delt_notes(line_left, bu_line_num) # This function should delete the record stored in the # delete record. In the case of the function call above # I had a sequential counter associated with each row in # the array that was stored in the database so I HAD to # delete from delrec, and then delete ALL from "line_left" # to end of the array, renumber, reinsert, and redisplay. # Set backup array current to working array CALL bkup_notes() # recount