Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

DataGridView: paginated grids

DataGridView shows a list of rows from a table on a Screen, with native pagination (Page Up/Down) over a DDS subfile. There can only be one per Screen.

1. Full example

@Properties {
    Type : Screen
    Name : SGRIDDEMO
}
@References {
    Tables = ["tables/TLGRIDDEMO.warp"]
}
@Variables {
    global {
        VCustCode char(6)
        VName     char(20)
        VCity     char(15)
        VTotal    number(5)
        VLast     char(6)
    }
}
@Layout {
    DataGridView("GridDemo", 2, 2, 5)
    [
        Column("Code", &VCustCode)
        Column("Name", &VName)
        Column("City", &VCity)
    ]
}
@Source {
    Event Load
        For Each In GRIDDEMO Index GRIDDMNOM
            &VCustCode = CustCode
            &VName     = Name
            &VCity     = City
            LoadRow()
        EndFor
    EndEvent

    Event Enter
        &VTotal = 0
        For Each Row
            &VTotal = &VTotal + 1
            &VLast = &VCustCode
        EndFor
        Message("Rows: " + String(&VTotal, 5) + " Last: " + &VLast, Info)
    EndEvent
}

Between two contiguous visible columns there is always at least one free position (the separator, if declared; otherwise a space). This counts toward the E00353 width calculation: see Available width and error E00353.

2. Loading the grid: Event Load + LoadRow()

LoadRow() takes the current values of the variables bound to each Column and appends a row to the grid. It is valid anywhere in the body of any Event of a Screen — directly, inside If, Case, While, For or For Each — so it can also load the grid with data that does not come from a table. A For Each that loads the grid must declare Index (E00201). There can be several loads in the same event: all of them append rows to the same grid. In Event Load the grid is reset only once, when the event starts; in any other Event or Procedure the rows are appended to the ones already there. It loads the entire result set in a single pass — Page Up/Down are native terminal scrolling over what’s already loaded; Load never runs again.

LoadRow() can also be used inside any Procedure of the Screen, regardless of where it is invoked from (with Do). A Function cannot use LoadRow(), and it cannot be used outside an Event or Procedure either (E00198).

Event Load
    Do Carga()
EndEvent

Procedure Carga()
    For &Indice = 1 To 5
        &VCod    = &Indice
        &VNombre = "Item " + String(&Indice, 3)
        LoadRow()
    EndFor
EndProc

A Procedure with LoadRow() can also be called from another event. Here Enter appends rows to the ones Load already loaded (and F5/Refresh runs Load again, which resets the grid):

Event Enter
    Do AddRows()
EndEvent

Procedure AddRows()
    &VCod    = 99
    &VNombre = "Added row"
    LoadRow()
EndProc

Or directly in the event, with no procedure and no table:

Event Load
    &VCod    = 1
    &VNombre = "First"
    LoadRow()
    &VCod    = 2
    &VNombre = "Second"
    LoadRow()
EndEvent

Related rule: a local variable with the same name as a Column variable shadows the global one (LoadRow() would copy the local value), error E00356. See Diagnostics.

3. Reading the selection: RefreshSelectRow() and CurrentInput()

When the cursor lands inside the grid’s rectangle (header, attention row, or any data row), CurrentInput() returns the grid’s name. RefreshSelectRow() re-reads the row under the cursor and writes each column (including Hidden ones) back into its bound variable — it’s the reverse of LoadRow(). This is how to recover the value of a Hidden column: those columns travel in the subfile record as hidden fields (usage H in the DDS), with no line or position on the screen:

Event Enter
    &Control = CurrentInput()
    If &Control = "GridDemo"
        RefreshSelectRow()
        Message("You selected: " + &VCustCode, Info)
    EndIf
EndEvent

4. Iterating over all loaded rows: For Each Row

For Each Row ... EndFor iterates over all rows already loaded into the subfile (not the database table), writing each Column into its bound variable before every iteration — same direction as RefreshSelectRow(). It doesn’t support Index/Where/When None because there’s no table being iterated:

Event Enter
    &VTotal = 0
    For Each Row
        &VTotal = &VTotal + 1
    EndFor
EndEvent

5. Hidden columns

Column("Internal ID", &VInternalId, Hidden)

A Hidden column loads its data (participates in LoadRow()/RefreshSelectRow()/For Each Row) but doesn’t show its cell or header title — useful for carrying an internal key without taking up screen space.

6. Editable columns (Input)

Column("Quantity", &VQuantity, Input)

Lets the user edit the value directly in the grid.

Reloading the grid: Refresh and Refresh Keep

To run Event Load again (for example, after changing a filter) use Refresh (goes back to the first row) or Refresh Keep (keeps the row where the user was). The reload happens when the current event ends. F5, if declared in @FunctionKeys, runs Event Refresh and then reloads the grid. See Refresh and Refresh Keep.

7. Rules to keep in mind

  • The name ("GridDemo") is required and must be unique among Input/DataGridView controls on the same screen.
  • Only one DataGridView per Screen.
  • Only valid inside a Screen’s @Layout, never a Program’s.