Re: record verification in INPUT ARRAY
Posted in 1994
andrewm@ccfadm.eeg.ccf.org (Martin Andrews) writes: >I have tried to avoid the awkward INPUT ARRAY statement, but >I find that I have to wrangle with it again. Does anyone know >a way to verify the consistency of the values in a row when the >user exits the row? After row would seem the appropriate clause, >except that I can't seem to force the cursor back to the row if >the verification fails. I can verify in the after field clauses, >but then I have to check the last key pressed to determine if the >user is about to exit the row (and the keys that will cause an exit >vary depending on the current field). There must be an easier way, >yes? (Or will this turn into another 4GL bashing thread?) INPUT ARRAY is only awkward until you've played with it awhile, and there are a couple bugs and lacking features one has to work around. You're on the right track, testing for rows in the AFTER ROW statetment, and just need a way to get back to the row you were just on. Here's a short article I posted awhile back that addresses this and other INPUT ARRAY issues: Emulating "NEXT ROW" syntax in INPUT ARRAY until version 5.0. 1) Create a screen record in which the last field in a NOENTRY field. This field can be one that actually stores data for display or a CHAR(1) designed just for this purpose. Remember that the last field in the screen record doesn't have to be the right-most field on the screen, but it usually is SCREEN { [a ][b ][c ][n] ... } ATTRIBUTES a = ... b = ... c = ... n = FORMONLY.ne TYPE CHAR, NOENTRY; INSTRUCTIONS ... SCREEN RECORD s_array[##] (...,FORMONLY.ne) END 2) Define your array with the last field that matches the NOENTRY in the screen record: DEFINE ma_array ARRAY[##] OF RECORD ... ne CHAR(1) END RECORD ... 3) In your INPUT ARRAY function, you need counters for arr_curr, scr_line, arr_count, and one to mark if we want to jump rows: DEFINE arr SMALLINT DEFINE scr SMALLINT DEFINE act SMALLINT DEFINE arrg SMALLINT 4) We surround the entire INPUT ARRAY with a WHILE loop, because the trick to moving backward is to mark the row to go to, then exit the input and loop back around to begin input again. LET arrg = 1 LET act = number of rows filled in the array already WHILE arrg > 0 CALL set_count(act) INPUT ARRAY ma_array WITHOUT DEFAULTS FROM s_array.* BEFORE ROW LET arr = arr_curr() LET scr = scr_line() IF arrg > arr THEN # this means we want to go to a row below us in the # array, so NEXT FIELD the NOENTRY field, which means # jump to the next row NEXT FIELD ne END IF # reset arrg to 0 if we get to this point, which allows # us to leave the WHILE loop around the INPUT ARRAY if # the user hits the ACCEPT or INTERRUPT key LET arrg = 0 ... AFTER ROW # I have found that AFTER ROW is the best place to track # the last filled in row. LET act = arr_count() ... # below is an example of how we can implement a function key # to act as a HOME key. When the user types the function key # designated as HOME, the cursor will move to array row 1 ON KEY (F##) LET arrg = 1 EXIT INPUT ... # below is an example of how we can implement a function key # to act as an END key. When the user types the function key # designated as END, the cursor will move to the last filled # in row. ON KEY (F##) IF arr < act THEN # if we're not on the last row now, go there LET arrg = act NEXT FIELD ne END IF ... END INPUT # in case we're looping we need to track arr_count here # because an EXIT INPUT call avoids the AFTER ROW block LET act = arr_count() END WHILE IF int_flag THEN ... The only drawback to this approach is that for very large arrays the looping can take some time. But for arrays that are 50 rows or less, this is suitable. BUG #11364 WORK AROUND The only problem, now, is that with version 4.10 there is a bug that causes exiting from an AUTONEXT field into the NOENTRY field (and thus to the next row) to put the cursor into an infinite loop. This bug (#11364) is scheduled for a fix in version 4.10.UE1, which is currently shipping on some platforms. If you can't get the fixed version, there are two approaches to fixing the problem. The first approach is to remove the AUTONEXT from the field just before the NOENTRY field. This is the simplest, and thus recommended, approach. If your user can't live with hitting the RETURN key after this field, though, you can use some of the new 4.10 library functions as a work around: ... AFTER FIELD before_ne IF fgl_lastkey() = fgl_keyval("autonext") THEN IF arr < maximum array size THEN # go to the next row, avoiding bug 11364 LET arrg = arr + 1 ELSE # we're on the last row already, loop back to the top LET arrg = 1 END IF EXIT INPUT END IF ... "before_ne" in the example above is the name of the AUTONEXT field that is listed just before the NOENTRY field in the screen record, and "maximum array size" is the size of array ma_array. This work around has the same problem as the jumping solution in that for very large arrays a lot of screen repainting is done to get back down to the desired row. ============================================================ Dennis J. Pimple Informix Software Inc Senior Consultant Denver Colorado USA dennisp@informix.com Voice:303-850-0210 Fax:303-779-4025