# SAP Background Job History Report Generator: TBTCO and TBTCP in ABAP

> Source: https://netray.co/tools/sap-ecc-tbtco-job-history-abap-select-generator
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: Free Tools

## Short answer

Fill in a job name pattern, program, status and date range and get a classic ABAP report that joins TBTCO and TBTCP, computes runtime, reads the job log of cancelled jobs and shows the result in ALV.

## Category

developer

## Erp

SAP ECC 6.0

## Audience

- ABAP developer
- Basis administrator
- SAP support analyst

## Tool

**Kind:** template

**Output:** code

**Language:** abap

**Fields:**

#### Report name

**Key:** report

**Type:** text

**Default:** ZBC_JOB_HISTORY

#### Job name pattern (* allowed)

**Key:** job_pattern

**Type:** text

**Default:** Z*

#### Program name pattern (blank = all)

**Key:** prog_pattern

**Type:** text

#### Job status

**Key:** status

**Type:** select

**Options:**

- A
- F
- R
- S
- *

**Default:** A

**Help:** A cancelled, F finished, R active, S released, * all

#### Start date from (YYYYMMDD)

**Key:** from_date

**Type:** text

**Default:** 20261001

#### Start date to (YYYYMMDD)

**Key:** to_date

**Type:** text

**Default:** 20261022

#### Step user (blank = all)

**Key:** step_user

**Type:** text

#### Max rows

**Key:** max_rows

**Type:** number

**Default:** 500

**Blocks:**

#### Report source (classic Open SQL, any ECC 6.0 release)

**Body:** REPORT {{report}}.

TYPES: BEGIN OF ty_result,
         jobname   TYPE tbtco-jobname,
         jobcount  TYPE tbtco-jobcount,
         status    TYPE tbtco-status,
         strtdate  TYPE tbtco-strtdate,
         strttime  TYPE tbtco-strttime,
         enddate   TYPE tbtco-enddate,
         endtime   TYPE tbtco-endtime,
         sdluname  TYPE tbtco-sdluname,
         stepcount TYPE tbtcp-stepcount,
         progname  TYPE tbtcp-progname,
         variant   TYPE tbtcp-variant,
         authcknam TYPE tbtcp-authcknam,
         listident TYPE tbtcp-listident,
         runtime_s TYPE i,
         lastmsg   TYPE tbtc5-text,
       END OF ty_result.

DATA: lt_result TYPE STANDARD TABLE OF ty_result,
      lt_log    TYPE STANDARD TABLE OF tbtc5,
      ls_log    TYPE tbtc5,
      lr_status TYPE RANGE OF tbtco-status,
      ls_status LIKE LINE OF lr_status,
      lr_user   TYPE RANGE OF tbtcp-authcknam,
      ls_user   LIKE LINE OF lr_user,
      lv_job    TYPE tbtco-jobname,
      lv_prog   TYPE tbtcp-progname,
      lv_text   TYPE string,
      lo_alv    TYPE REF TO cl_salv_table,
      lo_func   TYPE REF TO cl_salv_functions_list,
      lx_msg    TYPE REF TO cx_salv_msg.

FIELD-SYMBOLS: <ls_res> TYPE ty_result.

PARAMETERS: p_job  TYPE tbtco-jobname   DEFAULT '{{job_pattern}}',
            p_prog TYPE tbtcp-progname  DEFAULT '{{prog_pattern}}',
            p_stat TYPE tbtco-status    DEFAULT '{{status}}',
            p_from TYPE sy-datum        DEFAULT '{{from_date}}',
            p_to   TYPE sy-datum        DEFAULT '{{to_date}}',
            p_user TYPE tbtcp-authcknam DEFAULT '{{step_user}}',
            p_max  TYPE i               DEFAULT {{max_rows}}.

START-OF-SELECTION.

* Convert * wildcards to SQL LIKE wildcards
  lv_job = p_job.
  TRANSLATE lv_job USING '*%'.
  IF lv_job IS INITIAL.
    lv_job = '%'.
  ENDIF.
  lv_prog = p_prog.
  TRANSLATE lv_prog USING '*%'.
  IF lv_prog IS INITIAL.
    lv_prog = '%'.
  ENDIF.

* Empty range = no restriction
  IF p_stat IS NOT INITIAL AND p_stat <> '*'.
    ls_status-sign   = 'I'.
    ls_status-option = 'EQ'.
    ls_status-low    = p_stat.
    APPEND ls_status TO lr_status.
  ENDIF.
  IF p_user IS NOT INITIAL.
    ls_user-sign   = 'I'.
    ls_user-option = 'EQ'.
    ls_user-low    = p_user.
    APPEND ls_user TO lr_user.
  ENDIF.

  SELECT a~jobname a~jobcount a~status a~strtdate a~strttime
         a~enddate a~endtime a~sdluname
         b~stepcount b~progname b~variant b~authcknam b~listident
    INTO CORRESPONDING FIELDS OF TABLE lt_result
    FROM tbtco AS a
    INNER JOIN tbtcp AS b
      ON  b~jobname  = a~jobname
      AND b~jobcount = a~jobcount
    UP TO p_max ROWS
    WHERE a~jobname   LIKE lv_job
      AND a~status    IN lr_status
      AND a~strtdate  BETWEEN p_from AND p_to
      AND b~progname  LIKE lv_prog
      AND b~authcknam IN lr_user
    ORDER BY a~strtdate DESCENDING a~strttime DESCENDING.

  IF sy-subrc <> 0.
    MESSAGE 'No jobs found for the selection' TYPE 'S'.
    RETURN.
  ENDIF.

  LOOP AT lt_result ASSIGNING <ls_res>.
*   Runtime: date difference in days plus time difference in seconds
    IF <ls_res>-enddate IS NOT INITIAL.
      <ls_res>-runtime_s = ( <ls_res>-enddate - <ls_res>-strtdate ) * 86400
                         + ( <ls_res>-endtime - <ls_res>-strttime ).
    ENDIF.

*   Last error or abort message from the job log of cancelled jobs
    IF <ls_res>-status = 'A'.
      CLEAR lt_log.
      CALL FUNCTION 'BP_JOBLOG_READ'
        EXPORTING
          client    = sy-mandt
          jobcount  = <ls_res>-jobcount
          jobname   = <ls_res>-jobname
        TABLES
          joblogtbl = lt_log
        EXCEPTIONS
          OTHERS    = 1.
      IF sy-subrc = 0.
        LOOP AT lt_log INTO ls_log WHERE msgtype = 'A' OR msgtype = 'E'.
          <ls_res>-lastmsg = ls_log-text.
        ENDLOOP.
      ENDIF.
    ENDIF.
  ENDLOOP.

  TRY.
      cl_salv_table=>factory(
        IMPORTING r_salv_table = lo_alv
        CHANGING  t_table      = lt_result ).
      lo_func = lo_alv->get_functions( ).
      lo_func->set_all( 'X' ).
      lo_alv->display( ).
    CATCH cx_salv_msg INTO lx_msg.
      lv_text = lx_msg->get_text( ).
      MESSAGE lv_text TYPE 'I'.
  ENDTRY.

#### Optional: strict Open SQL variant with INTO at the end (NW 7.40 SP08 and later)

**Body:** * Replace the SELECT above with this form if your release supports it
*  SELECT a~jobname, a~jobcount, a~status, a~strtdate, a~strttime,
*         a~enddate, a~endtime, a~sdluname,
*         b~stepcount, b~progname, b~variant, b~authcknam, b~listident
*    FROM tbtco AS a
*    INNER JOIN tbtcp AS b
*      ON  b~jobname  = a~jobname
*      AND b~jobcount = a~jobcount
*    WHERE a~jobname   LIKE @lv_job
*      AND a~status    IN @lr_status
*      AND a~strtdate  BETWEEN @p_from AND @p_to
*      AND b~progname  LIKE @lv_prog
*      AND b~authcknam IN @lr_user
*    ORDER BY a~strtdate DESCENDING, a~strttime DESCENDING
*    INTO CORRESPONDING FIELDS OF TABLE @lt_result
*    UP TO @p_max ROWS.

**Notes:** Verify in SE11 that TBTCO and TBTCP carry the fields used here on your release and in SE37 that BP_JOBLOG_READ has the CLIENT, JOBCOUNT, JOBNAME and JOBLOGTBL parameters. Jobs that never started have an initial STRTDATE and are excluded by the date filter; select on SDLSTRTDT instead for scheduled jobs. Open SQL on TBTCO and TBTCP does not check batch authorizations, so the report shows every user's jobs: protect it with an authorization group or an AUTHORITY-CHECK on S_BTCH_JOB before you transport it.

## Content

**Intro:** This generator builds an ABAP report for SAP ECC 6.0 that lists background jobs from TBTCO (job header) joined to TBTCP (job steps), filtered by job name, program, status, step user and start date. It adds runtime in seconds and the last error message from the job log of cancelled jobs.

**Sections:**

#### Where job data lives in ECC

**Body:** TBTCO holds one row per job run, keyed by JOBNAME and JOBCOUNT, with the status, the user who scheduled it (SDLUNAME), planned start (SDLSTRTDT, SDLSTRTTM) and actual start and end (STRTDATE, STRTTIME, ENDDATE, ENDTIME). TBTCP holds one row per step, with PROGNAME, VARIANT, the step user AUTHCKNAM and the spool request number LISTIDENT. The job log is not a normal table: it is stored in the TemSe and read with BP_JOBLOG_READ, which returns lines of structure TBTC5. SM37 reads exactly these objects.

**Bullets:**

- Status values in TBTCO-STATUS: P scheduled, S released, Y ready, R active, F finished, A cancelled.
- To find which job runs a program, filter TBTCP-PROGNAME.
- LISTIDENT leads to the spool request in SP01.

#### How to use it

**Body:** Enter the job and program patterns with * as wildcard, choose a status and a start date range, then copy the code into SE38. The selection screen defaults come from your inputs, so the same report can be reused with other values. The generated SELECT uses classic Open SQL without @ host variables so it compiles on every ECC 6.0 NetWeaver release; a strict-syntax version with the INTO clause at the end is included as a comment for 7.40 SP08 and later.

#### Worked example

**Body:** To find every cancelled run of the stock extract this month, set job pattern Z*, program pattern ZMM_STOCK*, status A and dates 20261001 to 20261022. Each result row shows job name, job count, step program and variant, step user, start and end time and runtime_s. The lastmsg column holds the last E or A message from the job log, which is usually the real error, while the final log line is often only the generic job cancelled message.

#### Gotchas

**Body:** A job with several steps returns one row per step, so counts of rows are not counts of jobs. Runtime across midnight works because the date difference is converted to seconds before the time difference is added. TBTCO grows fast on busy systems: keep the date range tight, and make sure the standard reorganisation job SAP_REORG_JOBS runs, otherwise both the report and SM37 slow down. Reading the job log for many cancelled jobs is the slowest part; lower max rows if needed.

**Cta:** If you want Basis and support staff to ask which jobs failed overnight in plain English on your own servers, we can set that up over your ECC system.

**Faq:**

#### Which SAP table stores the background job with program name?

**Answer:** The program name is in TBTCP, field PROGNAME, one row per job step. Join it to TBTCO on JOBNAME and JOBCOUNT to get the job status, scheduler and start and end times. The generated report does this join and lets you filter by program pattern.

#### What is the batch job status table in SAP?

**Answer:** TBTCO holds the job status in field STATUS: P scheduled, S released, Y ready, R active, F finished and A cancelled. Each job run has its own JOBCOUNT, so a periodic job appears once per run. SM37 is the transaction view over the same data.

#### Where is the SAP batch job log stored?

**Answer:** The job log is stored in the TemSe, not as rows in a transparent table you can select directly. Use function module BP_JOBLOG_READ with job name and job count; it returns the log lines in table structure TBTC5 with date, time, message ID, number, type and text.

#### How do I find the batch job that runs a program?

**Answer:** Run the report with the program name in the program pattern and status * for all. Each row shows the job name and step. In SM37 you can also enter the program under the ABAP program name field of the extended selection, which reads TBTCP in the same way.

## Search terms

sap table for batch job with program name, table to check batch job in sap, batch job status table in sap, sap batch job log table, sap how to find batch job for a program, tbtco tbtcp join, sap batch job report

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
