Real-World Report — SUBMIT, Variants, Background Jobs, Authority Checks, Message Class

Real-World ABAP Report: SUBMIT, Variants, Background Jobs, Authority Checks
ABAP Reports Series · Blog 14 of 15

A Real-World Report: SUBMIT, Variants, Background Jobs, Authority Checks, Message Class

Intermediate to advanced · 28 min read · Needs Blogs 10 and 11

1. What makes a report production-ready?

A report that works on your test data is not finished. In production, hundreds of users run it, with different permissions, on large data, sometimes at 3 a.m. with nobody watching.

QualityTool in this blog
SecureAuthority checks
Friendly and translatableText elements and message classes
ReusableVariants and SUBMIT
SchedulableBackground jobs and sy-batch
ResilientTRY ... CATCH
Easy to startA transaction code

2. Text elements

Never hard-code text that users read. Text elements live outside the code, so they can be translated and changed without editing logic. In SE38 choose Goto > Text Elements.

KindUsed forIn code
Selection textsLabels of parameters and select-optionsAutomatic (Blog 2)
Text symbolsAny other text in the programTEXT-001
List headingsTitles of classical listsSet in the editor
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
  ...
SELECTION-SCREEN END OF BLOCK b1.

WRITE: / TEXT-002.

3. Message class (SE91)

A message class is a numbered list of messages, kept in SE91. Your code refers to the number, not the text.

  1. Open SE91 and create message class ZSD.
  2. Add messages by number. Use & for values filled in at runtime:
    001 No sales orders found for your selection
    002 You are not authorized for sales organization &1
    003 Maximum rows must be greater than zero
    004 &1 sales order(s) read
  3. Save and activate.
MESSAGE e002(zsd) WITH p_vkorg.        " error, fills &1
MESSAGE s004(zsd) WITH lv_count.       " success in the status bar
MESSAGE s001(zsd) DISPLAY LIKE 'E'. " shown as an error, but no stop
MESSAGE s004(zsd) WITH lv_count INTO lv_text.  " only build the text

The letter after MESSAGE is the message type:

TypeMeaningBehaviour in dialog
SSuccessStatus bar message, program continues
IInformationPopup, program continues after Enter
WWarningStatus bar, user may continue with Enter
EErrorStatus bar. On a selection screen the input stays open. In START-OF-SELECTION the program stops.
AAbortPopup, then the transaction ends
XExitShort dump

The same type behaves differently depending on the event, which is why validation messages belong in AT SELECTION-SCREEN. MESSAGE ... INTO builds the text without showing it, which is useful for logs.

4. Authority checks

Without a check, every user who can start your report sees all data. AUTHORITY-CHECK asks the system whether the user holds a permission.

AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
  ID 'VKORG' FIELD lv_vkorg
  ID 'VTWEG' DUMMY
  ID 'SPART' DUMMY
  ID 'ACTVT' FIELD '03'.         " 03 = display

IF sy-subrc <> 0.
  MESSAGE e002(zsd) WITH lv_vkorg.
ENDIF.
  • sy-subrc = 0: allowed. 4: not allowed. Any other value is a technical problem (for example a wrong field name), so treat every non-zero value as no access.
  • List every field of the object. Use DUMMY for fields you do not want to check. Look up the fields in SU21.
  • Use a standard object where one fits. Create your own in SU21 only when none does.

Where and how often

  • Before reading data. A check after the SELECT means the data was already read.
  • Once per value, not per row. Check each sales organization once, then filter, instead of checking inside the loop.
  • Validate explicit input in AT SELECTION-SCREEN so the user gets the error right away.
An empty range selects everything

If a user may see no sales organization at all, your “allowed” range is empty, and vkorg IN @lt_allowed would return all rows. Always stop the report when the allowed list is empty.

TransactionUse
SU21Display and create authorization objects
SU53Shows the last failed authorization check of a user. Ask the user to run it.
PFCGRoles. Where administrators grant the permission.

5. Report variants

A variant stores the values of a selection screen, so the user does not retype them. A monthly report can have a variant “last month, plant 1000”.

  1. Run the report and fill in the selection screen.
  2. Choose Save (the disk icon or Ctrl+S) and give the variant a name and description.
  3. In the attributes you can protect the variant, hide fields, and use selection variables such as “current date” so the variant never goes out of date.
  4. Load it any time with Get Variant (Shift+F5), or manage them in SE38 under Goto > Variants.

Variants are also what a background job uses to run the report with fixed inputs.

Not the same as ALV layouts

A report variant stores selection screen values. An ALV variant (Blog 10) stores grid layout. Users often confuse them.

6. SUBMIT: calling one report from another

" Run another report and come back
SUBMIT zsales_report AND RETURN.

" With a saved variant
SUBMIT zsales_report USING SELECTION-SET 'MONTHLY' AND RETURN.

" With explicit values
DATA lt_dates TYPE RANGE OF vbak-erdat.
lt_dates = VALUE #( ( sign = 'I' option = 'BT'
                   low  = sy-datum - 30 high = sy-datum ) ).

SUBMIT zsales_report
  WITH s_vkorg = '1000'
  WITH s_erdat IN lt_dates
  AND RETURN.

" Show the selection screen first, with the values pre-filled
SUBMIT zsales_report VIA SELECTION-SCREEN
  WITH s_vkorg = '1000' AND RETURN.
AdditionMeaning
AND RETURNCome back to the calling program afterwards. Without it, the calling program ends.
WITH p = valueFills a parameter
WITH s IN rangeFills a select-option with a range table
WITH SELECTION-TABLE ltA prepared table of type rsparams, for dynamic cases
USING SELECTION-SET 'V'Uses a saved variant
VIA SELECTION-SCREENShows the selection screen to the user
EXPORTING LIST TO MEMORYKeeps the output list instead of showing it

Getting data back

A submitted report cannot return values like a function. Use memory:

" In the called report: put data into ABAP memory
EXPORT orders = gt_orders TO MEMORY ID 'ZSALES_ORDERS'.

" In the calling report: read it, then clean up
SUBMIT zsales_report WITH s_vkorg = '1000' AND RETURN.
IMPORT orders = lt_orders FROM MEMORY ID 'ZSALES_ORDERS'.
FREE MEMORY ID 'ZSALES_ORDERS'.
MemoryStatementsReaches
ABAP memoryEXPORT / IMPORT ... MEMORY IDPrograms in the same call chain of one session
SAP memorySET PARAMETER ID / GET PARAMETER IDAll sessions of the same user logon

The importing variable must have the same type as the exported data, or the import fails.

7. Background processing

In dialog mode, a work process has a time limit, so long reports time out. A background job has no such limit and needs no user at the screen.

  1. Quick way: on the selection screen choose Program > Execute in Background (F9).
  2. Scheduled: in SM36 define the job: name, step (program and variant), and start time or repeat period.
  3. Monitor: in SM37 check the job status, the job log, and the spool output.
SM36 and SM35 are different

SM36 schedules jobs. SM35 is for batch input sessions, an older data upload technique. Do not mix them up.

Rules for background-safe reports

  • Detect the mode with sy-batch: it is 'X' in a background job.
  • Do not rely on popups. A type I or W message only goes to the job log, and an E or A message cancels the job.
  • Do not use interactive features such as GET CURSOR or AT LINE-SELECTION.
  • Output goes to the spool. REUSE_ALV_GRID_DISPLAY switches to a list automatically in background.
  • Do not depend on OBLIGATORY inputs the user must correct. Use a variant with all values set.
IF sy-batch = abap_true.
  WRITE: / lv_text.                       " ends up in the spool
ELSE.
  MESSAGE s004(zsd) WITH lv_count.      " status bar for the user
ENDIF.

Scheduling from code

DATA: lv_jobname  TYPE tbtcjob-jobname VALUE 'Z_SALES_NIGHTLY',
      lv_jobcount TYPE tbtcjob-jobcount.

CALL FUNCTION 'JOB_OPEN'
  EXPORTING jobname  = lv_jobname
  IMPORTING jobcount = lv_jobcount
  EXCEPTIONS OTHERS   = 1.
IF sy-subrc <> 0. RETURN. ENDIF.

SUBMIT zsales_report USING SELECTION-SET 'MONTHLY'
  VIA JOB lv_jobname NUMBER lv_jobcount
  AND RETURN.

CALL FUNCTION 'JOB_CLOSE'
  EXPORTING jobname   = lv_jobname
            jobcount  = lv_jobcount
            strtimmed = abap_true       " start immediately
  EXCEPTIONS OTHERS    = 1.

8. Error handling with TRY / CATCH

Many runtime errors are class-based exceptions. Catch them to keep the report running, or to give a clear message instead of a short dump.

TRY.
    DATA(ls_order) = lt_orders[ vbeln = lv_vbeln ].
    DATA(lv_avg)   = lv_total / lines( lt_orders ).
  CATCH cx_sy_itab_line_not_found.
    MESSAGE s001(zsd) DISPLAY LIKE 'E'.
  CATCH cx_sy_zerodivide INTO DATA(lx_div).
    MESSAGE lx_div->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
ENDTRY.
ExceptionRaised when
CX_SY_ITAB_LINE_NOT_FOUNDA table expression finds no row
CX_SY_ZERODIVIDEDivision by zero
CX_SY_CONVERSION_ERROR (and subclasses)A value cannot be converted
  • lx->get_text( ) returns a readable message.
  • Catch the specific exception. Catching CX_ROOT hides real bugs, so use it only at the top level.
  • Function modules use classical EXCEPTIONS and sy-subrc. Class methods use class-based exceptions.

9. Transaction code and transport

  1. Open SE93, enter a name such as ZSALES_RPT, and click Create.
  2. Choose Program and selection screen (report transaction) and enter the report name.
  3. Save. Users can now start the report by typing the code. Access is controlled through the role (S_TCODE) in PFCG, in addition to your own authority check.

Changes move through the landscape by transport request, created and released in SE09 or SE10: development, then quality, then production.

Never edit in production

Fix the problem in development, test it in quality, and transport it. Variants, message classes and text elements are separate objects: check that they travel with the report. Ask your Basis team how variants are handled in your landscape.

10. The complete production-ready report

This report brings the series together: selection screen, text elements, message class ZSD, authority check, background-safe messages, error handling, and ALV. It uses the structure ZST_VBAK from Blog 5.

REPORT zsales_report_prod.

*---------------------------------------------------------------------*
* Text symbols: 001 = Selection
* Message class ZSD: 001 no data, 002 not authorized (&1),
*                    003 max rows, 004 &1 order(s) read
*---------------------------------------------------------------------*
TYPES: ty_orders_t TYPE STANDARD TABLE OF zst_vbak WITH DEFAULT KEY,
       ty_vkorg_r  TYPE RANGE OF vbak-vkorg,
       ty_erdat_r  TYPE RANGE OF vbak-erdat.

DATA: gv_erdat TYPE vbak-erdat,
      gv_vkorg TYPE vbak-vkorg.

SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
  SELECT-OPTIONS: s_erdat FOR gv_erdat OBLIGATORY,
                  s_vkorg FOR gv_vkorg.
  PARAMETERS     p_max   TYPE i DEFAULT 1000.
SELECTION-SCREEN END OF BLOCK b1.

*---------------------------------------------------------------------*
CLASS lcl_report DEFINITION FINAL.
  PUBLIC SECTION.
    METHODS:
      is_authorized  IMPORTING iv_vkorg TYPE vbak-vkorg
                     RETURNING VALUE(rv_ok) TYPE abap_bool,
      get_data       IMPORTING it_erdat TYPE ty_erdat_r
                               it_vkorg TYPE ty_vkorg_r
                               iv_max   TYPE i,
      display.
  PRIVATE SECTION.
    DATA mt_orders TYPE ty_orders_t.
    METHODS:
      get_allowed_vkorg RETURNING VALUE(rt_range) TYPE ty_vkorg_r,
      notify            IMPORTING iv_no TYPE symsgno
                                  iv_v1 TYPE string OPTIONAL.
ENDCLASS.

CLASS lcl_report IMPLEMENTATION.

  METHOD is_authorized.
    AUTHORITY-CHECK OBJECT 'V_VBAK_VKO'
      ID 'VKORG' FIELD iv_vkorg
      ID 'VTWEG' DUMMY
      ID 'SPART' DUMMY
      ID 'ACTVT' FIELD '03'.
    rv_ok = xsdbool( sy-subrc = 0 ).
  ENDMETHOD.

  METHOD get_allowed_vkorg.
    " Check each sales organization once, not once per order
    SELECT vkorg FROM tvko INTO TABLE @DATA(lt_all).
    LOOP AT lt_all INTO DATA(ls_org).
      IF is_authorized( ls_org-vkorg ) = abap_true.
        APPEND VALUE #( sign = 'I' option = 'EQ' low = ls_org-vkorg ) TO rt_range.
      ENDIF.
    ENDLOOP.
  ENDMETHOD.

  METHOD notify.
    " Dialog: status bar. Background: write to the spool.
    MESSAGE ID 'ZSD' TYPE 'S' NUMBER iv_no WITH iv_v1 INTO DATA(lv_text).
    IF sy-batch = abap_true.
      WRITE: / lv_text.
    ELSE.
      MESSAGE ID 'ZSD' TYPE 'S' NUMBER iv_no WITH iv_v1
              DISPLAY LIKE 'E'.
    ENDIF.
  ENDMETHOD.

  METHOD get_data.
    DATA(lt_allowed) = get_allowed_vkorg( ).

    " An empty allowed list would select EVERYTHING: stop instead
    IF lt_allowed IS INITIAL.
      notify( iv_no = '002' iv_v1 = '*' ).
      RETURN.
    ENDIF.

    SELECT vbeln, erdat, ernam, vbtyp, netwr, waerk
      FROM vbak
      WHERE erdat IN @it_erdat
        AND vkorg IN @it_vkorg
        AND vkorg IN @lt_allowed
      ORDER BY erdat DESCENDING, vbeln
      INTO CORRESPONDING FIELDS OF TABLE @mt_orders
      UP TO @iv_max ROWS.

    IF sy-subrc <> 0.
      notify( '001' ).
    ENDIF.
  ENDMETHOD.

  METHOD display.
    IF mt_orders IS INITIAL.
      RETURN.
    ENDIF.

    DATA(lv_repid)  = sy-repid.
    DATA(ls_layout) = VALUE slis_layout_alv( zebra = 'X' colwidth_optimize = 'X' ).
    DATA(ls_variant) = VALUE disvariant( report = lv_repid ).

    " In a background job ALV switches to a list for the spool automatically
    CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
      EXPORTING
        i_callback_program = lv_repid
        i_structure_name   = 'ZST_VBAK'
        is_layout          = ls_layout
        i_save             = 'A'
        is_variant         = ls_variant
      TABLES
        t_outtab           = mt_orders
      EXCEPTIONS
        program_error      = 1
        OTHERS             = 2.

    IF sy-subrc = 0.
      notify( iv_no = '004' iv_v1 = |{ lines( mt_orders ) }| ).
    ENDIF.
  ENDMETHOD.

ENDCLASS.

*---------------------------------------------------------------------*
DATA go_report TYPE REF TO lcl_report.

INITIALIZATION.
  go_report = NEW #( ).
  s_erdat-sign = 'I'. s_erdat-option = 'BT'.
  s_erdat-low  = sy-datum - 30. s_erdat-high = sy-datum.
  APPEND s_erdat.

AT SELECTION-SCREEN.
  " Validate only on execute, so users can still click and edit
  IF sy-ucomm = 'ONLI'.
    IF p_max <= 0.
      MESSAGE e003(zsd).
    ENDIF.
    LOOP AT s_vkorg INTO DATA(ls_vkorg) WHERE sign = 'I' AND option = 'EQ'.
      IF go_report->is_authorized( ls_vkorg-low ) = abap_false.
        MESSAGE e002(zsd) WITH ls_vkorg-low.
      ENDIF.
    ENDLOOP.
  ENDIF.

START-OF-SELECTION.
  TRY.
      go_report->get_data( it_erdat = s_erdat[]
                           it_vkorg = s_vkorg[]
                           iv_max   = p_max ).
      go_report->display( ).
    CATCH cx_sy_open_sql_error INTO DATA(lx_sql).
      MESSAGE lx_sql->get_text( ) TYPE 'S' DISPLAY LIKE 'E'.
  ENDTRY.
Setup checklist before you run it
  • Structure ZST_VBAK exists and is active (Blog 5).
  • Message class ZSD has messages 001 to 004 (section 3).
  • Text symbol 001 exists. Selection texts are set for the three fields.
  • Your test user has authorization object V_VBAK_VKO for at least one sales organization. Check with SU53 if the report stops.
  • Run it normally, then with F9 in the background and look at the spool in SM37.
  • Create transaction ZSALES_RPT in SE93.

11. Try it yourself

  • Create message class ZSD with the four messages and replace any hard-coded text.
  • Test the report with a user who lacks authorization and read the failed check in SU53.
  • Save a variant, then call the report with SUBMIT ... USING SELECTION-SET.
  • Schedule the report in SM36 and read the spool in SM37.
  • Create a transaction code in SE93 and start the report from it.

12. Common mistakes

  • Hard-coded text instead of text elements or message classes.
  • No authority check, so every user sees all data.
  • Authority check after the SELECT. The data was already read.
  • An empty “allowed” range used in IN. It selects everything.
  • SUBMIT without AND RETURN. The calling program ends.
  • Relying on popups in a background job. Nobody sees them. Write to the spool or job log.
  • An error message that cancels the job where a logged warning would do.
  • Not handling sy-subrc after CALL FUNCTION.
  • Forgetting FREE MEMORY ID after IMPORT.
  • Editing variants or code directly in production instead of transporting.

Up next: Blog 15

What’s Next. SALV, CDS views, RAP, ABAP Development Tools, unit testing, and your learning roadmap.

ABAP Reports: Zero to Hero · Blog 14 of 15
WhatsApp WhatsApp us
Call Now Button