Progress
Programming
Handbook


Searching Columns (Windows Only)

When a read-only browse has focus, typing any printable key (an alphanumeric character), forces Progress to reposition the browse to the first row where the first character of the first browse column matches the typed character. Thus, the read-only browse allows searching, but based only on the data in the first column. If the browse finds no match, it wraps to the top of the column and continues searching.

In an updatable browse, the user can select the column that will be the basis of the character search. First, the user clicks a column label. The column label depresses. Typing any printable key searches for the first row in that column that matches and Progress focuses that row. Column searches also wrap to the top if necessary.

NOTE: A column search on a browse associated with a query with the INDEXED–REPOSITION option does not wrap to the top of the column if it cannot find a record to satisfy the search. This behavior is a side effect of the reposition optimization. To work around this, you can apply HOME to the query before starting the search.

There are two ways to extend this basic functionality. First, you can configure an updatable browse to look like a read-only browse. This technique gives you selectable columns and searching on those columns. Second, you can use the START–SEARCH and END–SEARCH events to trap the beginning and end of search mode. You can use this functionality to write your own search routines. For example, you can perform incremental searches using multiple keys.

Implementing Column-Searching on a Read-Only Browse

The column-searching feature is exclusive to the updatable browse. The read-only browse can do one-character deep searches on the initial column of the browse. You can work around this by defining your browse with one field enabled for input and the NO–ROW–MARKERS option specified. After the definition, disable the enabled column by using the READ–ONLY attribute. This provides an updatable browse that looks like a read-only browse. However, the updatable browse retains the ability for the user to select individual columns and perform searches on them.

Implementing Incremental Searching

The following code example depicts a multi-character incremental search on the customer name field. You can modify the basic algorithm to provide this type of search on any column:

p-br06.p
DEFINE QUERY q1 FOR customer SCROLLING.  
DEFINE VARIABLE credit-left AS DECIMAL LABEL "Credit Left". 
DEFINE BROWSE b1 QUERY q1 DISPLAY cust-num name credit-limit balance  
    (credit-limit - balance) @ credit-left ENABLE credit-limit  
    WITH 10 DOWN SEPARATORS TITLE "Update Credit Limits". 
DEFINE VARIABLE method-return AS LOGICAL. 
DEFINE VARIABLE wh AS WIDGET-HANDLE. 
DEFINE VARIABLE lblflag AS LOGICAL. 
DEFINE FRAME f1 
    b1 
WITH SIDE-LABELS ROW 2 CENTERED NO-BOX. ON END-SEARCH OF b1 IN FRAME f1   
DO: 
    IF lblflag THEN 
        wh:LABEL = "Name". 
    lblflag = FALSE. 
END. 
ON START-SEARCH OF b1 IN FRAME f1 
DO:  
    wh = b1:CURRENT-COLUMN.  
    IF wh:LABEL = "name" THEN DO:  
       lblflag = TRUE.  
       wh:label = "SEARCHING...".  
       MESSAGE "Incremental Search?" VIEW-AS ALERT-BOX QUESTION  
          BUTTONS YES-NO-CANCEL TITLE "Search Mode"  
         UPDATE answ AS LOGICAL. 
       CASE answ: 
          WHEN TRUE THEN DO: 
              /* SETTING REPOSITIONED ROW */ 
              method-return = b1:SET-REPOSITIONED-ROW(3,"CONDITIONAL"). 
              RUN inc-src. 
              RETURN.  
          END. 
          WHEN FALSE THEN DO: 
              MESSAGE "Search mode defaults to the first character." 
              VIEW-AS ALERT-BOX INFORMATION BUTTONS OK. 
              RETURN NO-APPLY. 
          END. 
          OTHERWISE APPLY "END-SEARCH" TO SELF. 
      END CASE.  
    END. 
END. 
OPEN QUERY q1 FOR EACH customer NO-LOCK BY customer.name.  
ENABLE ALL WITH FRAME f1. 
WAIT-FOR WINDOW-CLOSE OF CURRENT-WINDOW.PROCEDURE inc-src: DEFINE VARIABLE 
curr-record AS RECID. 
DEFINE VARIABLE initial-str AS CHARACTER.APPLY "START-SEARCH" TO BROWSE b1.ON 
ANY-PRINTABLE OF b1 IN FRAME f1 
DO:  
   ASSIGN curr-record = RECID(customer) 
          initial-str = initial-str + LAST-EVENT:LABEL. 
   match-string: 
   DO ON ERROR UNDO match-string, LEAVE match-string:  
       IF RETRY THEN  
           initial-str = LAST-EVENT:LABEL. 
       FIND NEXT customer WHERE customer.name BEGINS initial-str  
            USE-INDEX name NO-LOCK NO-ERROR 
IF AVAILABLE customer THEN  
            curr-record = RECID(customer). 
        ELSE IF RETRY THEN  
             DO: 
                initial-str = "". 
                BELL. 
             END. 
             ELSE  
                UNDO match-string, RETRY match-string. 
    END. 
     
    REPOSITION q1 TO RECID curr-record. 
    END.    ON VALUE-CHANGED OF b1 IN FRAME f1 
    DO:  
        initial-str = "". 
    END. 
    WAIT-FOR "END-SEARCH" OF BROWSE b1. 
    APPLY "ENTRY" TO name IN BROWSE b1. 
END PROCEDURE. 

The screen below shows what happens when you choose the Name column:

In brief, the START–SEARCH trigger traps the user action and presents the user with choices. This is good for demonstration purposes, but in practice, you may want your custom search behavior to override the default behavior.

If the user chooses Yes at the Incremental Search alert box, then the trigger enables search mode. The search mode is instantiated and maintained entirely by the internal procedure, inc–src. This procedure executes a trigger when any printable key is typed. While the code can build up a valid search string, it keeps going. So, if the user types B L U E, the procedure finds Blue Line Hockey. As soon as the procedure encounters a character that creates a string it can’t match, it assumes it is starting a new search. So if the User types B L U E A, the procedure focuses Blue Line Hockey, but discards the string and moves to ABC Mountain Bikes when it encounters the A.

Another way to implement multiple character searches is to provide the user with a Search button. The Search button would simply apply START–SEARCH to the correct column, and the START–SEARCH trigger and internal procedure would take over.


Copyright © 2004 Progress Software Corporation
www.progress.com
Voice: (781) 280-4000
Fax: (781) 280-4095