""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   CREATE AN AD HOC BROWSER USING THE POWER OF CHOOSE
   """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   PRODUCT   :  R:BASE                  VERSION      :  3.1
   CATEGORY  :  PROGRAMMING             SUBCATEGORY  :  TOOLS
   """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
   From Marva Dasef, 80770 Turkey Run Road, Creswell, OR 97426. Marva is
   an award-winning writer and database programmer who recently wrote
   "Using R:BASE," a new book on R:BASE 3.0 published by Que. You can
   reach Marva at 503-942-5228.
 
   If you write applications for other people's use, you know you won't
   usually be able to cover all the possibilities for data inquiry that
   users might want. Often, users don't know what they want until they
   want it.
 
   By using the R:BASE 3.1 CHOOSE command, you can create a generic
   selection routine like COMMON.CMD (listed below) that people can use
   to pick and choose data to their heart's content, without having to
   learn anything about the database structure.
 
   COMMON.CMD works as is with any database, without any modification to
   the code. All table and column names are selected by using the CHOOSE
   command, rather than by naming them specifically in the command file.
 
 
   Step by Step to Ad Hoc Queries
   """"""""""""""""""""""""""""""
   STEP 1--Create a table in each database named COMMON with two columns:
   COMCOLUMN and COMTABLE. Enter the names of the common columns and
   their respective tables. For example, here's COMMON for CONCOMP:
 
             ComColumn                  ComTable
             Bonuspct                   bonusrate
             Bonuspct                   salesbonus
             Compid                     component
             Compid                     compused
             Custid                     contact
             Custid                     customer
             Custid                     transmaster
             Empid                      employee
             Empid                      transmaster
             Model                      compused
             Model                      prodlocation
             Model                      product
             Model                      transdetail
             Netamount                  salesbonus
             Netamount                  transmaster
             Transdate                  salesbonus
             Transdate                  transmaster
             Transid                    transdetail
             Transid                    transmaster
 
   Find the common columns by using the LIST COLUMN command and noting
   when a column name occurs in more than one table. Only include common
   columns that have the same name. You can't, for example, tell R:BASE
   that two differently named columns are common. In fact, that wouldn't
   be a good database design.
 
   STEP 2--Next, create a CHKBOX menu file for each table. These menus
   will provide a current list of the columns in each table when the
   command file executes. For example, here's the menu file for
   TRANSMASTER:
 
     transmas
     CHKBOX
     #COLUMNS IN transmaster
     ENDC
 
   Use the first eight characters of each table name as the menu name.
   These will be unique in the database, because R:BASE, although
   allowing up to 18 characters for a table name, only uses the first
   eight characters to identify a table.
 
   STEP 3--Create the COMMON.CMD command file.
 
     *( COMMON.CMD--Ad Hoc Selection for Browsing.)
     SET MESSAGES OFF ; SET ERR MESSAGES OFF
     *( Set BELL OFF so when checking for common column values,)
     *( it won't beep if it doesn't find a match. It doesn't)
     *( require a common column unless combining data from two tables.)
     SET BELL OFF
     CLS
     *( Display a menu of databases in the current directory. To include this)
     *( command file as a block in an application by using the Macro option)
     *( omit this section so the program uses the currently open database.)
     CHOOSE vdatab FROM #DATABASES
     IF vdatab IS NULL THEN
       QUIT
     ENDIF
     CONNECT .vdatab
     *( The LABEL identifies where control will return after a pick, so you can
)
     *( choose again without reconnecting to the database.)
     LABEL pickagin
     CLS
     WRITE 'Choose the primary table. [Esc] to exit.' AT 23 10
     *( Display a menu of the tables in the database.)
     CHOOSE vtable1 FROM #TABLES
     *( Provide an "out," so if you don't want to continue, you can)
     *( press [Esc] to leave the command file.)
     IF vtable1 = '[Esc]' THEN
       CLEAR VAR vchkcom, vcols1, vcols2, vcommon, vdatab, vsecond, +
         vshort1, vshort2, vsort, vtable1, vtable2
       SET MESSAGES ON
       SET ERROR MESSAGES ON
       SET BELL ON ; CLS
       RETURN
     ENDIF
     *( Use SET VAR to ensure that you have a menu name for the table.)
     *( You provided a menu file for each table using the first eight)
     *( characters of the table name as the menu name. SGET moves)
     *( the first eight characters of the table name stored in VTABLE1 into)
     *( the variable VSHORT1.)
     SET VAR vshort1 = (SGET(.vtable1,8,1))
     *( Display an explanation and a list of columns from the table selected)
     *( earlier, so you can choose the columns from the first table. Notice the
)
     *( CASCADE RIGHT option to  "tile" menus on the screen in the same)
     *( way that R:BASE 3.1 does with its own menus.)
     WRITE 'Choose the columns you want to display. F2 to continue.' +
       AT 23, 10
     CHOOSE vcols1 FROM &vshort1 CASCADE RIGHT
     *( Use SET VAR to check COMMON table to determine if a second table)
     *( selection is appropriate. It does this by moving the table name into)
     *( the variable VCHKCOM. If the table name exists in COMMON, then)
     *( you know that at least one other table in the database has a column)
     *( in common with the first table. If VCHKCOM is null, the table doesn't)
     *( exist in COMMON, so command file sets variable VSECOND to N)
     *( and doesn't ask for a second table--it skips the FILLIN.)
     SET VAR vchkcom = comtable IN common WHERE comtable=.vtable1
     IF vchkcom IS NULL THEN
        SET VAR vsecond = 'N'
        GOTO onetab
     ENDIF
     *( Initialize VSECOND to Y to make a second table request the default.)
     *( Note that FILLIN now has an EDIT clause so you can edit the current)
     *( contents of the FILLIN variable.)
     SET VAR vsecond = 'Y'
     CLS FROM 23 TO 23
     FILLIN vsecond=1 USING 'Do you want to combine tables? ' AT 23 10 EDIT
     LABEL onetab
     *( These commands execute if you do want a second table.)
     IF vsecond EQ 'Y' THEN
       CLS FROM 23 TO 23
       WRITE 'Choose a combining column.' AT 23 10
       CHOOSE vcommon FROM #VALUES FOR DISTINCT comcolumn +
         FROM common WHERE comtable = .vtable1 CASCADE RIGHT
       CLS ; WRITE 'Choose the secondary table.' AT 23 10
       CHOOSE vtable2 FROM #VALUES FOR DISTINCT comtable +
         FROM common WHERE comcolumn = .vcommon
       SET VAR vshort2 = (SGET(.vtable2,8,1))
       CLS FROM 23 TO 23
       WRITE 'Choose the columns you want to display. F2 to execute. ' +
         AT 23 10
       CHOOSE vcols2 FROM &vshort2 CASCADE RIGHT
       BROWSE DISTINCT &vcols1, &vcols2 FROM &vtable1, &vtable2 +
          WHERE &vcommon = &vcommon ORDER BY &vcommon
     ELSE  *( These commands execute if you don't want a second table.)
       CLS FROM 23 TO 23
       WRITE 'Choose one or more columns to sort by (ascending).' AT 23 10
       CHOOSE vsort FROM &vshort1 CASCADE RIGHT
       BROWSE DISTINCT &vcols1 FROM &vtable1 ORDER BY &vsort
     ENDIF
     *( When you exit from the tabular edit display, clear the variables and)
     *( pass control to the top of the command file at the PICKAGIN label.)
     CLEAR VAR vchkcom, vcols1, vcols2, vcommon, vdatab, vsecond, +
       vshort1, vshort2, vsort, vtable1, vtable2
     GOTO pickagin
 
   The section of COMMON.CMD that executes when you want a second table,
   accomplishes these tasks:
 
     o  Display a list of columns from the COMMON table for the first
        selected table. This is the column by which the data from the two
        tables will be combined. This ensures that the list of tables for
        the second table selection will only be those with a common
        column with the first table. The user won't be able to select
        tables that aren't related.
     o  Display a list of tables that have a column in common with the
        first table. By using the COMMON table list, the user will only
        be able to select appropriate second tables.
     o  Create the eight character name for the second table (to match
        the menu file name for that table).
     o  Display a list of columns from the second table using the menu
        file to let the user select the columns to display from the
        second table.
     o  Display the data selected from both tables in the tabular edit
        format. BROWSE disallows any data modification because it uses
        the DISTINCT option.
 
   The section of COMMON.CMD file that executes when you don't want a
   second table or when there is no second table available, accomplishes
   these tasks:
 
     o  Display a list of columns from the table to select for sorting.
        R:BASE has a CHKSORT menu type that lets you choose a column for
        sorting and choose whether you want the sort to be in ascending
        or descending order. For simplicity, this program assumes an
        ascending sort and uses the same CHKBOX menu as used for
        selecting the columns to display.
     o  Display the selected data sorted by the appropriate columns.