=====================================================================
     Form in a Form in a Form in a Form
     =====================================================================
     PRODUCT: R:BASE            VERSION: 4.5
     =====================================================================
     AREA: FORMS                CATALOG: FORMS, REPORTS & LABELS
     =====================================================================
 
     One of the exciting new features of R:BASE 4.5 is the ability to call 
     a form from within an Entry/Exit procedure. The called form can be 
     used to either add or edit data. This allows developers, even 
     beginning users to increase the flexibility and ease of use for a 
     standard form. When you use this feature with the new row and table 
     level Entry/Exit procedures the possibilities are almost endless. 
 
     This article presents some ideas and ways to use the form in a form 
     feature, but also describes some of the areas that cause more 
     headaches than results. Is this a complete listing of things to do or 
     avoid?, no, this is merely a beginning. Look for more ways to use form 
     in a form in future issues of the Exchange.
 
     It's simple to set up a form in a form. Just write an Entry/Exit 
     procedure using R:BEDIT or your favorite ASCII text editor. Include 
     either ENTER formname or EDIT USING formname, any of the command 
     options can be used. A simple Entry/Exit procedure to do a form in a 
     form requires just the following commands:
 
     SET ERROR MESSAGES OFF
     SET MESSAGES OFF
     ENTER tranform
     RETURN
     
     It really is this simple. When this runs it will place you into the 
     form Tranform in the Add data mode. There is no error checking being 
     done and the form in a form will always execute. The EEP can be placed 
     as an entry or exit EEP on a field through the field settings screen 
     or as a row or table level EEP through the table settings screen. 
 
     Be aware that you will not be able to modify the same row of data in 
     the same table using a form in a form. You cannot enter a new row then 
     edit that row in a secondary form. You cannot edit or add parts of the 
     same row in a form in a form. You must always return to the outer form 
     and it will resave the row over edits made in the inner form. A form 
     in a form can reference other rows from the same table, just not the 
     same row.
 
     Most of the time the form in a form has some type of connection to the 
     first form. The easiest type of connection between the two forms is 
     using a variable to link the forms. Remember, the form in a form is 
     called from an EEP, an EEP doesn't know about column values, only 
     about variable values. In both forms, locate the same variable name. 
     The data would appear and be loaded to the tables in both forms using 
     ENTER. You also need an expression in both forms like this to save the 
     variable data into a column in each table:
 
     Column_name = .variable_name
     
     This loads the variable value into the column, and the link between 
     the tables is created. When EDITing data, use the command EDIT USING 
     formname WHERE column_name=.variable_name. The brings up a matching 
     row of data in the form in a form. Again, a fairly simple process to 
     link a form in a form. A few things to remember:
 
     1.      The column in the expression should be a linking column 
             between the tables (has the same name). This makes sure the 
             link will also work if the tables are used in a multi-table 
             form.
 
     2.      The expression is required or when you exit from the forms 
             the variable data will not be saved to the tables. 
 
     3.      Don't modify the same row of data in the same table in a form 
             in a form. 
 
     4.      Call the Entry/exit procedure after you have entered the data 
             into the variable. It can be a field level EEP on the 
             variable, or a row level EEP called after leaving the row. 
 
     Now, suppose the first table has an autonumbered column and that 
     column is the link between the two forms (i.e. tables). The same type 
     of setup is used with one exception. The first form, instead of an 
     expression that says Column_name = .variable_name, has one that is 
     just the opposite. The expression would be:
 
     variable_name = Column_name
     
     What happens is, when the first form starts up, the autonumber column 
     increments, and variable list is evaluated. The new number moves from 
     the column (which is placed as a field on the form) into the variable. 
     Then the form in a form picks up that variable value. When second form 
     is exited, the number from the variable (the autonumber) is saved to 
     the column and the tables are linked. Multiple rows can be entered in 
     the form in a form, each of the rows is linked to the same row in the 
     first form.
 
     Now that the process is clear, look at some real examples. 
 
     Example 1: Set up a transaction form where you can edit the customer 
     information for existing customers or add a new customer record if the 
     customer is not yet on file. This example uses the Concomp sample 
     database and is based on the form tranform. The first thing is to make 
     a copy of tranform. The copy will be modified to use a form in a form. 
 
     1.      Replace the custid field in the Transmaster table with the 
             variable vcustid 
 
     2.      Add an expression to the Transmaster table, custid = .vcustid. 
 
     3.      Modify the lookup expression in the Customer table so that the 
             WHERE clause reads WHERE custid = .vcustid. 
 
     4.      Add the following Entry/Exit procedure, custform.cmd, as an 
             Exit procedure on the vcustid field in the Transmaster table. 
 
     5.      Create a quick form, named cform, based on the Customer table 
     
     6.      Add an expression to cform, vcustid = custid. 
 
     7.      Using RBEDIT create the file called custform.cmd.
 
     
     *( The Exit Procedure custform.cmd  )
     SET ERROR MESSAGES OFF
     SET MESSAGES OFF
     DEBUG SET ERROR MESSAGES ON  *( FOR DEBUGGING  )
     DEBUG SET MESSAGES ON    
     DEBUG TRACE           
     SET ERROR VARIABLE verror   
     DIALOG 'Verify Existence of customer?' RKEY EKEY YES
     IF EKEY = 'NO' THEN
        RETURN
        ELSE
        EDIT USING cform WHERE custid = .vcustid
        SET VAR vexist = .verror   
            IF vexist <> 0 THEN     
                ENTER cform
            ENDIF          
     ENDIF          
     RECALC   
     RETURN    
     
     Place this as an Exit procedure on the Field settings screen for 
     vcustid. After the user enters the customer id value into the 
     variable vcustid he will be asked if he wants to verify the id. number 
     (The DIALOG command). The Exit procedure then tries to edit data using 
     the vcustid value the user entered. If the edit fails the error 
     variable is set to a non-zero value, and the procedure then brings up 
     the form cform for entering new customer information. The custid 
     column in the Customer table is an autonumber column so it will 
     automatically increment. As the user leaves cform, the variable is set 
     equal to the column, so when you return to tranform, the Customer 
     table lookup will access the correct data, either the edited 
     information or the new information. This an easy way to verify that 
     the customer information is correct or to add new customer 
     information.
 
     
     Example 2: Allow users to lookup rows of data to edit from within a 
     form. Previous versions of R:BASE required a command file that took 
     you in and out of the edit form. Using form in a form lets you sit in 
     a field in a form and enter different values for which the row or rows 
     immediately appear for editing. Edit the data, save changes and the 
     cursor returns to the same field on the form ready for entry of the 
     next data value to lookup and edit. You can easily modify your 
     existing edit forms to do this.
 
     1.      Make a copy of the form. The copy of the original form is used 
             as a "template". 
 
     2.      Modify the copy. Remove all field locations for the first 
             table in the form. Remove all tables except for the first 
             table (automatically removes the field locations for those 
             tables). Remove all pages except the first page (automatically 
             removed when all field locations are removed.
 
     3.      On the Form settings screen, indicate this form can only be 
             used with edit. Remove the menu from the form.
 
     4.      You now have a "template", a form that looks like the first 
             page of the original form, but with no fields located and no 
             user-defined menu. The actual editing of data is done on the 
             original form.
 
     5.      Locate a variable in the same position as the field that is 
             used as the lookup or search field. For example, if you edit 
             customer records and identify customers by the Cust_Id column, 
             locate a variable, VCust_Id, in the same location on the form 
             where the Cust_Id column is located on the original form. 
 
     6.      Customize the Field settings for the variable to make sure the 
             user can change the data in the field.
 
     7.      Add the following Entry/Exit procedure, search.eep, as an Exit 
             procedure on the variable field. 
 
     8.      Using RBEDIT create the file called search.eep. 
 
     *( The Exit Procedure search.eep  )
     SET VAR vlast = (lastkey(0))
     IF vlast = '[Esc]' THEN
          RETURN
     ENDIF
     EDIT USING original_form WHERE Cust_Id = .VCust_Id
     SET VARIABLE VCust_Id = NULL
     RETURN
     
     
     The procedure will execute unless the user presses [Esc] from the 
     template form. If the user presses [Esc] the procedure does not 
     execute and they exit the template form. The EDIT USING command brings 
     up the original form using a WHERE clause with the VCust_Id variable 
     identifying the specified customer. After the data is edited and the 
     original form exited, the variable VCust_Id is reset to NULL so it 
     will be blank on return to the template form.
 
     The template form could be further customized to use a pop-up menu for 
     the VCust_Id field. Users can select the correct customer from a menu 
     displaying the id and the name. The EEP and the form in a form stay 
     the same.
 
     What else can you do with a form in a form? You are not limited to 
     calling just one form. That form can call another form and so on. The 
     number of forms you can nest is limited by available memory. When you 
     reach the limit R:BASE will give you a message and you need to then 
     back out of each form. Use a form in a form to Enter/Edit a form at a 
     specific screen row to emulate windowed forms. A form in a form can 
     display historical data at the press of a key. Allow users to view 
     data in any table in the database using form in a form. You could 
     potentially run your entire application from a form. The possibilities 
     are endless. Just remember that a form in a form needs to reference a 
     different table or different rows of data if the table is the same.