How to Fill Down and Copy Values in an Interactive Grid in Oracle APEX

Build an editable Interactive Grid that opens in cell selection mode, fill and copy values across many rows, lock finished rows, and validate the bulk changes on save.

Editing the same column in many rows is a common chore. A planner assigns one technician to five jobs, or moves a group of tasks to the same date. Changing each cell by hand is slow, and it is easy to miss a row or pick a wrong value.

The Oracle APEX Interactive Grid has built-in tools for this: Fill, Copy Down, Clear, and Copy and Paste of cell ranges. This guide builds an editable grid that opens in cell selection mode, locks finished rows, and checks the result on the server. Then it uses each tool and saves the changes.

The guide Oracle APEX Interactive Grid: A Complete Guide mentions these menu entries in one paragraph. This article is the hands-on version: the page settings they need, how each one behaves, and what to watch out for.

The example uses service jobs and field technicians; the same steps work for any table.

Step 1: Create the Tables

Two tables hold the data:

  • FIELD_TECHNICIANS lists the people who can do a job.
  • SERVICE_JOBS has one row per job, with the technician, the visit date, the priority and the status.

Example:

set define off

create table field_technicians (
    technician_id    number generated by default on null as identity,
    technician_name  varchar2(60) not null,
    region           varchar2(30) not null,
    constraint field_technicians_pk primary key (technician_id),
    constraint field_technicians_name_uk unique (technician_name)
);

create table service_jobs (
    job_id         number generated by default on null as identity,
    job_ref        varchar2(20)  not null,
    site_name      varchar2(80)  not null,
    job_type       varchar2(30)  not null,
    technician_id  number,
    visit_date     date,
    priority       varchar2(10)  default on null 'NORMAL' not null,
    status         varchar2(10)  default on null 'OPEN' not null,
    constraint service_jobs_pk primary key (job_id),
    constraint service_jobs_ref_uk unique (job_ref),
    constraint service_jobs_tech_fk foreign key (technician_id)
        references field_technicians (technician_id),
    constraint service_jobs_priority_ck check (priority in ('LOW', 'NORMAL', 'HIGH')),
    constraint service_jobs_status_ck check (status in ('OPEN', 'SCHEDULED', 'DONE')),
    constraint service_jobs_scheduled_ck check (
        status = 'OPEN' or (technician_id is not null and visit_date is not null))
);

create index service_jobs_tech_ix on service_jobs (technician_id);

insert into field_technicians (technician_name, region) values ('Asha Menon', 'North');
insert into field_technicians (technician_name, region) values ('Brian Cole', 'North');
insert into field_technicians (technician_name, region) values ('Carla Diaz', 'South');
insert into field_technicians (technician_name, region) values ('Dev Patel', 'South');

insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1001', 'Riverside Clinic', 'Boiler service');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1002', 'Riverside Clinic', 'Air filter change');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1003', 'Oakwood School', 'Boiler service');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1004', 'Oakwood School', 'Fire alarm test');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1005', 'Oakwood School', 'Air filter change');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1006', 'Harbor Offices', 'Fire alarm test');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1007', 'Harbor Offices', 'Boiler service');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1008', 'Harbor Offices', 'Lift inspection');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1009', 'Maple Library', 'Air filter change');
insert into service_jobs (job_ref, site_name, job_type) values ('SJ-1010', 'Maple Library', 'Lift inspection');
insert into service_jobs (job_ref, site_name, job_type, technician_id, visit_date, status)
select 'SJ-0998', 'Riverside Clinic', 'Lift inspection', technician_id, date '2026-10-12', 'DONE'
from field_technicians where technician_name = 'Asha Menon';
insert into service_jobs (job_ref, site_name, job_type, technician_id, visit_date, status)
select 'SJ-0999', 'Harbor Offices', 'Air filter change', technician_id, date '2026-10-14', 'DONE'
from field_technicians where technician_name = 'Carla Diaz';

commit;

select j.job_ref, j.site_name, j.job_type, t.technician_name,
       to_char(j.visit_date, 'YYYY-MM-DD') as visit_date, j.priority, j.status
from service_jobs j
left join field_technicians t on t.technician_id = j.technician_id
order by j.job_ref;

Output:

Table FIELD_TECHNICIANS created.

Table SERVICE_JOBS created.

Index SERVICE_JOBS_TECH_IX created.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

1 row inserted.

Commit complete.

JOB_REF    SITE_NAME           JOB_TYPE             TECHNICIAN_NAME    VISIT_DATE    PRIORITY    STATUS
__________ ___________________ ____________________ __________________ _____________ ___________ _________
SJ-0998    Riverside Clinic    Lift inspection      Asha Menon         2026-10-12    NORMAL      DONE
SJ-0999    Harbor Offices      Air filter change    Carla Diaz         2026-10-14    NORMAL      DONE
SJ-1001    Riverside Clinic    Boiler service                                        NORMAL      OPEN
SJ-1002    Riverside Clinic    Air filter change                                     NORMAL      OPEN
SJ-1003    Oakwood School      Boiler service                                        NORMAL      OPEN
SJ-1004    Oakwood School      Fire alarm test                                       NORMAL      OPEN
SJ-1005    Oakwood School      Air filter change                                     NORMAL      OPEN
SJ-1006    Harbor Offices      Fire alarm test                                       NORMAL      OPEN
SJ-1007    Harbor Offices      Boiler service                                        NORMAL      OPEN
SJ-1008    Harbor Offices      Lift inspection                                       NORMAL      OPEN
SJ-1009    Maple Library       Air filter change                                     NORMAL      OPEN
SJ-1010    Maple Library       Lift inspection                                       NORMAL      OPEN

12 rows selected.
  • SERVICE_JOBS_TECH_FK links each job to a technician, and SERVICE_JOBS_TECH_IX indexes that foreign key.
  • SERVICE_JOBS_PRIORITY_CK and SERVICE_JOBS_STATUS_CK allow only known values. PRIORITY and STATUS use DEFAULT ON NULL, so new rows get NORMAL and OPEN without a trigger.
  • SERVICE_JOBS_SCHEDULED_CK makes sure a scheduled or done job has a technician and a visit date.
  • Ten jobs are open and unassigned. Two jobs (SJ-0998 and SJ-0999) are done; the grid will lock them.

Step 2: Create the Interactive Grid Page

In App Builder, open the application and click Create Page. On the Component tab, select Interactive Grid:

Create a Page wizard with the Interactive Grid tile marked with a red box
Choose the Interactive Grid page type.

Set Page Number to 940 and Name to Service Jobs. Keep Page Mode Normal:

Create Interactive Grid screen with Page Number 940 and Name Service Jobs marked with a red box
The page number and name.

Under Data Source, keep Source Type Table, set Table / View Name to SERVICE_JOBS and turn on Editing Enabled. Fill, Copy Down and Clear appear only in an editable grid:

Data Source section with Table / View Name SERVICE_JOBS and Editing Enabled on, marked with a red box
An editable grid on the jobs table.

Keep the Navigation settings. The wizard adds a breadcrumb and a navigation menu entry:

Navigation section with Use Breadcrumb and Use Navigation on
The default navigation settings.

Click Next. On the Primary Key screen, select JOB_ID and click Create Page:

Primary Key screen with Primary Key Column 1 JOB_ID marked with a red box
JOB_ID is the primary key.

Step 3: Add a Column That Locks Finished Rows

Fill and Copy Down change many rows at once, so finished jobs need protection. The Interactive Grid can read the allowed operations for each row from a column. That column must come from the region query, so the source changes from a table to a SQL query.

In Page Designer, select the Service Jobs region. Under Source, set Type to SQL Query and enter this query:

Example:

select job_id,
       job_ref,
       site_name,
       job_type,
       technician_id,
       visit_date,
       priority,
       status,
       case when status <> 'DONE' then 'U' end as allowed_ops
from   service_jobs
Page Designer with the Service Jobs region selected and Source Type SQL Query with the query marked with a red box
The query returns U (update allowed) for every job that is not done.

ALLOWED_OPS is U for open and scheduled jobs and empty for done jobs. The query has no ORDER BY clause on purpose. In a first test, an ORDER BY inside the query did not keep the rows in job order after some rows were saved. Step 8 sets the sort the way the grid expects.

Step 4: Allow Updates Only

Open the Attributes tab of the region. Under Edit, keep Enabled on, tick only Update Row in Allowed Operations, and set Allowed Row Operations Column to ALLOWED_OPS:

Attributes tab with Allowed Operations Update Row only and Allowed Row Operations Column ALLOWED_OPS marked with a red box
Users can update rows, but not add or delete them, and only where ALLOWED_OPS allows it.

The jobs are created elsewhere, so this page only schedules them. Rows with an empty ALLOWED_OPS are read-only in the grid. Step 13 shows that the server also refuses them.

Step 5: Set the Grid Columns

Expand Service Jobs and Columns. Select JOB_REF, set Type to Display Only and turn on Query Only under Source:

Column JOB_REF with Type Display Only and Query Only on marked with red boxes
The job reference is shown but never changed.

Do the same for SITE_NAME (set Heading to Site) and JOB_TYPE. In a test, Copy Down over a range that started in the Job Type column left Job Type unchanged and copied only the technician.

Select TECHNICIAN_ID. Set Type to Select List and Heading to Technician:

Column TECHNICIAN_ID with Type Select List and Heading Technician marked with red boxes
The technician column becomes a select list.

Under List of Values, set Type to SQL Query, enter this query, and set Null Display Value to - Unassigned -:

Example:

select technician_name as display_value, technician_id as return_value from field_technicians order by technician_name
List of Values group of TECHNICIAN_ID with Type SQL Query, the query and Null Display Value marked with red boxes
Users pick a technician by name.

Select PRIORITY and set Type to Select List:

Column PRIORITY with Type Select List marked with a red box
Priority is a select list.

Under List of Values, set Type to Static Values. Enter Low, Normal and High as display values with LOW, NORMAL and HIGH as return values, and turn off Display Null Value:

List of Values group of PRIORITY with Type Static Values and Display Null Value off marked with red boxes
Three fixed priorities and no empty entry.

Select STATUS, set Type to Select List, and set its List of Values the same way with Open, Scheduled and Done (return values OPEN, SCHEDULED and DONE):

List of Values group of STATUS with Type Static Values and Display Null Value off marked with red boxes
The status values match the check constraint.

Keep VISIT_DATE as the Date Picker that the wizard created. Finally, select ALLOWED_OPS, set Type to Hidden and turn on Query Only:

Column ALLOWED_OPS with Type Hidden and Query Only on marked with red boxes
ALLOWED_OPS is used by the grid but never shown or saved.

Step 6: Open the Grid in Cell Selection Mode

By default, the grid selects whole rows. Fill and Copy Down work best on a range of cells in one or more columns. Users can switch with Actions, Selection, Cell Selection, but the page can also start in that mode.

On the Attributes tab, under Advanced, enter this Initialization JavaScript Function:

Example:

function( options ) {
    options.defaultGridViewOptions = {
        selectCells: true
    };
    return options;
}
Advanced group of the grid attributes with the Initialization JavaScript Function marked with a red box
selectCells: true starts the grid view in cell selection mode.

Step 7: Add a Validation for Scheduled Jobs

Fill can set Scheduled on many rows in one move, including rows without a technician. The check constraint would stop such a save, but with a database error. A validation gives a clear message on the right cells.

On the Processing tab, right-click Validations and click Create Validation. Set Name to Scheduled Jobs Need a Technician and Visit Date, Editable Region to Service Jobs, Type to Expression, Language to PL/SQL, and enter this PL/SQL Expression:

Example:

:STATUS = 'OPEN' or (:TECHNICIAN_ID is not null and :VISIT_DATE is not null)
Validation with Name, Editable Region Service Jobs, Type Expression and the PL/SQL Expression marked with red boxes
The validation runs for every changed row.

Under Error, enter the Error Message A scheduled or done job needs a technician and a visit date. and set Associated Column to STATUS:

Error group with the Error Message and Associated Column STATUS marked with red boxes
The error points at the Status cell.

Click Save. The wizard already created the Service Jobs - Save Interactive Grid Data process, so no other process is needed.

Step 8: Sort the Grid by Job Ref

Run the page while you are logged in to App Builder. In Actions, open Data and click Sort:

Actions menu with Data open and the Sort entry marked with a red box
Before the sort, the rows came back in no useful order.

Set Column to Job Ref and Direction to Ascending, then click Save:

Sort dialog with Column Job Ref and Direction Ascending marked with a red box
The grid sorts by job reference.

Then open Actions, Report and click Save. Because you run the page as a developer, APEX saves this as the default report and shows Default report saved for all users:

Actions menu with Report open and the Save entry marked with a red box
Save the sort into the default report.

In a later test as another user, the grid opened sorted by Job Ref, SJ-0998 first and SJ-1010 last.

Step 9: Fill a Column with One Value

Run the page as an end user. The grid opens in cell selection mode, with the two done jobs at the top:

Service Jobs grid with twelve jobs, ten of them open and unassigned
The grid before any change.

The three Oakwood School jobs need Brian Cole. Click the Technician cell of SJ-1003, then Shift+click the Technician cell of SJ-1005. The footer shows 3 cells selected.

Click the Selection Actions button in the header of the row menu column (the icon left of Job Ref) and click Fill:

Selection Actions menu open over the grid with the Fill entry marked with a red box
The selection menu has Copy, Paste, Copy Down, Fill and Clear.

The Fill Selection dialog shows the column's own select list, because only one column is selected. Choose Brian Cole and click OK:

Fill Selection dialog with the Technician select list set to Brian Cole marked with a red box
The dialog uses the Technician list of values.

Now select the Visit Date cells of the same three rows and click Fill again. This time the dialog shows a date picker. Enter 11/04/2026 and click OK:

Fill Selection dialog with the Visit Date field set to 11/04/2026 marked with a red box
A date column gets a date picker in the dialog.

All three rows now have the same technician and visit date. The small triangles mark changed cells that are not saved yet:

Grid with Brian Cole and 11/04/2026 in the Technician and Visit Date cells of SJ-1003 to SJ-1005 marked with a red box
Two fills changed six cells.

Step 10: Copy the First Row Down

Copy Down takes the values of the first selected row and copies them into the other selected rows, column by column. It works across several columns at once.

Edit the first row as usual. For SJ-1006, click the Technician cell, press Enter and choose Carla Diaz, then set Visit Date to 11/05/2026, Priority to High and Status to Scheduled. Press Escape to leave edit mode:

Grid with the SJ-1006 row set to Carla Diaz, 11/05/2026, High and Scheduled marked with a red box
The first row holds the values to copy.

Click the Technician cell of SJ-1006 and Shift+click the Status cell of SJ-1008. That selects 12 cells in four columns. Open Selection Actions and click Copy Down:

Selection Actions menu with the Copy Down entry marked with a red box
Copy Down uses the first row of the selection.

SJ-1007 and SJ-1008 now match SJ-1006 in all four columns:

Grid with SJ-1006 to SJ-1008 all set to Carla Diaz, 11/05/2026, High and Scheduled marked with a red box
One Copy Down changed eight cells.

Step 11: Fill Skips Locked Rows

Select the Priority cells from SJ-0998 down to SJ-1002 and use Fill with High. The selection includes the two done jobs:

Grid where SJ-0998 and SJ-0999 still show Normal and SJ-1001 and SJ-1002 show High, marked with a red box
The done jobs keep Normal; only the open jobs changed.

Fill wrote High only into the rows where ALLOWED_OPS allows an update. The done jobs were not marked as changed at all.

Step 12: Copy and Paste Cells

In APEX 26.1, the selection menu also has Copy, Cut, Paste and Paste Insert, with keyboard shortcuts. Select the Technician and Visit Date cells of SJ-1006 and press Cmd+C (macOS, as shown in the menu):

Grid with the Technician and Visit Date cells of SJ-1006 marked with a red box
Two cells copied.

The clipboard now holds the display values separated by a tab: Carla Diaz and 11/05/2026. That is the same format a spreadsheet uses, so cells can also be copied to and from a spreadsheet.

Click the Technician cell of SJ-1009 and press Cmd+V. The footer shows 1 rows pasted:

Grid with Carla Diaz and 11/05/2026 pasted into SJ-1009 marked with a red box
The pasted text Carla Diaz was matched to the technician's ID.

Step 13: Save and Check the Data

Click Save. The grid sends all changed rows in one request and shows Changes saved:

Changes saved message marked with a red box above the saved grid
All changes saved at once.

Check the table in SQL:

Example:

select j.job_ref, t.technician_name,
       to_char(j.visit_date, 'YYYY-MM-DD') as visit_date, j.priority, j.status
from service_jobs j
left join field_technicians t on t.technician_id = j.technician_id
order by j.job_ref;

Output:

JOB_REF    TECHNICIAN_NAME    VISIT_DATE    PRIORITY    STATUS
__________ __________________ _____________ ___________ ____________
SJ-0998    Asha Menon         2026-10-12    NORMAL      DONE
SJ-0999    Carla Diaz         2026-10-14    NORMAL      DONE
SJ-1001                                     HIGH        OPEN
SJ-1002                                     HIGH        OPEN
SJ-1003    Brian Cole         2026-11-04    NORMAL      OPEN
SJ-1004    Brian Cole         2026-11-04    NORMAL      OPEN
SJ-1005    Brian Cole         2026-11-04    NORMAL      OPEN
SJ-1006    Carla Diaz         2026-11-05    HIGH        SCHEDULED
SJ-1007    Carla Diaz         2026-11-05    HIGH        SCHEDULED
SJ-1008    Carla Diaz         2026-11-05    HIGH        SCHEDULED
SJ-1009    Carla Diaz         2026-11-05    NORMAL      OPEN
SJ-1010                                     NORMAL      OPEN

12 rows selected.

Every fill, copy down and paste reached the table. The done jobs SJ-0998 and SJ-0999 are unchanged.

Test the Rules

First, the validation. Select the Status cells of SJ-1001 and SJ-1002, which have no technician, and use Fill with Scheduled. Click Save:

Error notification with two messages A scheduled or done job needs a technician and a visit date, marked with a red box
Both rows are refused, and the Status cells are marked.

Nothing was saved. Reload the page to drop the unsaved changes.

Second, a forced request. The grid does not let you edit a done row, but someone could change the save request in the browser. In a test, the save request was changed to set Priority High on the done job SJ-0998, with its update flag switched to true:

Error notification Session state protection violation for the protected item PRIORITY marked with a red box
The server rejects the changed request.

APEX answered with a session state protection violation for PRIORITY. The grid sends checksums for each row, so a request changed in the browser does not pass. The whole save was refused:

Example:

select job_ref, priority, status
from service_jobs
where job_ref in ('SJ-0998', 'SJ-1001')
order by job_ref;

Output:

JOB_REF    PRIORITY    STATUS
__________ ___________ _________
SJ-0998    NORMAL      DONE
SJ-1001    HIGH        OPEN

SJ-0998 is still NORMAL and DONE. SJ-1001 keeps its saved value, because its change was replaced by the forged row in the request.

Things to Know

  • Use cell selection for Fill. In row selection mode (Actions, Selection, Row Selection; the menu shows F8 as its shortcut), Fill shows a plain text box and writes the text into every editable column of the selected rows. The same menu entry then reads Cell Selection and switches back.
  • In a test, filling one row with High in row selection mode put High into Visit Date (marked invalid) and turned Priority to Low, because High is a display value, not a return value:
Row SJ-1010 after a row-mode fill: Visit Date High marked invalid and Priority Low, marked with a red box
Row-mode Fill wrote the same text into several columns.
  • Clear empties the selected cells, but a select list without a null entry cannot be empty. Clearing Priority in SJ-1009 and SJ-1010 set both to Low, the first value in the list. Clearing the Technician cell made it empty, as expected.
  • Paste matches text to the display values of a select list. When the clipboard held a name that is not in the list, the grid reported 1 rows pasted but left the Technician cell empty.
  • An ORDER BY inside the region query was not kept after rows were saved. Set the default sort in the saved report instead (Step 8).
  • The tools change only cells that can be edited. Fill skipped the rows locked through ALLOWED_OPS, Copy Down skipped the Display Only Job Type column, and the server checks the locked rows again on save.

Related Guides

Conclusion

To fill down and copy values in an Interactive Grid in Oracle APEX, make the grid editable, start it in cell selection mode, and use Fill, Copy Down and Paste from the selection menu. An Allowed Row Operations Column and a validation keep the bulk changes safe.

In this example, three fills, one Copy Down and one paste scheduled eight jobs in a few clicks and saved them in one request. Locked rows were skipped in the browser and refused on the server, and invalid statuses were stopped with a clear message.

Get more Vinish.dev tutorials on Google

See my articles more often when you search Google.

Vinish Kapoor
Vinish Kapoor

An Oracle ACE, author of four books on Oracle APEX, SQL and PL/SQL, and Oracle Forms, and a software developer building Oracle database applications since 2001.

guest

0 Comments
Oldest
Newest Most Voted