A browse can support single and multiple selections of rows. By default, a browse is single-select. The MULTIPLE option sets up a multiple-select browse. Multiple-selection lets you select any combination of rows from the browse, which you can then access using the appropriate browse attributes and methods.

In a multiple-select browse, the user first clicks in a row to select it. To select additional rows without deselecting the first, the user holds down the CTRL key and clicks in each row. Alternatively, the user can click in one row, hold down the mouse key, and drag the cursor through multiple rows to select them all. Clicking on a selected row while pressing CTRL deselects it. Clicking on a row without pressing CTRL selects it and deselects all other rows. In a multiple-select updateable browse, the user must click on one row marker, hold down the mouse button and drag down through the row markers to select multiple contiguous rows.

Note that an updateable browse can only have one selected row when it is in edit mode. So, if the user selects five rows and then an updateable cell, the four rows that do not contain the active cell are deselected.

Note: For a multiple-select browse in character interfaces, selection of each row is switched by the space bar. The close angle bracket (>) indicates each selected row. The same technique applies to both read-only and updateable multiple-select browses.

There are several attributes and methods you can use in conjunction with selected rows in a single-selection or multiple-selection browse. You can learn about these in the ABL Reference.

Next, you modify your test procedure to use the NUM-SELECTED-ROWS attribute and the FETCH-SELECTED-ROW method to gather information about a set of selected rows in a multiple-selection browse

To modify your test procedure:

  1. Add the MULTIPLE option to the browse definition for OlineBrowse to enable multiple selection.
  2. Add a button named BtnTotal with the label Total to your window.
  3. Add a fill-in called dTotal to the window with no label.
  4. In its property sheet, change its data type to Decimal.
  5. Define this trigger block for the CHOOSE event for BtnTotal:
    DO:
      DEFINE VARIABLE iRow AS INTEGER NO-UNDO.
      DEFINE VARIABLE hBrowse AS HANDLE NO-UNDO.
    
      hBrowse = BROWSE OlineBrowse:HANDLE.
      DO iRow = 1 TO hBrowse:NUM-SELECTED-ROWS:
        hBrowse:FETCH-SELECTED-ROW(iRow).
        dTotal = dTotal + ttOline.ExtendedPrice.
      END.
      DISPLAY dtotal WITH FRAME CustQuery.
    END.

The NUM-SELECTED-ROWS attribute returns the number of rows the user has selected in the browse. You can then use the FETCH-SELECTED-ROW method, which takes the sequence within the list of selected rows as an argument, to position the query to each selected row in turn, and add up the ExtendedPrice for each of those rows.

One question you might have is, why is it necessary to define a handle variable to hold the handle of the browse, rather than just referring to it in each statement as BROWSE OlineBrowse? The browse is not part of the initial frame definition for the window’s frame. It is displayed after the window is initialized. If you refer to BROWSE OlineBrowse in the statements with the NUM-SELECTED-ROWS attribute or the FETCH-SELECTED-ROW method, the AVM insists that you qualify the reference with a frame name so that it can identify the browse. Normally, you would qualify each reference to make it explicit or else simply put the entire set of references inside a DO block that defines the context:
DO WITH FRAME CustQuery:
  DO iRow = 1 TO BROWSE OlineBrowse:NUM-SELECTED-ROWS:
    .
    .   
    .

But because the browse is not part of the frame at compile time, ABL gives you an error message when you compile the procedure (or when you run it, which compiles it first) to the effect that it cannot find OlineBrowse in frame CustQuery. To get around this, you need to fool ABL into accepting the reference at compile time. To do this, you first set the handle hBrowse variable to the HANDLE attribute of the browse, and then use the handle in place of the name. ABL accepts this because handle references are always difficult or impossible to check at compile time, so ABL has to assume that the reference is valid when the code is executed, which it is.

To see a total displayed, Run the window, select some OrderLines, and then click the Total button: