[ABAP] Business Application Log (BAL) verwenden

Variante 1 (cf_reca_message_list)

* Kapselt im Paket RE_CA_BC die FuBas der Funktionsgruppe SBAL (Paket SZAL)

* BAL-Message-Collector Objekt anlegen
* id_object:    BAL-Objekttyp (SLG0, SLG1)
* id_subobject: BAL-Unterobjekttyp (SLG0, SLG1)
* id_extnumber: Freitext für spätere Suche in der SLG1, i.d.R. Belegnummern
* id_deldate:   Verfallsdatum der Lognachricht (i.d.R. 30 Tage)
DATA(o_msg_list) = cf_reca_message_list=>create( id_object    = 'Z_TEST_LOG'
                                                 id_subobject = 'Z_TEST_LOG_U1'
                                                 id_extnumber = 'Identifier_01234'
                                                 id_deldate   = CONV #( sy-datum + 30 ) ).
										
* Log-Eintrag dem Message-Objekt hinzufügen
o_msg_list->add( EXPORTING id_msgty = 'I'
                           id_msgid = 'OO'
                           id_msgno = '000'
                           id_msgv1 = 'Text1'
                           id_msgv2 = 'Text2'
                           id_msgv3 = ''
                           id_msgv4 = '' ).

TRY.
* Division durch Null provozieren
    DATA(lv_div) = 1 / 0.
  CATCH cx_root INTO DATA(e_txt).
* Log-Eintrag dem Message-Objekt hinzufügen
    o_msg_list->add_from_exception( e_txt ).
ENDTRY.

* Message-Liste im BAL speichern
o_msg_list->store( ).

* Protokoll als Applikation bzw. Popup anzeigen
CALL FUNCTION 'RECA_GUI_MSGLIST_POPUP'
  EXPORTING
    io_msglist = o_msg_list.

Variante 2 (BAL_LOG_CREATE)

* Paket: SZAL
* Demo: SBAL_DEMO_*
* Vorteil: vollständige Parametrierung über bal_s_log (Externe Identifikation, Verfallsdatum...)
* Link: https://wiki.scn.sap.com/wiki/display/Snippets/Using+Application+Log
CLASS lcl_applog DEFINITION.
  PUBLIC SECTION.

    TYPES:
      BEGIN OF ty_s_msgtext,
        msgv1 TYPE symsgv,
        msgv2 TYPE symsgv,
        msgv3 TYPE symsgv,
        msgv4 TYPE symsgv,
      END OF ty_s_msgtext .

* Message-Typen
    CONSTANTS: co_msg_type_error TYPE symsgty VALUE 'E'.
    CONSTANTS: co_msg_type_warning TYPE symsgty VALUE 'W'.
    CONSTANTS: co_msg_type_info TYPE symsgty VALUE 'I'.

* Problemklassen (Domäne BALPROBCL)
* 1 sehr wichtig
* 2 wichtig
* 3 mittel
* 4 Zusatzinformationen
*   Sonstiges
    CONSTANTS: co_problem_class_high TYPE balprobcl VALUE '1'.
    CONSTANTS: co_problem_class_medium TYPE balprobcl VALUE '2'.
    CONSTANTS: co_problem_class_low TYPE balprobcl VALUE '3'.
    CONSTANTS: co_problem_class_info TYPE balprobcl VALUE '4'.
    CONSTANTS: co_problem_class_other TYPE balprobcl VALUE ' '.

    CLASS-METHODS:
      create
        IMPORTING
                  i_bal_s_log  TYPE bal_s_log
        RETURNING VALUE(rv_ok) TYPE abap_bool.

    CLASS-METHODS:
      add_message
        IMPORTING
                  i_probclass  TYPE balprobcl DEFAULT co_problem_class_info
                  i_msgtype    TYPE symsgty DEFAULT co_msg_type_error
                  i_msgid      TYPE symsgid DEFAULT '01'  " Verwendung der generische Nachrichtenklasse mit & & & &
                  i_msgno      TYPE symsgno DEFAULT '319' " Verwendung der generische Nachrichtenklasse mit & & & &
                  i_msgv1      TYPE symsgv OPTIONAL
                  i_msgv2      TYPE symsgv OPTIONAL
                  i_msgv3      TYPE symsgv OPTIONAL
                  i_msgv4      TYPE symsgv OPTIONAL
        RETURNING VALUE(rv_ok) TYPE abap_bool.

    CLASS-METHODS:
      add_string
        IMPORTING
                  i_probclass  TYPE balprobcl DEFAULT co_problem_class_info
                  i_msgtype    TYPE symsgty DEFAULT co_msg_type_error
                  i_msgid      TYPE symsgid DEFAULT '01'  " Verwendung der generische Nachrichtenklasse mit & & & &
                  i_msgno      TYPE symsgno DEFAULT '319' " Verwendung der generische Nachrichtenklasse mit & & & &
                  i_msg_text   TYPE string
        RETURNING VALUE(rv_ok) TYPE abap_bool.

    CLASS-METHODS:
      add_exception
        IMPORTING
                  i_probclass  TYPE balprobcl DEFAULT co_problem_class_info
                  i_msgtype    TYPE symsgty DEFAULT co_msg_type_error
                  i_exception  TYPE REF TO cx_root
        RETURNING VALUE(rv_ok) TYPE abap_bool.

    CLASS-METHODS:
      save
        RETURNING VALUE(rv_ok) TYPE abap_bool.

    CLASS-METHODS:
      delete
        RETURNING VALUE(rv_ok) TYPE abap_bool.

    CLASS-METHODS:
      display_current
        IMPORTING
          i_title     TYPE baltitle OPTIONAL
          i_it_balnri TYPE ehsky_balnri.

    CLASS-METHODS:
      display
        IMPORTING
          iv_object                    TYPE balhdr-object DEFAULT space
          iv_subobject                 TYPE balhdr-subobject DEFAULT space
          iv_external_number           TYPE balhdr-extnumber DEFAULT space
          iv_object_attribute          TYPE i DEFAULT 0
          iv_subobject_attribute       TYPE i DEFAULT 0
          iv_external_number_attribute TYPE i DEFAULT 0
          iv_date_from                 TYPE balhdr-aldate DEFAULT sy-datum
          iv_time_from                 TYPE balhdr-altime DEFAULT '000000'
          iv_date_to                   TYPE balhdr-aldate DEFAULT sy-datum
          iv_time_to                   TYPE balhdr-altime DEFAULT sy-uzeit
          iv_suppress_selection_dialog TYPE abap_bool DEFAULT abap_false
          iv_title_selection_screen    TYPE char255 DEFAULT space
          iv_title_list_screen         TYPE char255 DEFAULT space.

    CLASS-METHODS:
      has_data
        RETURNING VALUE(rv_has) TYPE abap_bool.

  PRIVATE SECTION.
    CLASS-DATA:
      gv_log_handle TYPE balloghndl.

ENDCLASS.

CLASS lcl_applog IMPLEMENTATION.

* Log erzeugen und Log-Handle ermitteln
  METHOD create.

    rv_ok = abap_false.

    CALL FUNCTION 'BAL_LOG_CREATE'
      EXPORTING
        i_s_log                 = i_bal_s_log
      IMPORTING
        e_log_handle            = gv_log_handle
      EXCEPTIONS
        log_header_inconsistent = 1
        OTHERS                  = 2.

    IF sy-subrc = 0.
      rv_ok = abap_true.
    ENDIF.

  ENDMETHOD.

* Log-Message hinzufügen
* Achtung: Die Stringlänge für die Parameter i_msgv1, i_msgv2, i_msgv3 und i_msgv4 ist jeweils max. 50 Zeichen!
  METHOD add_message.

    rv_ok = abap_false.

    DATA(lv_msg) = VALUE bal_s_msg( probclass = i_probclass
                                    msgty     = i_msgtype
                                    msgid     = i_msgid
                                    msgno     = i_msgno
                                    msgv1     = i_msgv1
                                    msgv2     = i_msgv2
                                    msgv3     = i_msgv3
                                    msgv4     = i_msgv4 ).

    CALL FUNCTION 'BAL_LOG_MSG_ADD'
      EXPORTING
        i_log_handle     = gv_log_handle
        i_s_msg          = lv_msg
      EXCEPTIONS
        log_not_found    = 1
        msg_inconsistent = 2
        log_is_full      = 3
        OTHERS           = 4.

    IF sy-subrc = 0.
      rv_ok = abap_true.
    ENDIF.

  ENDMETHOD.

  METHOD add_string.
    rv_ok = abap_false.

* String (max. 200 Zeichen) -> TY_S_MSGTEXT (msgv1 ... msgv4) (max. 4 x 50 Zeichen) wandeln
    DATA(lv_msg_text) = CONV ty_s_msgtext( i_msg_text ).

    DATA(lv_msg) = VALUE bal_s_msg( probclass = i_probclass
                                    msgty     = i_msgtype
                                    msgid     = i_msgid
                                    msgno     = i_msgno
                                    msgv1     = lv_msg_text-msgv1
                                    msgv2     = lv_msg_text-msgv2
                                    msgv3     = lv_msg_text-msgv3
                                    msgv4     = lv_msg_text-msgv4 ).

* altenativ: Verwendung von FuBa BAL_LOG_MSG_ADD_FREE_TEXT
    CALL FUNCTION 'BAL_LOG_MSG_ADD'
      EXPORTING
        i_log_handle     = gv_log_handle
        i_s_msg          = lv_msg
      EXCEPTIONS
        log_not_found    = 1
        msg_inconsistent = 2
        log_is_full      = 3
        OTHERS           = 4.

    IF sy-subrc = 0.
      rv_ok = abap_true.
    ENDIF.
  ENDMETHOD.

* Log-Message anhand einer Exception hinzufügen
  METHOD add_exception.

    rv_ok = abap_false.

    DATA(lv_ex) = VALUE bal_s_exc( probclass  = i_probclass
                                   msgty      = i_msgtype
                                   exception  = i_exception ).

    CALL FUNCTION 'BAL_LOG_EXCEPTION_ADD'
      EXPORTING
        i_log_handle     = gv_log_handle
        i_s_exc          = lv_ex
      EXCEPTIONS
        log_not_found    = 1
        msg_inconsistent = 2
        log_is_full      = 3
        OTHERS           = 4.

    IF sy-subrc = 0.
      rv_ok = abap_true.
    ENDIF.

  ENDMETHOD.

* akt. Log auf der Datenbank speichern
  METHOD save.

    rv_ok = abap_false.

    DATA: it_log_handle TYPE bal_t_logh.
    APPEND gv_log_handle TO it_log_handle.

* alternativ: Verwendung von FuBa APPL_LOG_WRITE_DB
    CALL FUNCTION 'BAL_DB_SAVE'
      EXPORTING
        i_t_log_handle   = it_log_handle
      EXCEPTIONS
        log_not_found    = 1
        save_not_allowed = 2
        numbering_error  = 3
        OTHERS           = 4.

    IF sy-subrc = 0.
      rv_ok = abap_true.
    ENDIF.

  ENDMETHOD.

* Log-Messages löschen
  METHOD delete.

    rv_ok = abap_false.

    CALL FUNCTION 'BAL_LOG_MSG_DELETE_ALL'
      EXPORTING
        i_log_handle  = gv_log_handle
      EXCEPTIONS
        log_not_found = 1
        OTHERS        = 2.

    IF sy-subrc = 0.
      rv_ok = abap_true.
    ENDIF.

  ENDMETHOD.

* akt. Log anhand Lognumber anzeigen
  METHOD display_current.

    IF sy-batch IS INITIAL.

      DATA: lv_bal_s_prof TYPE bal_s_prof.

      CALL FUNCTION 'BAL_DSP_PROFILE_STANDARD_GET'
        IMPORTING
          e_s_display_profile = lv_bal_s_prof
        EXCEPTIONS
          OTHERS              = 1.

      lv_bal_s_prof-show_all   = abap_true.
      lv_bal_s_prof-cwidth_opt = abap_true.

      DATA(it_lognumbers) = VALUE szal_lognumbers( FOR <l> IN i_it_balnri
                                                   (
                                                      item = <l>-lognumber
                                                   )
                                                 ).

      CALL FUNCTION 'APPL_LOG_DISPLAY_WITH_LOGNO'
        EXPORTING
          title_list_screen   = i_title
          i_s_display_profile = lv_bal_s_prof
        TABLES
          lognumbers          = it_lognumbers
        EXCEPTIONS
          no_authority        = 1
          OTHERS              = 2.
    ENDIF.

  ENDMETHOD.

* SLG1 aufrufen: gesamtes Appl. Log anhand von Suchkriterien anzeigen
  METHOD display.

    CALL FUNCTION 'APPL_LOG_DISPLAY'
      EXPORTING
        object                    = iv_object
        subobject                 = iv_subobject
        external_number           = iv_external_number
        object_attribute          = iv_object_attribute
        subobject_attribute       = iv_subobject_attribute
        external_number_attribute = iv_external_number_attribute
        date_from                 = iv_date_from
        time_from                 = iv_time_from
        date_to                   = iv_date_to
        time_to                   = iv_time_to
        title_selection_screen    = iv_title_selection_screen
        title_list_screen         = iv_title_list_screen
*       COLUMN_SELECTION          = '11112221122   '
        suppress_selection_dialog = iv_suppress_selection_dialog
*       COLUMN_SELECTION_MSG_JUMP = '1'
*       EXTERNAL_NUMBER_DISPLAY_LENGTH       = 20
*       I_S_DISPLAY_PROFILE       =
*       I_VARIANT_REPORT          = ' '
*       I_SRT_BY_TIMSTMP          = ' '
*     IMPORTING
*       NUMBER_OF_PROTOCOLS       =
      EXCEPTIONS
        no_authority              = 1
        OTHERS                    = 2.

  ENDMETHOD.

* sind für das akt. Log Daten verfügbar
  METHOD has_data.

    rv_has = abap_false.

    DATA: lv_statistics TYPE bal_s_scnt.

    CALL FUNCTION 'BAL_LOG_HDR_READ'
      EXPORTING
        i_log_handle  = gv_log_handle
      IMPORTING
        e_statistics  = lv_statistics
      EXCEPTIONS
        log_not_found = 1
        OTHERS        = 2.

    IF sy-subrc = 0.

      CLEAR: lv_statistics-msg_max_pc.

      IF NOT lv_statistics IS INITIAL.
        rv_has = abap_true.
      ENDIF.
    ENDIF.

  ENDMETHOD.

ENDCLASS.
**********************************************************************
*
* PARAMETERS
*
**********************************************************************
PARAMETERS: p_show AS CHECKBOX DEFAULT abap_false.
**********************************************************************
*
* START-OF-SELECTION
*
**********************************************************************
START-OF-SELECTION.
  IF abap_false = p_show.
* Log-Objekte und Subobjekte definieren -> Transaktion SLG0 --> es werden Transportaufträge generiert
* extnumber: Freitext für spätere Suche in der SLG1, i.d.R. Belegnummern
* aldate_del: Verfallsdatum der Lognachricht (i.d.R. 30 Tage)
    DATA(lv_bal_log) = VALUE bal_s_log( object     = 'Z_TEST_LOG'
                                        subobject  = 'Z_TEST_LOG_U1'
                                        extnumber  = 'Identifier_01234'
                                        aldate_del = sy-datum + 30
                                      ).
* Legt eine Protokoll-Instanz an
* Log-Objekte werden in der Transaktion SLG0 definiert -> es werden Transportaufträge generiert
* Anlegen der Objekte erfolgt in den Tabellen
*   BALOBJ (Anwendungs-Log: Objekte)
*   BALSUB (Anwendungs-Log: Unterobjekte)
    IF abap_true = lcl_applog=>create( i_bal_s_log = lv_bal_log ).
* Protokolleinträge hinzufügen -> Nachrichten werden in der Transaktion SE91 gefplegt
* Beispiel: Verwendung der vordefinierten Nachrichtenklasse 'S_AUT', Nr. '128'
      lcl_applog=>add_message( i_probclass = lcl_applog=>co_problem_class_info
                               i_msgtype   = lcl_applog=>co_msg_type_info
                               i_msgid     = 'S_AUT'
                               i_msgno     = '128' ).

* Beispiel: Verwendung der generische Nachrichtenklasse mit & & & & für die Parameter msgv1 - msgv4
      lcl_applog=>add_message( i_probclass = lcl_applog=>co_problem_class_info
                               i_msgtype   = lcl_applog=>co_msg_type_warning
                               i_msgv1     = 'Test1'
                               i_msgv2     = 'Test2'
                               i_msgv3     = 'Test3'
                               i_msgv4     = 'Test4' ).

* Beispiel: Verwendung der generische Nachrichtenklasse mit & & & &
      lcl_applog=>add_string( i_probclass = lcl_applog=>co_problem_class_medium
                              i_msgtype   = lcl_applog=>co_msg_type_error
                              i_msg_text  = 'Testeintrag' ).

      TRY.
* Ausnahme auslösen
          DATA(result) = 1 / 0.

        CATCH cx_root INTO DATA(e_txt).
* Fügt eine Ausnahme hinzu, wobei
* i_probclass: 1 - sehr wichtig
*              2 - wichtig
*              3 - mittel
*              4 - Zusatzinformationen
          lcl_applog=>add_exception( i_probclass = lcl_applog=>co_problem_class_high
                                     i_msgtype   = lcl_applog=>co_msg_type_error
                                     i_exception = e_txt ).
      ENDTRY.

* Schließt und persistiert (speichert) das Protokoll
* Protokoll kann auch in der Transaktion SLG1 angeschaut werden
* Speicherung der Log-Daten erfolgt in den Tabellen
*   BALHDR (Anwendungs-Log: Protokollkopf)
*   BALDAT (Anwendungs-Log: Daten eines Protokolls)
      DATA: it_balnri TYPE ehsky_balnri.

* Log speichern
      IF abap_true = lcl_applog=>save( ).

* Beispiel: Verwendung der generische Nachrichtenklasse mit & & & &
        lcl_applog=>add_string( i_probclass = lcl_applog=>co_problem_class_other
                                i_msgtype   = lcl_applog=>co_msg_type_warning
                                i_msg_text  = 'Testeintrag warning' ).

* Log speichern
        IF abap_true = lcl_applog=>save( ).
* Existieren Meldungen?
          IF abap_true = lcl_applog=>has_data( ).
* Protokoll anzeigen
            lcl_applog=>display_current( i_title     = 'Application-Log'
                                         i_it_balnri = it_balnri ).
          ELSE.
            WRITE: / 'Keine Statistik verfügbar.'.
          ENDIF.
        ELSE.
          WRITE: / 'Fehler beim Speichern des Logs.'.
        ENDIF.
      ELSE.
        WRITE: / 'Fehler beim Speichern des Logs.'.
      ENDIF.
    ELSE.
      WRITE: / 'Fehler beim Erzeugen des Logs.'.
    ENDIF.
  ELSE.
* SLG1 aufrufen
    lcl_applog=>display( iv_object    = 'Z_TEST_LOG'
                         iv_subobject = 'Z_TEST_LOG_U1' ).
  ENDIF.

[ABAP] Quellcode im ABAP-Editor anzeigen und mit Pretty Print überarbeiten

* https://wiki.scn.sap.com/wiki/display/ABAP/Create+your+own+New+Editor+for+BOR+objects
DATA(it_source_code_in) = VALUE stringtab( ).
DATA(it_source_code_out) = VALUE stringtab( ).

* Quelltext des Reports in Stringtab einlesen
READ REPORT sy-repid INTO it_source_code_in.

* Pretty Print für Code durchführen
CALL FUNCTION 'PRETTY_PRINTER'
  EXPORTING
    inctoo             = space
  TABLES
    ntext              = it_source_code_out
    otext              = it_source_code_in
  EXCEPTIONS
    enqueue_table_full = 1
    include_enqueued   = 2
    include_readerror  = 3
    include_writeerror = 4
    OTHERS             = 5.

IF sy-subrc = 0.
* ABAP-Editor im cl_gui_container=>default_screen anzeigen
  DATA(o_editor) = NEW cl_gui_abapedit( parent = cl_gui_container=>default_screen ).
* ReadOnly setzen
  o_editor->set_readonly_mode( 1 ).
* Quelltext setzen
  o_editor->set_text( it_source_code_out ).

* cl_gui_container=>default_screen erzwingen
  WRITE space.
ENDIF.

[ABAP] Profilparameter auslesen

Variante 1 (SXPG_PROFILE_PARAMETER_GET)

DATA: lv_par TYPE tpfyvalue-value.
DATA: lv_ret TYPE i.

CALL FUNCTION 'SXPG_PROFILE_PARAMETER_GET'
  EXPORTING
    parameter_name  = 'DIR_GLOBAL'
  IMPORTING
    parameter_value = lv_par
    ret             = lv_ret.

IF lv_ret = 0.
  WRITE: / lv_par.
ELSE.
  WRITE: / 'Access not allowed.'.
ENDIF.

Variante 2 (TH_GET_PROFILE_VALUE)

DATA: lv_par_value type tpfyvalue-value.

CALL FUNCTION 'TH_GET_PROFILE_VALUE'
  EXPORTING
    name           = 'DIR_GLOBAL'
    server         = space
  IMPORTING
    value          = lv_par_value
  EXCEPTIONS
    internal_error = 1
    too_large      = 2
    not_found      = 3
    OTHERS         = 4.

IF sy-subrc = 0.
  WRITE: / lv_par_value.
ENDIF.

[ABAP] Texttabelle zu einer Tabelle suchen

DATA: lv_tabname TYPE dd08v-tabname.
DATA: lv_for_key TYPE dd08v-fieldname.

* Prüft über die Tabelle DD08L zu Verfügbarkeit einer Texttabelle
* Siehe auch SE11 -> Tabelle anzeigen -> Menü -> Springen -> Texttabelle
CALL FUNCTION 'DDUT_TEXTTABLE_GET'
  EXPORTING
    tabname    = 'TPAR'
  IMPORTING
    texttable  = lv_tabname
    checkfield = lv_for_key.

WRITE: / 'Texttabelle:', lv_tabname.
WRITE: / 'Fremdschlüssel:', lv_for_key.

[ABAP] Datenelement und zugehörige Domäne auslesen

* Name Datenelement
PARAMETERS: p_elem TYPE rollname DEFAULT 'TXT50'.
* Sprachenschlüssel
PARAMETERS: p_lang TYPE ddlanguage DEFAULT 'D'.

SELECT * INTO TABLE @DATA(it_dd04l) FROM dd04l
  WHERE rollname  = @p_elem.

IF sy-subrc = 0.
* Bezeichner zum Datenelent holen
  SELECT * INTO TABLE @DATA(it_dd04t) FROM dd04t
    WHERE rollname   = @p_elem
      AND ddlanguage = @p_lang.

* aktive Domäne holen
  DATA(lv_domname) = it_dd04l[ as4local = 'A' ]-domname.
  SELECT * INTO TABLE @DATA(it_dd01l) FROM dd01l
    WHERE domname = @lv_domname.

* Bezeichner zur Domäne holen
  SELECT * INTO TABLE @DATA(it_dd01t) FROM dd01t
    WHERE domname    = @lv_domname
      AND ddlanguage = @p_lang.

  IF sy-subrc = 0.
    cl_demo_output=>write_data( value = it_dd04l name = |Datenelement: { p_elem }| ).
    cl_demo_output=>write_data( value = it_dd04t name = |Datenelement: { p_elem }| ).
    cl_demo_output=>write_data( value = it_dd01l name = |Domäne: { lv_domname }| ).
    cl_demo_output=>write_data( value = it_dd01t name = |Domäne: { lv_domname }| ).
    cl_demo_output=>display(  ).
  ENDIF.
ENDIF.

Links

[ABAP] Konvertierung einstelliges SAP-Sprachenkürzel <-> zweistellige ISO-Sprache

sy-langu -> ISO

* Variante 1 (CONVERSION_EXIT_ISOLA_OUTPUT)
DATA: lv_iso_lang TYPE laiso.

CALL FUNCTION 'CONVERSION_EXIT_ISOLA_OUTPUT'
  EXPORTING
    input  = sy-langu
  IMPORTING
    output = lv_iso_lang.

WRITE: / |{ sy-langu } -> { lv_iso_lang }|.

* Variante 2 (cl_i18n_languages)
DATA(lv_iso_lang) = cl_i18n_languages=>sap1_to_sap2( im_lang_sap1 = sy-langu ).
WRITE: / lv_iso_lang.

ISO -> sy-langu

* Variante 1 (CONVERSION_EXIT_ISOLA_INPUT)
DATA: lv_iso_lang TYPE laiso VALUE 'DE'.
DATA: lv_lang_r3 TYPE sy-langu.

CALL FUNCTION 'CONVERSION_EXIT_ISOLA_INPUT'
  EXPORTING
    input  = lv_iso_lang
  IMPORTING
    output = lv_lang_r3.

WRITE: / |{ lv_iso_lang } -> { lv_lang_r3 }|.

* Variante 2 (cl_i18n_languages)
DATA(lv_lang_r3) = cl_i18n_languages=>sap2_to_sap1( im_lang_sap2 = 'DE' ).
WRITE: / |{ lv_lang_r3 }|.

[ABAP] HTML-Email versenden

DATA: lv_recipient TYPE adr6-smtp_addr.
DATA: lv_subject TYPE string.

lv_recipient = 'email@email.com'.
lv_subject = 'Testemail'.

DATA(lv_html_text) = VALUE string( ).

lv_html_text = |<BODY> | &&
               |<P><B>Test</B></BR>| &&
               |</BODY>|.

DATA(it_body_txt) = cl_document_bcs=>string_to_soli( ip_string = lv_html_text ).

TRY.
* it_body_txt beinhaltet die Zeilen des Body-Textes
* die Zeilen sind jeweils char255 Zeichen lang
* eine Zeile (line) ist vom Typ SOLI

* Document (Mail) erzeugen
* Email-Subject (i_subject) darf hier max. 50 Zeichen lang sein (Subject-Darstellung in der SOST)
* die "richtige" Übergabe des Email-Subjects erfolgt weiter unten in der Funktion set_message_subject( )
    DATA(o_document) = cl_document_bcs=>create_document( i_type    = 'HTM'
                                                         i_text    = it_body_txt
                                                         i_subject = CONV so_obj_des( lv_subject ) ).

* Sendrequest erzeugen
    DATA(o_send_request) = cl_bcs=>create_persistent( ).
* Email-Subject festlegen, ip_subject ist vom Typ String
    o_send_request->set_message_subject( ip_subject = lv_subject ).
* Die Mail an den Sendrequest hängen
    o_send_request->set_document( o_document ).

* SAP-User als Sender
    DATA(o_sender) = cl_sapuser_bcs=>create( sy-uname ).
* Email-Adresse als Sender
*        DATA(o_sender) = cl_cam_address_bcs=>create_internet_address( i_address_string = 'email@email.com' ).
    o_send_request->set_sender( o_sender ).

* Empfänger -> beachte: u.U. sind Email-Adressen mit Umlauten nicht zulässig -> Exception
    DATA(o_recipient) = cl_cam_address_bcs=>create_internet_address( lv_recipient ).
    o_send_request->add_recipient( i_recipient = o_recipient
                                   i_express = abap_true
                                 " i_copy      = abap_true " CC
                                 " i_blind_copy = abap_true " BCC
                                 ).

* Sofort senden
    o_send_request->set_send_immediately( abap_true ).

* Dokument senden
    IF o_send_request->send( i_with_error_screen = abap_true ) = abap_true.
      WRITE: / 'Email gesendet.'.
    ELSE.
      WRITE: / 'Fehler beim Email-Versand.'.
    ENDIF.

    DATA: lv_in_update_task TYPE sy-subrc.

* Überprüft, ob das Programm im Verbucher abläuft
    CALL FUNCTION 'TH_IN_UPDATE_TASK'
      IMPORTING
        in_update_task = lv_in_update_task.

    IF lv_in_update_task EQ 0.
* Persistenzdienste des Objektes starten, sonst wird ggf. die Mail nicht gesendet
      COMMIT WORK.
    ENDIF.

  CATCH cx_root INTO DATA(e_text).
    WRITE: / e_text->get_text( ).
ENDTRY.

[ABAP] Serverinfo holen

TRY.
    DATA(o_server_info) = NEW cl_server_info( ).

    DATA(lv_startup_time) = o_server_info->get_startup_time( ).

    WRITE: / '       startup time:', lv_startup_time.

    WRITE: / '             worker:'.
    LOOP AT o_server_info->get_worker_list( ) ASSIGNING FIELD-SYMBOL(<w>).
      WRITE: / '                  ',  <w>-logon_id, <w>-logon_type, <w>-logon_hdl, <w>-application, <w>-user_name, <w>-main_program, <w>-wp_program.
    ENDLOOP.

    DATA(lv_release_info) = o_server_info->get_release_info( ).

    WRITE: / '        server name:', lv_release_info->server_name.
    WRITE: / '            release:', lv_release_info->release.
    WRITE: / '       compile date:', lv_release_info->compile_date.
    WRITE: / '       compile time:', lv_release_info->compile_time.
    WRITE: / '         patchlevel:', lv_release_info->patchlevel.
    WRITE: / '        patchnumber:', lv_release_info->patchnumber.
    WRITE: / '           sourceid:', lv_release_info->sourceid.
    WRITE: / 'compatibility_level:', lv_release_info->compatibility_level.
    WRITE: / '       make_variant:', lv_release_info->make_variant.
    WRITE: / '              dblib:', lv_release_info->dblib.
    WRITE: / '       supportlevel:', lv_release_info->supportlevel.

    WRITE: / '       supported OS:'.
    LOOP AT lv_release_info->supported_os ASSIGNING FIELD-SYMBOL(<os>).
      WRITE: / '                    ', <os>.
    ENDLOOP.

    WRITE: / '     supported ABAP:'.
    LOOP AT lv_release_info->supported_abap ASSIGNING FIELD-SYMBOL(<a>).
      WRITE: / '                    ', <a>.
    ENDLOOP.

    WRITE: / '       supported DB:'.
    LOOP AT lv_release_info->supported_db ASSIGNING FIELD-SYMBOL(<db>).
      WRITE: / '                    ', <db>.
    ENDLOOP.

    WRITE: / '      patch comment:'.
    LOOP AT lv_release_info->patchcomment ASSIGNING FIELD-SYMBOL(<p>).
      WRITE: / '                    ', <p>.
    ENDLOOP.
  CATCH cx_root INTO DATA(e_txt).
    WRITE: / e_txt->get_text( ).
ENDTRY.