The following example shows how you can use keyed collections to perform error checking for grids where the user may update multiple records at once. It also demonstrates the correct use of nested BEGINCHECK/ENDCHECK blocks to provide visual feedback for fields which fail validation rules.
Note that nested BEGINCHECK/ENDCHECK blocks are used because updating a grid in this way is similar to validating multiple details input via a browse list on IBM i.
* COMPONENT: STD_FORM
Function Options(*DIRECT)
Begin_Com Role(*EXTENDS #PRIM_FORM) Clientheight(221) Clientwidth(492) Height(255) Left(335) Top(106)
Define_Com Class(#PRIM_GRID) Name(#GRID_1) Captionnoblanklines(True) Columnbuttonheight(29) Columnscroll(False) Componentversion(1) Displayposition(1) Height(193) Left(0) Parent(#COM_OWNER) Showbuttonselection(True) Showselection(True) Showselectionhilight(False) Showsortarrow(True) Tabposition(1) Top(0) Visualstyle(#VS_NORM) Width(401)
Define_Com Class(#PRIM_GDCL) Name(#GDCL_1) Caption('Empno') Captiontype(Caption) Displayposition(1) Parent(#GRID_1) Source(#EMPNO) Width(15)
Define_Com Class(#PRIM_GDCL) Name(#GDCL_2) Caption('Surname') Captiontype(Caption) Displayposition(2) Parent(#GRID_1) Source(#SURNAME) Width(29)
Define_Com Class(#PRIM_GDCL) Name(#GDCL_3) Caption('Zip') Captiontype(Caption) Columnalign(Right) Displayposition(3) Parent(#GRID_1) Readonly(False) Source(#POSTCODE) Width(14)
Define_Com Class(#PRIM_GDCL) Name(#GDCL_4) Columnalign(Right) Displayposition(4) Parent(#GRID_1) Source(#SALARY) Widthtype(Remainder)
Define_Com Class(#PRIM_PHBN) Name(#PHBN_1) Caption('&Refresh ') Displayposition(2) Left(408) Parent(#COM_OWNER) Tabposition(2) Top(8)
Define_Com Class(#PRIM_STBR) Name(#STBR_1) Displayposition(3) Height(24) Left(0) Messageposition(1) Parent(#COM_OWNER) Tabposition(3) Tabstop(False) Top(197) Width(492)
Define_Com Class(#PRIM_PHBN) Name(#PHBN_upd) Caption('&Update ') Displayposition(4) Left(408) Parent(#COM_OWNER) Tabposition(4) Top(40)
*
Define_Com Class(#prim_kcol<#postcode #empno>) Name(#postcodes)
Define_Com Class(#prim_kcol<#salary #empno>) Name(#salaries)
*
Evtroutine Handling(#PHBN_1.Click)
* Clear Collections as well as grid
#postcodes.RemoveAll
#salaries.RemoveAll
Clr_List Named(#grid_1)
Select Fields(#grid_1) From_File(pslmst)
#postcodes<#empno> := #postcode
#salaries<#empno> := #salary
Add_Entry To_List(#grid_1)
Endselect
Endroutine
*
Evtroutine Handling(#PHBN_upd.Click)
* Check the input data
Begincheck
Selectlist Named(#GRID_1)
Continue If(#Com_owner.HasNotChanged)
Begincheck
Update Fields(#salary #postcode) In_File(pslmst) With_Key(#empno) Io_Error(*NEXT) Val_Error(*NEXT) Check_Only(*yes)
If_Status Is_Not(*okay)
#grid_1.currentitem.Visualstyle <= #vs_emph
Else
#grid_1.currentitem.Visualstyle <= #vs_norm
Endif
Upd_Entry In_List(#GRID_1)
Endcheck If_Error(*next)
Endselect
Endcheck
*
* Now do the updates (now that every field is validated and correct)
Selectlist Named(#Grid_1)
Continue If(#Com_owner.HasNotChanged)
Update Fields(#salary #postcode) In_File(pslmst) With_Key(#empno) Io_Error(*NEXT) Val_Error(*NEXT)
Endselect
Endroutine
*
* Method Routine to check for changes
Mthroutine Name(HasNotChanged)
Define_Map For(*result) Class(#prim_boln) Name(#Result)
If ((#postcode = #postcodes<#Empno>) And (#salary = #salaries<#Empno>))
#Result := True
Endif
Endroutine
End_Com
The "inner" BEGINCHECK/ENDCHECK loop is processed for each grid row entry that the user updated. The IF_ERROR(*NEXT) parameter causes the SELECTLIST loop to continue to process all grid entries and not stop the first time an error is detected.
If a validation error is detected, the "outer" BEGINCHECK/ENDCHECK command uses the default IF_ERROR(*LASTDIS) setting which will cause the update event routine to be terminated without writing any records to the database.
A validation error will be detected if an error is found in one or more of the grid rows. This happens because any error in the "inner" validation block also triggers an error in the "outer" validation block.