INITIALIZATION.
  DATA: ls_restrictions TYPE sscr_restrict.
  APPEND VALUE #( name = 'CP' options-cp = abap_true ) TO ls_restrictions-opt_list_tab.
  APPEND VALUE #( kind    = 'S' name    = 'S_GRUND' sg_main = 'I'
                  sg_addy = ' ' op_main = 'CP'      op_addy = 'CP' ) TO ls_restrictions-ass_tab.
  CALL FUNCTION 'SELECT_OPTIONS_RESTRICT'
    EXPORTING
      restriction = ls_restrictions.
Tag: abap
[FI] CALCULATE_TAX_FROM_GROSSAMOUNT
    DATA lt_mwdat TYPE TABLE OF RTAX1U15.
    CALL FUNCTION 'CALCULATE_TAX_FROM_GROSSAMOUNT'
      EXPORTING
        i_bukrs                 = lv_bukrs
        i_mwskz                 = lv_mwskz
*       I_TXJCD                 = ' '
        i_waers                 = lv_waers
        i_wrbtr                 = lv_wrbtr
*     IMPORTING
*       E_FWNAV                 =
*       E_FWNVV                 =
*       E_FWSTE                 =
*       E_FWAST                 =
      TABLES
        t_mwdat                 = lt_mwdat
      EXCEPTIONS
        bukrs_not_found         = 1
        country_not_found       = 2
        mwskz_not_defined       = 3
        mwskz_not_valid         = 4
        account_not_found       = 5
        different_discount_base = 6
        different_tax_base      = 7
        txjcd_not_valid         = 8
        not_found               = 9
        ktosl_not_found         = 10
        kalsm_not_found         = 11
        parameter_error         = 12
        knumh_not_found         = 13
        kschl_not_found         = 14
        unknown_error           = 15
        OTHERS                  = 16.
    IF sy-subrc <> 0 OR lt_mwdat IS INITIAL. 
      RAISE EXCEPTION TYPE zcx_xxx
        EXPORTING
          textid = zcx_xxx=>zcx_xxx
          msgv1  = SWITCH #( sy-subrc
         WHEN 1 THEN 'BUKRS_NOT_FOUND  '
         WHEN 2 THEN 'COUNTRY_NOT_FOUND'
         WHEN 3 THEN 'MWSKZ_NOT_DEFINED'
         WHEN 4 THEN 'MWSKZ_NOT_VALID'
         WHEN 5 THEN 'ACCOUNT_NOT_FOUND'
         WHEN 6 THEN 'DIFFERENT_DISCOUNT_BASE'
         WHEN 7 THEN 'DIFFERENT_TAX_BASE'
         WHEN 8 THEN 'TXJCD_NOT_VALID'
         WHEN 9 THEN 'NOT_FOUND'
         WHEN 10 THEN 'KTOSL_NOT_FOUND'
         WHEN 11 THEN 'KALSM_NOT_FOUND'
         WHEN 12 THEN 'PARAMETER_ERROR'
         WHEN 13 THEN 'KNUMH_NOT_FOUND'
         WHEN 14 THEN 'KSCHL_NOT_FOUND'
         WHEN 15 THEN 'UNKNOWN_ERROR' )
          mtype  = 'E'.
    ENDIF.
[ABAP] commercial rounding
ls_pr00-kbetr = ROUND( val = ls_pr00-kbetr 
                       dec = 2 
                      mode = cl_abap_math=>round_half_up ).
[ABAP] BAPI_PR_CREATE – extensionin
METHOD fill_extension_struc 
    RETURNING value(rt_extin) TYPE bapiparex_t.
    APPEND INITIAL LINE TO rt_extin ASSIGNING FIELD-SYMBOL(<ls_extin>).
    <ls_extin>-structure    = 'BAPI_TE_MEREQITEM'.
    CALL METHOD cl_abap_container_utilities=>fill_container_c
      EXPORTING
        im_value               = is_bapi_te_mereqitem
      IMPORTING
        ex_container           = <ls_extin>+30
      EXCEPTIONS
        illegal_parameter_type = 1
        OTHERS                 = 2.
    IF sy-subrc <> 0.
      CLEAR <ls_extin>.
    ENDIF.
    APPEND INITIAL LINE TO rt_extin ASSIGNING FIELD-SYMBOL(<ls_extinx>).
    <ls_extin>-structure    = 'BAPI_TE_MEREQITEMX'.
    CALL METHOD cl_abap_container_utilities=>fill_container_c
      EXPORTING
        im_value               = is_bapi_te_mereqitemx
      IMPORTING
        ex_container           = <ls_extinx>+30
      EXCEPTIONS
        illegal_parameter_type = 1
        OTHERS                 = 2.
    IF sy-subrc <> 0.
      CLEAR <ls_extin>.
    ENDIF.
  ENDMETHOD.
[ABAP] Send mail using CL_BCS
Find related example reports in package SBCOMS.
 TRY.
        DATA(lo_sender) = cl_sapuser_bcs=>create( sy-uname ).
        DATA(lo_recipient) = cl_cam_address_bcs=>create_internet_address( i_address_string = lv_mailaddress ).
        DATA(lv_html_text) = |<BODY> | &&
                             |<p>Guten Tag,<br>| &&
                             |<br>| &&
                             |Es ist ein Fehler aufgetreten.<br>| &&
                             |Bitte schauen Sie in das Application Log.<br>| &&
                             |<br>| &&
                             |Vielen Dank!</p>| &&
                             |</BODY>|.
        DATA(lo_document) = cl_document_bcs=>create_document( i_type    = 'HTM'
                                                              i_text    = cl_document_bcs=>string_to_soli( ip_string = lv_html_text )
                                                              i_subject = |Fehler| ).
        " Erzeuge Business Communication Service und setze Objekte
        DATA(lo_send_request) = cl_bcs=>create_persistent( ).
        lo_send_request->set_sender( lo_sender ).           " Sender
        lo_send_request->add_recipient( lo_recipient ).     " Empfänger
        lo_send_request->set_document( lo_document ).       " Mailtext
        lo_send_request->set_send_immediately( abap_true ). " Mail sofort senden
        lo_send_request->send( ).                           " Sende Mail!
        COMMIT WORK.                                        " Ohne Commit wird keine Mail in der SOST auftauchen
        " Schreibe Fehler in das Log
      CATCH cx_address_bcs  INTO DATA(lx_address_bsc).
        mr_log->add_exception( i_exception = lx_address_bsc ).
      CATCH cx_send_req_bcs INTO DATA(lx_send_req_bcs).
        mr_log->add_exception( i_exception = lx_send_req_bcs ).
      CATCH cx_document_bcs INTO DATA(lx_document_bcs).
        mr_log->add_exception( i_exception = lx_document_bcs ).
  ENDTRY.
[ABAP] CL_DEMO_OUTPUT
cl_demo_output=>new( )->write_data( lt_display_data )->display( ).
*or
cl_demo_output=>display( lt_display_data ).
[ABAP] Log using CL_BAL_LOGOBJ
 DATA(lr_log) = NEW cl_bal_logobj( i_log_object        = 'ZMM'
                                   i_default_subobject = 'ZMM_LOGGING' ).
 lr_log->add_statustext( i_statustext = |Write a text.| ).
 lr_log->add_exception( lo_excp ).
 lr_log->add_errortext( lo_excp->get_longtext( ) ).
 lr_log->add_msg( i_probclass = '1' ).   "will use sy-msgty sy-msgid sy-msgno sy-msgv1 ...
 lr_log->save( i_client = sy-mandt ).
 lr_log->display( ).
Note: When using on EHP 7.40 you will get some confusing & & around your message texts.
https://tricktresor.de/blog/ausnahmen-mit-t100-nachricht-abap750/
Possible values for i_probclass:

[ABAP] SALV
    TRY.
        cl_salv_table=>factory( IMPORTING r_salv_table = DATA(lo_salv)
                                CHANGING  t_table      = lt_display_data ).
        lo_salv->display( ).
      CATCH cx_salv_msg.
    ENDTRY.
[ABAP] BAPI_ACC_DOCUMENT_POST
How to handle BAPI_ACC_DOCUMENT_POST with a document split at position 980. The method create_document fills the necessary tables and calls post_document, if it reaches position 980, to post the current document. Then the method create_document calls itself recursive for the next positions.
  METHOD create_document.
    DATA: lt_pos                    TYPE TABLE OF bapiacgl09,
          lt_pos_amt                TYPE TABLE OF bapiaccr09.
    gr_listlog->append_log_entry( iv_type = gr_listlog->gc_log_type_info
                                  iv_text = |Beginne Belegerstellung|
                                  iv_alog = abap_true ).
    "Belegkopf
    DATA(ls_documentheader) = VALUE bapiache09( comp_code   = gs_sel-p_bukrs
                                                header_txt  = |header text|
                                                pstng_date  = sy-datum
                                                doc_date    = sy-datum
                                                fisc_year   = sy-datum(4)
                                                fis_period  = sy-datum+4(2)
                                                doc_type    = gs_sel-p_blart
                                                username    = sy-uname ).
    "Fülle Positionen
    LOOP AT it_xxx ASSIGNING FIELD-SYMBOL(<ls_xxx>).
      APPEND VALUE #( itemno_acc     = lines( lt_pos ) + 1
                      gl_account     = <ls_xxx>-hkont
                      stat_con       = abap_false
                      acct_type      = 'S'                      "Sachkonto
                      bus_area       = '0030'
                      fis_period     = sy-datum+4(2)
                      fisc_year      = sy-datum(4)
                      pstng_date     = sy-datum
                      value_date     = sy-datum
                      item_text      = |item text|
                      alloc_nmbr     = <ls_xxx>-zuonr
                      doc_type       = <ls_xxx>-blart
                      comp_code      = <ls_xxx>-bukrs
                      func_area      = '0030'
                      costcenter     = <ls_xxx>-kostl
                      tax_code       = <ls_xxx>-mwskz ) TO lt_pos.
      APPEND VALUE #( itemno_acc   = lines( lt_pos_amt ) + 1
                      curr_type    = '00'                       "Belegwährung
                      currency     = |EUR|
                      amt_doccur   = <ls_xxx>-betrg ) TO lt_pos_amt.
      "Belegsplit notwendig?
      IF lines( lt_pos ) = 980.
        gr_listlog->append_log_entry( iv_type = gr_listlog->gc_log_type_statistic
                                      iv_text = |Belegsplit notwendig!|
                                      iv_alog = abap_true ).
        "Verbuche die aktuellen Positionen
        post_document( is_documentheader = ls_documentheader
                       it_pos            = lt_pos
                       it_pos_amt        = lt_pos_amt ).
        "Rekursiver Aufruf der Methode! Nur mit den Sätzen die noch nicht verarbeitet wurden
        create_document( it_xxx = FILTER #( it_xxx USING KEY sort_key WHERE xxx = xxx ) ).
        "Verlasse bei Rekursion hier
        RETURN.
      ENDIF.
    ENDLOOP.
    "Wenn alle Positionen hinzugefügt, lege den Beleg an
    post_document( is_documentheader = ls_documentheader
                   it_pos            = lt_pos
                   it_pos_amt        = lt_pos_amt ).
  ENDMETHOD.
Calling the BAPI:
  METHOD post_document.
    DATA lt_return            TYPE STANDARD TABLE OF bapiret2.
    IF gs_sel-p_test = abap_true.
      gr_listlog->append_log_entry( iv_type = gr_listlog->gc_log_type_info
                                    iv_text = |Testlauf: Keine Belegbuchung|
                                    iv_alog = abap_true ).
      RETURN. "Im Testlauf hier verlassen
    ENDIF.
    SET UPDATE TASK LOCAL.
    CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
      EXPORTING
        documentheader = is_documentheader
      TABLES
        accountgl      = it_pos
        currencyamount = it_pos_amt
        return         = lt_return.
    "Protokollzeilen mit BAPI Meldungen hinzufügen
    LOOP AT lt_return ASSIGNING FIELD-SYMBOL(<ls_return>).
      gr_listlog->append_log_entry( iv_type = <ls_return>-type
                                    iv_text = CONV #( <ls_return>-message )
                                    iv_alog = abap_true ).
    ENDLOOP.
    "Prüfen, ob eine Fehlermeldung vorliegt
    IF line_exists( lt_return[ type = 'A' ] ) OR line_exists( lt_return[ type = 'E' ] ).
      "Rollback
      CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
    ELSE.
      "Alles gut -> commit
      CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
        EXPORTING
          wait = 'X'.
      "Protokollzeile mit der Erzeugten Belegnummer nochmal explizit ins Log
      DATA(lv_documentnumber) = lt_return[ 1 ]-message_v2(10). "hier steht laut Doku die Belegnummer drin
      gr_listlog->append_log_entry( iv_type = gr_listlog->gc_log_type_success
                                    iv_text = |Belegnummer: { lv_documentnumber }|
                                    iv_alog = abap_true ).
    ENDIF.
  ENDMETHOD.
