Custom Tab Order

When pressing the Tab key during data entry, Panorama normally moves from left to right, and in a form, also from top to bottom. If Shift-Tab is pressed, the order is from right to left, and bottom to top. With a special procedure, however, you can customize the tab order, perhaps skipping some fields. The order can even change depending on what data is entered.

#### Custom Tab Order – Data Sheet

To customize the operation of the Tab key when tabbing out of a database field, add the label `tabForward:` to the field code (see Automatic Field Code), then add code that calculates the name of the field to tab to. Panorama will execute this code as a function, so the field name must be returned using the functionvalue statement, as shown here.

When a company name is entered, Panorama tabs to the Title field, as it normally would. But if no company name is entered, Panorama will skip the Title field and go directly to the Address field when the tab key is pressed.

You may have noticed that in this example the automatic field code begins with a return statement. This is because this code will run from the top when editing of the field is complete (for example when clicking out of the field, or pressing the Enter key). Since we don’t want the tab forward part of the procedure to run, the return statement simply makes sure that the program will stop immediately, without running the rest of the code.

You can also customize the operation of the Shift-Tab key using the `tabBackward:` label, as shown here. (As this example shows, you can customize both forward and backwards tabbing out of any field.)

Here’s a more advanced example. With this code, if a zip code is entered into the City field and the Tab key pressed, Panorama will automatically move it to the Zip field, look up the city and state using Panorama’s built in zip code database, and skip to the Country field. On the other hand, if a city name is entered into the City field, the Tab key will simply advance to the State field.

Here is this code in action.

Note: If the code returns empty text for the field name (`""`), Panorama will cancel the tab and leave the cursor on the current field.

If you prefer, you can move the field code to a separate named subroutine, and call it from the properties panel. This can be more convienient for editing and debugging, and also allows you to share the same code among multiple forms. If you do this, the code in the properties panel can only contain one statement – the call statement that calls the subroutine. If Panorama sees just this one statement, it will look in the subroutine for any special labels like `tabForward:` and `tabBackward:`. If there is more than one statement, the labels must be in the properties panel. Here is a revised version of the previous example with the code moved into a separate procedure named CityLookup.

#### Custom Tab Order – Forms

The Form Properties panel offers three basic options for tab order: data sheet order, natural (top to bottom) and back to front. The following section describes how to go beyond those basic options, allowing the tab order to change dynamically based on the data entered. Dynamic customization of the tab order in a form is similar to the techniques described above for the data sheet, but somewhat more complicated. The code to modify the tab order is placed in the Text Editor Object, and begins with the `tabForward:` label.

Let’s take a closer look at this code:

    return

    tabForward:
        local city
        activeobjectaction "gettext",city
        if rangematch(city,"09")
            Zip = city
            City = city(Zip)
            State = state(Zip)
            functionvalue "Country"
        else
            functionvalue "State"
        endif
        return

A problem that needs to be overcome is that Panorama determines the next object to tab to very early in the process – in fact, before the field has been updated. So in this example, when the code starts running the City field doesn’t contain the new value yet, it still contains the old city value. Since we want to use the new city name to determine where to tab to, the first two lines use the activeobjectaction statement to grab the currently edited text into a variable named city.

    local city
    activeobjectaction "gettext",city

The next line uses the rangematch( function to check if a zip code (all numeric digits) has been typed into the City field.

    if rangematch(city,"09")

If the text is all numbers, we assume it is a zip code, so the code copies the number into the Zip field and uses the city( and state( function to look up the city and state using Panorama’s built in US Zip Code database.

    Zip = city
    City = city(Zip)
    State = state(Zip)

Finally, the code returns the name of the object to tab to. Take note that this is not necessarily the field name, though in this case we arranged it so that the object name and field name are the same.

    functionvalue "Country"

For the code in this example to work the Text Editor object that edits the Country field must be assigned the name Country.

See Object Names to learn more about assigning a name to an object.

Instead of using an object name, the functionvalue statement can return an object id number. Here is an alternate version of the functionvalue formula for this example that uses an object id number instead of the object name.

    functionvalue val(objectinfoarray({objectinfo("id")},{objectinfo("fieldname")="Country"}))

This formula is a lot more complex, but it has the advantage that it doesn’t require that a name be assigned to the desired object. Instead it uses the objectinfoarray( and objectinfo( function to search for the object that edits the Country field name.

The end result is the same either way, as shown in this movie. If a zip code is typed in, pressing tab will look up the city and state and jump directly to the Country field. If an actual city name is entered, tab jumps to the State field.

Note: If the code returns empty text for the field name (`""`), Panorama will cancel the tab and leaves the current Text Editor object active.

If you prefer, you can move the field code to a separate named subroutine, and call it from the properties panel. This can be more convenient for editing and debugging, and also allows you to share the same code among multiple forms. If you do this, the code in the properties panel can only contain one statement – the call statement that calls the subroutine. If Panorama sees just this one statement, it will look in the subroutine for any special labels like `tabForward:` and `tabBackward:`. If there is more than one statement, the labels must be in the properties panel. Here is a revised version of the previous example with the code moved into a separate procedure named cityFormLookup.

See Also

- activeobjectaction -- allows a procedure to communicate with the object on the current form that is currently being edited (if any).
- Automatic Field Code -- running a short program when data is entered into a field.
- call -- allows a procedure to call a separate procedure within the current database as a subroutine.
- city( -- looks up the name of a city associated with a US zip code.
- Field Properties -- available field attributes.
- functionvalue -- returns a value calculated by a procedure using the call(, callwithin( or execute( functions.
- Object Names -- can be used to identify an object in a program.
- objectinfo( -- returns information about a graphic object: its location, size, color, font, etc.
- objectinfoarray( -- builds a text array of form object properties
- rangematch( -- returns true (-1) if the text matches a specified range.
- return -- ends a subroutine.
- state( -- returns the name of the state associated with a US zip code.
- Text Editor Object -- is used to edit text in a field or variable.

History

Version | Status | Notes
10.2 | Updated | Your special custom code that calculates the field to tab to now has the option of returning empty text ("") to cancel the tab operation.
10.1 | New | New in this version.