CIF Outbound in ERP: Function module CIF_PMORD_SEND
CIF Inbound in APO: Function module /SAPAPO/CIF_MNT_INBOUND
Monday, August 27, 2018
Wednesday, April 4, 2018
Compare ABAP sources remotely
Do remote compare for ABAP sources with transaction SREPO, report RSSYSCOMP.
Friday, February 2, 2018
Compress data with ABAP (ZIP, GZIP)
DATA lv_string TYPE string.
DATA lv_xstring TYPE xstring.
" gzip
cl_abap_gzip=>compress_text(
EXPORTING text_in = lv_string
IMPORTING gzip_out = lv_xstring
).
" unzip
cl_abap_gzip=>decompress_text(
EXPORTING gzip_in = lv_xstring
IMPORTING text_out = lv_string
).
See also methods COMPRESS_BINARY and DECOMPRESS_BINARY of cl_abap_gzip.
DATA lv_xstring TYPE xstring.
" gzip
cl_abap_gzip=>compress_text(
EXPORTING text_in = lv_string
IMPORTING gzip_out = lv_xstring
).
" unzip
cl_abap_gzip=>decompress_text(
EXPORTING gzip_in = lv_xstring
IMPORTING text_out = lv_string
).
See also methods COMPRESS_BINARY and DECOMPRESS_BINARY of cl_abap_gzip.
Robust ABAP to JSON serializer
SAP provides some classes to serialize and deserialize arbitrary ABAP variables. Unfortunately all of them have some disadvantages. The classes are often to complex to use. One method call should be enough to serialize. It is not necessary to call constructor and multiple methods. But a real problem of most classes is, that they just dump for some data constallations, e.g. if the variable contains json Control character like [, ], { or }. Even the colon can cause Problems.
Since the implementaion is easy, we made our own. I am sure that also our own implementation will have bugs... but we can correct them quickly, what is not possible with the SAP's standard classes
class ZCL_JSO_SERIAL definition
public
create public .
public section.
types:
BEGIN OF yt_s_component_value .
TYPES name TYPE string.
TYPES value TYPE string.
TYPES END OF yt_s_component_value .
types:
yt_t_component_value TYPE SORTED TABLE OF yt_s_component_value WITH UNIQUE KEY name .
class-methods SERIALIZE
importing
!I_ABAP type DATA
returning
value(R_V_JSON) type STRING .
class-methods SERIALIZE_CHECK
importing
!I_ABAP type DATA
exporting
!E_V_JSON type STRING
returning
value(R_V_SUCCESS) type ABAP_BOOL .
class-methods DESERIALIZE
importing
!I_V_JSON type STRING
exporting
!E_ABAP type DATA
raising
CX_XSLT_DESERIALIZATION_ERROR .
protected section.
class-methods GET_COMPONENTS_OF_STRUCTURE
importing
!I_V_JSON type STRING
returning
value(R_T_COMPONENT_VALUE) type YT_T_COMPONENT_VALUE
raising
CX_XSLT_DESERIALIZATION_ERROR .
class-methods SPLIT
importing
!I_V_JSON type STRING
!I_V_SPLITTER type CHAR1 default ','
returning
value(R_T_PART) type STRING_TABLE .
class-methods UNPACK
importing
!I_V_JSON type STRING
returning
value(R_V_JSON) type STRING
raising
CX_XSLT_DESERIALIZATION_ERROR .
METHOD serialize.
DATA lv_type.
DATA lv_item_count TYPE i.
DATA lo_structdescr TYPE REF TO cl_abap_structdescr.
DATA lv_index TYPE syindex.
FIELD-SYMBOLS <ls_compdescr> TYPE abap_compdescr.
FIELD-SYMBOLS <lv_item> TYPE any.
FIELD-SYMBOLS <lt_abap> TYPE ANY TABLE.
DESCRIBE FIELD i_abap TYPE lv_type COMPONENTS lv_item_count.
IF lv_type <> cl_abap_typedescr=>typekind_table.
IF lv_item_count = 0.
*** unstructured (plain field)
r_v_json = i_abap. " This assignment can cause problems. Monitor carefully!
r_v_json = |"{ cl_http_utility=>escape_url( r_v_json ) }"|.
ELSE.
*** structured
r_v_json = '{'.
lo_structdescr = CAST #( cl_abap_typedescr=>describe_by_data( i_abap ) ).
LOOP AT lo_structdescr->components ASSIGNING <ls_compdescr>.
lv_index = sy-tabix .
ASSIGN COMPONENT <ls_compdescr>-name OF STRUCTURE i_abap TO <lv_item> .
r_v_json = |{ r_v_json }| &&
|{ to_lower( <ls_compdescr>-name ) }:| &&
|{ serialize( <lv_item> ) }|.
IF lv_index < lv_item_count.
r_v_json = |{ r_v_json },|.
ENDIF .
ENDLOOP .
r_v_json = |{ r_v_json }\}|.
ENDIF.
ELSE.
*** internal table
r_v_json = '['.
ASSIGN i_abap TO <lt_abap>.
LOOP AT <lt_abap> ASSIGNING <lv_item>.
lv_index = sy-tabix .
r_v_json = |{ r_v_json }{ serialize( <lv_item> ) }|.
IF lv_index < lines( <lt_abap> ).
r_v_json = |{ r_v_json },|.
ENDIF .
ENDLOOP.
r_v_json = |{ r_v_json }]|.
ENDIF.
ENDMETHOD.
METHOD deserialize.
DATA lv_type.
DATA lv_item_count TYPE i.
DATA lv_value TYPE string.
DATA lv_json TYPE string.
DATA lo_structdescr TYPE REF TO cl_abap_structdescr.
DATA ls_component TYPE yt_s_component_value.
DATA lt_component TYPE yt_t_component_value.
DATA lt_json TYPE string_table.
DATA lr_row TYPE REF TO data.
FIELD-SYMBOLS <ls_compdescr> TYPE abap_compdescr.
FIELD-SYMBOLS <lv_item> TYPE any.
FIELD-SYMBOLS <lt_abap> TYPE ANY TABLE.
FIELD-SYMBOLS <l_abap> TYPE any.
CLEAR e_abap.
DESCRIBE FIELD e_abap TYPE lv_type COMPONENTS lv_item_count.
IF lv_type <> cl_abap_typedescr=>typekind_table.
IF lv_item_count = 0.
*** unstructured
lv_value = unpack( i_v_json ). " remove quotation marks
lv_value = cl_http_utility=>unescape_url( lv_value ).
e_abap = lv_value.
ELSE. " unstructured i_v_json (plain variable)
*** structured
" get component descriptor for abap object
lo_structdescr = CAST #( cl_abap_typedescr=>describe_by_data( e_abap ) ).
" get list of json components
lt_component = get_components_of_structure( i_v_json ).
" iterate components of abap structure
LOOP AT lo_structdescr->components ASSIGNING <ls_compdescr>.
" assign json components to components of abap structure
ASSIGN COMPONENT <ls_compdescr>-name OF STRUCTURE e_abap TO <lv_item> .
CLEAR ls_component.
READ TABLE lt_component INTO ls_component
WITH TABLE KEY name = to_lower( <ls_compdescr>-name ).
IF sy-subrc = 0.
deserialize(
EXPORTING i_v_json = ls_component-value
IMPORTING e_abap = <lv_item>
).
ELSE.
CLEAR <lv_item>.
ENDIF.
ENDLOOP. " components of structure
ENDIF. " structured i_v_json
ELSE.
*** internal table
" get field symbol for table
ASSIGN e_abap TO <lt_abap>.
" create work area for table
CREATE DATA lr_row LIKE LINE OF <lt_abap>.
ASSIGN lr_row->* TO <l_abap>.
" get table of json strings
lv_json = unpack( i_v_json ). " remove braces [ ]
lt_json = zcl_jso_serial=>split( lv_json ). " split at comma
" iterate json strings and deserialize each
LOOP AT lt_json INTO lv_json.
deserialize(
EXPORTING i_v_json = lv_json
IMPORTING e_abap = <l_abap>
).
INSERT <l_abap> INTO TABLE <lt_abap>. " collect result
ENDLOOP.
ENDIF. " i_v_json contains data of internal table
ENDMETHOD.
METHOD get_components_of_structure.
DATA lv_name TYPE string.
DATA lv_value TYPE string.
DATA lv_s TYPE string.
DATA lt_part TYPE string_table.
" remove braces { }
lv_s = unpack( i_v_json ).
" split at comma
lt_part = zcl_jso_serial=>split( lv_s ).
" split name and value at colon
LOOP AT lt_part INTO lv_s.
SPLIT lv_s AT ':' INTO lv_name lv_value.
INSERT VALUE #( name = lv_name value = lv_value ) INTO TABLE r_t_component_value.
ENDLOOP.
ENDMETHOD.
METHOD split.
DATA lv_i TYPE i.
DATA lv_start TYPE i.
DATA lv_len TYPE i.
DATA lv_c.
DATA lv_b1_count TYPE i.
DATA lv_b2_count TYPE i.
CHECK strlen( i_v_json ) > 0.
lv_i = 0.
lv_start = 0.
lv_len = 0.
WHILE lv_i < strlen( i_v_json ).
lv_c = i_v_json+lv_i(1).
ADD 1 TO lv_len.
IF lv_c = '['. ADD 1 TO lv_b1_count. ENDIF.
IF lv_c = ']'. SUBTRACT 1 FROM lv_b1_count. ENDIF.
IF lv_c = '{'. ADD 1 TO lv_b2_count. ENDIF.
IF lv_c = '}'. SUBTRACT 1 FROM lv_b2_count. ENDIF.
IF ( lv_c = i_v_splitter OR lv_i = strlen( i_v_json ) - 1 ) AND lv_b1_count = 0 AND lv_b2_count = 0.
IF lv_i < strlen( i_v_json ) - 1. SUBTRACT 1 FROM lv_len. ENDIF.
INSERT substring( val = i_v_json off = lv_start len = lv_len ) INTO TABLE r_t_part.
lv_start = lv_i + 1.
lv_len = 0.
ENDIF.
ADD 1 TO lv_i.
ENDWHILE.
ENDMETHOD.
METHOD unpack.
DATA lv_first.
DATA lv_last.
" validity checks
IF strlen( i_v_json ) < 2.
RAISE EXCEPTION TYPE cx_xslt_deserialization_error.
ENDIF.
" get first and last character
lv_first = i_v_json(1).
lv_last = substring( val = i_v_json off = strlen( i_v_json ) - 1 len = 1 ).
IF ( lv_first = '"' AND lv_last = '"' ) OR
( lv_first = '[' AND lv_last = ']' ) OR
( lv_first = '{' AND lv_last = '}' ).
" unpack
r_v_json = substring( val = i_v_json off = 1 len = strlen( i_v_json ) - 2 ).
ELSE.
RAISE EXCEPTION TYPE cx_xslt_deserialization_error.
ENDIF.
ENDMETHOD.
METHOD serialize_check.
DATA lr_abap TYPE REF TO data.
FIELD-SYMBOLS <l_abap> TYPE any.
" create a second variable <l_abap> with the same type like i_abap
CREATE DATA lr_abap LIKE i_abap.
ASSIGN lr_abap->* TO <l_abap>.
TRY.
" serialize i_abap to e_v_json
e_v_json = serialize( i_abap ).
" deserialize e_v_json to <l_abap>
deserialize(
exporting i_v_json = e_v_json
importing e_abap = <l_abap>
).
CATCH cx_xslt_deserialization_error.
r_v_success = abap_false.
RETURN.
ENDTRY.
" now i_abap and <l_abap> shall be equal
IF i_abap = <l_abap>.
r_v_success = abap_true.
ELSE.
r_v_success = abap_false.
ENDIF.
ENDMETHOD.
Since the implementaion is easy, we made our own. I am sure that also our own implementation will have bugs... but we can correct them quickly, what is not possible with the SAP's standard classes
class ZCL_JSO_SERIAL definition
public
create public .
public section.
types:
BEGIN OF yt_s_component_value .
TYPES name TYPE string.
TYPES value TYPE string.
TYPES END OF yt_s_component_value .
types:
yt_t_component_value TYPE SORTED TABLE OF yt_s_component_value WITH UNIQUE KEY name .
class-methods SERIALIZE
importing
!I_ABAP type DATA
returning
value(R_V_JSON) type STRING .
class-methods SERIALIZE_CHECK
importing
!I_ABAP type DATA
exporting
!E_V_JSON type STRING
returning
value(R_V_SUCCESS) type ABAP_BOOL .
class-methods DESERIALIZE
importing
!I_V_JSON type STRING
exporting
!E_ABAP type DATA
raising
CX_XSLT_DESERIALIZATION_ERROR .
protected section.
class-methods GET_COMPONENTS_OF_STRUCTURE
importing
!I_V_JSON type STRING
returning
value(R_T_COMPONENT_VALUE) type YT_T_COMPONENT_VALUE
raising
CX_XSLT_DESERIALIZATION_ERROR .
class-methods SPLIT
importing
!I_V_JSON type STRING
!I_V_SPLITTER type CHAR1 default ','
returning
value(R_T_PART) type STRING_TABLE .
class-methods UNPACK
importing
!I_V_JSON type STRING
returning
value(R_V_JSON) type STRING
raising
CX_XSLT_DESERIALIZATION_ERROR .
METHOD serialize.
DATA lv_type.
DATA lv_item_count TYPE i.
DATA lo_structdescr TYPE REF TO cl_abap_structdescr.
DATA lv_index TYPE syindex.
FIELD-SYMBOLS <ls_compdescr> TYPE abap_compdescr.
FIELD-SYMBOLS <lv_item> TYPE any.
FIELD-SYMBOLS <lt_abap> TYPE ANY TABLE.
DESCRIBE FIELD i_abap TYPE lv_type COMPONENTS lv_item_count.
IF lv_type <> cl_abap_typedescr=>typekind_table.
IF lv_item_count = 0.
*** unstructured (plain field)
r_v_json = i_abap. " This assignment can cause problems. Monitor carefully!
r_v_json = |"{ cl_http_utility=>escape_url( r_v_json ) }"|.
ELSE.
*** structured
r_v_json = '{'.
lo_structdescr = CAST #( cl_abap_typedescr=>describe_by_data( i_abap ) ).
LOOP AT lo_structdescr->components ASSIGNING <ls_compdescr>.
lv_index = sy-tabix .
ASSIGN COMPONENT <ls_compdescr>-name OF STRUCTURE i_abap TO <lv_item> .
r_v_json = |{ r_v_json }| &&
|{ to_lower( <ls_compdescr>-name ) }:| &&
|{ serialize( <lv_item> ) }|.
IF lv_index < lv_item_count.
r_v_json = |{ r_v_json },|.
ENDIF .
ENDLOOP .
r_v_json = |{ r_v_json }\}|.
ENDIF.
ELSE.
*** internal table
r_v_json = '['.
ASSIGN i_abap TO <lt_abap>.
LOOP AT <lt_abap> ASSIGNING <lv_item>.
lv_index = sy-tabix .
r_v_json = |{ r_v_json }{ serialize( <lv_item> ) }|.
IF lv_index < lines( <lt_abap> ).
r_v_json = |{ r_v_json },|.
ENDIF .
ENDLOOP.
r_v_json = |{ r_v_json }]|.
ENDIF.
ENDMETHOD.
METHOD deserialize.
DATA lv_type.
DATA lv_item_count TYPE i.
DATA lv_value TYPE string.
DATA lv_json TYPE string.
DATA lo_structdescr TYPE REF TO cl_abap_structdescr.
DATA ls_component TYPE yt_s_component_value.
DATA lt_component TYPE yt_t_component_value.
DATA lt_json TYPE string_table.
DATA lr_row TYPE REF TO data.
FIELD-SYMBOLS <ls_compdescr> TYPE abap_compdescr.
FIELD-SYMBOLS <lv_item> TYPE any.
FIELD-SYMBOLS <lt_abap> TYPE ANY TABLE.
FIELD-SYMBOLS <l_abap> TYPE any.
CLEAR e_abap.
DESCRIBE FIELD e_abap TYPE lv_type COMPONENTS lv_item_count.
IF lv_type <> cl_abap_typedescr=>typekind_table.
IF lv_item_count = 0.
*** unstructured
lv_value = unpack( i_v_json ). " remove quotation marks
lv_value = cl_http_utility=>unescape_url( lv_value ).
e_abap = lv_value.
ELSE. " unstructured i_v_json (plain variable)
*** structured
" get component descriptor for abap object
lo_structdescr = CAST #( cl_abap_typedescr=>describe_by_data( e_abap ) ).
" get list of json components
lt_component = get_components_of_structure( i_v_json ).
" iterate components of abap structure
LOOP AT lo_structdescr->components ASSIGNING <ls_compdescr>.
" assign json components to components of abap structure
ASSIGN COMPONENT <ls_compdescr>-name OF STRUCTURE e_abap TO <lv_item> .
CLEAR ls_component.
READ TABLE lt_component INTO ls_component
WITH TABLE KEY name = to_lower( <ls_compdescr>-name ).
IF sy-subrc = 0.
deserialize(
EXPORTING i_v_json = ls_component-value
IMPORTING e_abap = <lv_item>
).
ELSE.
CLEAR <lv_item>.
ENDIF.
ENDLOOP. " components of structure
ENDIF. " structured i_v_json
ELSE.
*** internal table
" get field symbol for table
ASSIGN e_abap TO <lt_abap>.
" create work area for table
CREATE DATA lr_row LIKE LINE OF <lt_abap>.
ASSIGN lr_row->* TO <l_abap>.
" get table of json strings
lv_json = unpack( i_v_json ). " remove braces [ ]
lt_json = zcl_jso_serial=>split( lv_json ). " split at comma
" iterate json strings and deserialize each
LOOP AT lt_json INTO lv_json.
deserialize(
EXPORTING i_v_json = lv_json
IMPORTING e_abap = <l_abap>
).
INSERT <l_abap> INTO TABLE <lt_abap>. " collect result
ENDLOOP.
ENDIF. " i_v_json contains data of internal table
ENDMETHOD.
METHOD get_components_of_structure.
DATA lv_name TYPE string.
DATA lv_value TYPE string.
DATA lv_s TYPE string.
DATA lt_part TYPE string_table.
" remove braces { }
lv_s = unpack( i_v_json ).
" split at comma
lt_part = zcl_jso_serial=>split( lv_s ).
" split name and value at colon
LOOP AT lt_part INTO lv_s.
SPLIT lv_s AT ':' INTO lv_name lv_value.
INSERT VALUE #( name = lv_name value = lv_value ) INTO TABLE r_t_component_value.
ENDLOOP.
ENDMETHOD.
METHOD split.
DATA lv_i TYPE i.
DATA lv_start TYPE i.
DATA lv_len TYPE i.
DATA lv_c.
DATA lv_b1_count TYPE i.
DATA lv_b2_count TYPE i.
CHECK strlen( i_v_json ) > 0.
lv_i = 0.
lv_start = 0.
lv_len = 0.
WHILE lv_i < strlen( i_v_json ).
lv_c = i_v_json+lv_i(1).
ADD 1 TO lv_len.
IF lv_c = '['. ADD 1 TO lv_b1_count. ENDIF.
IF lv_c = ']'. SUBTRACT 1 FROM lv_b1_count. ENDIF.
IF lv_c = '{'. ADD 1 TO lv_b2_count. ENDIF.
IF lv_c = '}'. SUBTRACT 1 FROM lv_b2_count. ENDIF.
IF ( lv_c = i_v_splitter OR lv_i = strlen( i_v_json ) - 1 ) AND lv_b1_count = 0 AND lv_b2_count = 0.
IF lv_i < strlen( i_v_json ) - 1. SUBTRACT 1 FROM lv_len. ENDIF.
INSERT substring( val = i_v_json off = lv_start len = lv_len ) INTO TABLE r_t_part.
lv_start = lv_i + 1.
lv_len = 0.
ENDIF.
ADD 1 TO lv_i.
ENDWHILE.
ENDMETHOD.
METHOD unpack.
DATA lv_first.
DATA lv_last.
" validity checks
IF strlen( i_v_json ) < 2.
RAISE EXCEPTION TYPE cx_xslt_deserialization_error.
ENDIF.
" get first and last character
lv_first = i_v_json(1).
lv_last = substring( val = i_v_json off = strlen( i_v_json ) - 1 len = 1 ).
IF ( lv_first = '"' AND lv_last = '"' ) OR
( lv_first = '[' AND lv_last = ']' ) OR
( lv_first = '{' AND lv_last = '}' ).
" unpack
r_v_json = substring( val = i_v_json off = 1 len = strlen( i_v_json ) - 2 ).
ELSE.
RAISE EXCEPTION TYPE cx_xslt_deserialization_error.
ENDIF.
ENDMETHOD.
METHOD serialize_check.
DATA lr_abap TYPE REF TO data.
FIELD-SYMBOLS <l_abap> TYPE any.
" create a second variable <l_abap> with the same type like i_abap
CREATE DATA lr_abap LIKE i_abap.
ASSIGN lr_abap->* TO <l_abap>.
TRY.
" serialize i_abap to e_v_json
e_v_json = serialize( i_abap ).
" deserialize e_v_json to <l_abap>
deserialize(
exporting i_v_json = e_v_json
importing e_abap = <l_abap>
).
CATCH cx_xslt_deserialization_error.
r_v_success = abap_false.
RETURN.
ENDTRY.
" now i_abap and <l_abap> shall be equal
IF i_abap = <l_abap>.
r_v_success = abap_true.
ELSE.
r_v_success = abap_false.
ENDIF.
ENDMETHOD.
Wednesday, December 13, 2017
Neue Berechtigungsgruppen für Tabellen anlegen
Einer Datenbanktabelle (transparenten Tabelle) kann ein Berechtigungsgruppe zugeordnet werden. Wenn eine neue Berechtigungsgruppe angelegt werden soll, kann dies über die Transaktion SE54 "Generierung Tabellensicht" durchgeführt werden. Auf dem Einstiegsbild wird über den Radio Button "Berechtigungsgruppe" ausgewählt. Durch den Button "Anlegen/Ändern" gelangt man in den Pflege-Dialog zum Anlegen von Berechtigungsgruppen für Tabellen.
Siehe auch: SAP Dokumentation "Berechtigungsgruppen pflegen"
Siehe auch: SAP Dokumentation "Berechtigungsgruppen pflegen"
Monday, December 4, 2017
Thursday, May 18, 2017
Using HTML in Dynpro an react on user interactions
The report needs dynpro 2000 with a custom container 'CC' for the HTML control.
REPORT zjso_html_in_dynpro_event.
CLASS lcl_html DEFINITION.
PUBLIC SECTION.
CLASS-DATA: mo_cc TYPE REF TO cl_gui_custom_container.
CLASS-DATA: mo_html TYPE REF TO cl_gui_html_viewer.
CLASS-METHODS: pbo, user_command, leave_screen.
CLASS-METHODS on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
IMPORTING action frame getdata postdata query_table.
ENDCLASS.
START-OF-SELECTION.
CALL SCREEN 2000.
*&---------------------------------------------------------------------*
*& Module STATUS_2000 OUTPUT
*&---------------------------------------------------------------------*
MODULE status_2000 OUTPUT.
SET PF-STATUS '2000'.
SET TITLEBAR '2000'.
lcl_html=>pbo( ).
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_2000 INPUT
*&---------------------------------------------------------------------*
MODULE user_command_2000 INPUT.
lcl_html=>user_command( ).
ENDMODULE.
CLASS lcl_html IMPLEMENTATION.
METHOD pbo.
DATA lv_url TYPE text1024.
DATA lt_html TYPE STANDARD TABLE OF text1024 WITH DEFAULT KEY.
DATA lt_event TYPE cntl_simple_events.
CHECK mo_cc IS NOT BOUND.
lt_html = VALUE #(
( |<!DOCTYPE html><head>| )
( | <meta charset="utf-8">| )
( | <title>HTML in Dynpro</title>| )
( | <style>| )
( ' body { font-family:segoe ui, arial, helvetica; }' )
( | </style>| )
( |<script>| )
( |function onClick(source) \{| )
( | window.location.href = 'SAPEVENT:'+source.innerHTML;| )
( |\}| )
( |</script>| )
( |</head>| )
( |<body>| )
( | <p>Hello, world!</p>| )
( | <a href="SAPEVENT:Hyperlink">Request SAP AS</a>| )
( | <div onclick="onClick(this)" style="width: 120px; height: 120px; margin: 8px; background-color:#ef0000">red</div>| )
( | <div onclick="onClick(this)" style="width: 120px; height: 120px; margin: 8px; background-color:#ffdd00">yellow</div>| )
( | <div onclick="onClick(this)" style="width: 120px; height: 120px; margin: 8px; background-color:#00ee00">green</div>| )
( |</body></html>| )
).
mo_cc = NEW #( 'CC' ).
mo_html = NEW #( mo_cc ).
" setup event handler for SAPEVENT from HTML control
INSERT VALUE #( eventid = mo_html->m_id_sapevent appl_event = abap_true ) INTO TABLE lt_event.
mo_html->set_registered_events( lt_event ).
SET HANDLER on_sapevent FOR mo_html.
" populate HTML control with HTML page
mo_html->load_data(
IMPORTING assigned_url = lv_url
CHANGING data_table = lt_html
).
mo_html->show_url( lv_url ).
ENDMETHOD.
METHOD user_command.
CASE sy-ucomm.
WHEN 'BACK' OR 'EXIT'. leave_screen( ). LEAVE TO SCREEN 0.
WHEN 'BACK' OR 'EXIT'. leave_screen( ). LEAVE PROGRAM.
ENDCASE.
ENDMETHOD.
METHOD leave_screen.
IF mo_cc IS BOUND.
mo_cc->free( ).
ENDIF.
ENDMETHOD.
METHOD on_sapevent.
MESSAGE |onClick = { action }| TYPE 'I'.
" check contents of { postdata } and { query_table } in debugger
ENDMETHOD.
ENDCLASS.
REPORT zjso_html_in_dynpro_event.
CLASS lcl_html DEFINITION.
PUBLIC SECTION.
CLASS-DATA: mo_cc TYPE REF TO cl_gui_custom_container.
CLASS-DATA: mo_html TYPE REF TO cl_gui_html_viewer.
CLASS-METHODS: pbo, user_command, leave_screen.
CLASS-METHODS on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
IMPORTING action frame getdata postdata query_table.
ENDCLASS.
START-OF-SELECTION.
CALL SCREEN 2000.
*&---------------------------------------------------------------------*
*& Module STATUS_2000 OUTPUT
*&---------------------------------------------------------------------*
MODULE status_2000 OUTPUT.
SET PF-STATUS '2000'.
SET TITLEBAR '2000'.
lcl_html=>pbo( ).
ENDMODULE.
*&---------------------------------------------------------------------*
*& Module USER_COMMAND_2000 INPUT
*&---------------------------------------------------------------------*
MODULE user_command_2000 INPUT.
lcl_html=>user_command( ).
ENDMODULE.
CLASS lcl_html IMPLEMENTATION.
METHOD pbo.
DATA lv_url TYPE text1024.
DATA lt_html TYPE STANDARD TABLE OF text1024 WITH DEFAULT KEY.
DATA lt_event TYPE cntl_simple_events.
CHECK mo_cc IS NOT BOUND.
lt_html = VALUE #(
( |<!DOCTYPE html><head>| )
( | <meta charset="utf-8">| )
( | <title>HTML in Dynpro</title>| )
( | <style>| )
( ' body { font-family:segoe ui, arial, helvetica; }' )
( | </style>| )
( |<script>| )
( |function onClick(source) \{| )
( | window.location.href = 'SAPEVENT:'+source.innerHTML;| )
( |\}| )
( |</script>| )
( |</head>| )
( |<body>| )
( | <p>Hello, world!</p>| )
( | <a href="SAPEVENT:Hyperlink">Request SAP AS</a>| )
( | <div onclick="onClick(this)" style="width: 120px; height: 120px; margin: 8px; background-color:#ef0000">red</div>| )
( | <div onclick="onClick(this)" style="width: 120px; height: 120px; margin: 8px; background-color:#ffdd00">yellow</div>| )
( | <div onclick="onClick(this)" style="width: 120px; height: 120px; margin: 8px; background-color:#00ee00">green</div>| )
( |</body></html>| )
).
mo_cc = NEW #( 'CC' ).
mo_html = NEW #( mo_cc ).
" setup event handler for SAPEVENT from HTML control
INSERT VALUE #( eventid = mo_html->m_id_sapevent appl_event = abap_true ) INTO TABLE lt_event.
mo_html->set_registered_events( lt_event ).
SET HANDLER on_sapevent FOR mo_html.
" populate HTML control with HTML page
mo_html->load_data(
IMPORTING assigned_url = lv_url
CHANGING data_table = lt_html
).
mo_html->show_url( lv_url ).
ENDMETHOD.
METHOD user_command.
CASE sy-ucomm.
WHEN 'BACK' OR 'EXIT'. leave_screen( ). LEAVE TO SCREEN 0.
WHEN 'BACK' OR 'EXIT'. leave_screen( ). LEAVE PROGRAM.
ENDCASE.
ENDMETHOD.
METHOD leave_screen.
IF mo_cc IS BOUND.
mo_cc->free( ).
ENDIF.
ENDMETHOD.
METHOD on_sapevent.
MESSAGE |onClick = { action }| TYPE 'I'.
" check contents of { postdata } and { query_table } in debugger
ENDMETHOD.
ENDCLASS.
Tuesday, May 9, 2017
Update IDoc Status
DATA ls_edi_ds TYPE edi_ds.
CLEAR es_edidc.
CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS'
EXPORTING
document_number = iv_docnum
IMPORTING
idoc_control = es_edidc
EXCEPTIONS
document_foreign_lock = 1
document_not_exist = 2
document_number_invalid = 3
document_is_already_open = 4
OTHERS = 5.
IF sy-subrc <> 0.
CLEAR es_edidc.
RETURN.
ENDIF.
ls_edi_ds = VALUE #(
docnum = iv_docnum
status = iv_status
uname = sy-uname
logdat = sy-datum
logtim = sy-uzeit
).
CALL FUNCTION 'EDI_DOCUMENT_STATUS_SET'
EXPORTING
document_number = iv_docnum
idoc_status = ls_edi_ds
IMPORTING
idoc_control = es_edidc
EXCEPTIONS
document_number_invalid = 1
other_fields_invalid = 2
status_invalid = 3
OTHERS = 4.
IF sy-subrc <> 0.
CLEAR es_edidc.
RETURN.
ENDIF.
CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS'
EXPORTING
document_number = iv_docnum
IMPORTING
idoc_control = es_edidc
EXCEPTIONS
document_not_open = 1
failure_in_db_write = 2
parameter_error = 3
status_set_missing = 4
OTHERS = 5.
IF sy-subrc <> 0.
CLEAR es_edidc.
RETURN.
ENDIF.
CLEAR es_edidc.
CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS'
EXPORTING
document_number = iv_docnum
IMPORTING
idoc_control = es_edidc
EXCEPTIONS
document_foreign_lock = 1
document_not_exist = 2
document_number_invalid = 3
document_is_already_open = 4
OTHERS = 5.
IF sy-subrc <> 0.
CLEAR es_edidc.
RETURN.
ENDIF.
ls_edi_ds = VALUE #(
docnum = iv_docnum
status = iv_status
uname = sy-uname
logdat = sy-datum
logtim = sy-uzeit
).
CALL FUNCTION 'EDI_DOCUMENT_STATUS_SET'
EXPORTING
document_number = iv_docnum
idoc_status = ls_edi_ds
IMPORTING
idoc_control = es_edidc
EXCEPTIONS
document_number_invalid = 1
other_fields_invalid = 2
status_invalid = 3
OTHERS = 4.
IF sy-subrc <> 0.
CLEAR es_edidc.
RETURN.
ENDIF.
CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS'
EXPORTING
document_number = iv_docnum
IMPORTING
idoc_control = es_edidc
EXCEPTIONS
document_not_open = 1
failure_in_db_write = 2
parameter_error = 3
status_set_missing = 4
OTHERS = 5.
IF sy-subrc <> 0.
CLEAR es_edidc.
RETURN.
ENDIF.
Monday, March 27, 2017
SAP Tables for Status Handling (in ABAP)
Some important tables concerning status:
JEST Individual Object Status
JCDS Change Documents for System/User Statuses (Table JEST)
JSTO Status object information
TJ02 System Status
TJ02T System status texts
TJ20T Texts for Status Profiles
TJ30T Texts for User Status
JEST Individual Object Status
JCDS Change Documents for System/User Statuses (Table JEST)
JSTO Status object information
TJ02 System Status
TJ02T System status texts
TJ20T Texts for Status Profiles
TJ30T Texts for User Status
Tuesday, February 14, 2017
Wednesday, January 25, 2017
Sending emails from ABAP / E-Mail mit ABAP versenden
* https://wiki.scn.sap.com/wiki/display/Snippets/Sending+mail+with+attachment+using+Object+Oriented+Approach
report zjso_send_email.
class lcl_email definition final.
public section.
class-methods send
importing
iv_subject type so_obj_des
it_message_body type bcsy_text
it_attachment type rmps_t_post_content optional
iv_sender_email type adr6-smtp_addr
it_recipient type uiyt_iusr
raising cx_send_req_bcs cx_document_bcs cx_address_bcs.
endclass.
start-of-selection.
try.
lcl_email=>send(
iv_subject = 'Betreff der E-Mail'(001)
it_message_body = value #(
( line = 'Hallo,'(002) )
( line = ' diese E-Mail wurde aus einem SAP-System verschickt.'(003) )
( line = '' )
( line = 'Mit freundlichen Grüßen'(004) )
)
iv_sender_email = 'marvin.maybe@p1zz4.com'
it_recipient = value #(
mandt = sy-mandt
( email = 'michael.laender@deutsch.de' )
( email = 'ablink@usa.com' )
)
).
write / 'E-Mail erfolgreich versendet'(005).
catch cx_send_req_bcs cx_document_bcs cx_address_bcs into data(go_x).
write / go_x->get_text( ).
endtry.
class lcl_email implementation.
method send.
data lo_send_request type ref to cl_bcs.
data lo_document type ref to cl_document_bcs.
data lo_sender type ref to if_sender_bcs.
data lv_attachment_subject type so_obj_des.
data lo_recipient type ref to if_recipient_bcs.
lo_send_request = cl_bcs=>create_persistent( ).
lo_document = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = it_message_body
i_subject = iv_subject
).
loop at it_attachment into data(ls_attachment).
lv_attachment_subject = ls_attachment-subject.
lo_document->add_attachment(
i_attachment_type = ls_attachment-objtp
i_attachment_subject = lv_attachment_subject
i_att_content_hex = ls_attachment-cont_hex
).
endloop.
lo_send_request->set_document( lo_document ).
lo_sender = cl_cam_address_bcs=>create_internet_address( iv_sender_email ).
lo_send_request->set_sender( lo_sender ).
loop at it_recipient into data(ls_recipient) where email is not initial.
lo_recipient = cl_cam_address_bcs=>create_internet_address( ls_recipient-email ).
lo_send_request->add_recipient( exporting
i_recipient = lo_recipient
i_express = 'X'
).
endloop.
lo_send_request->send( abap_true ).
endmethod.
endclass.
Check transaction SOST after sending an email.
report zjso_send_email.
class lcl_email definition final.
public section.
class-methods send
importing
iv_subject type so_obj_des
it_message_body type bcsy_text
it_attachment type rmps_t_post_content optional
iv_sender_email type adr6-smtp_addr
it_recipient type uiyt_iusr
raising cx_send_req_bcs cx_document_bcs cx_address_bcs.
endclass.
start-of-selection.
try.
lcl_email=>send(
iv_subject = 'Betreff der E-Mail'(001)
it_message_body = value #(
( line = 'Hallo,'(002) )
( line = ' diese E-Mail wurde aus einem SAP-System verschickt.'(003) )
( line = '' )
( line = 'Mit freundlichen Grüßen'(004) )
)
iv_sender_email = 'marvin.maybe@p1zz4.com'
it_recipient = value #(
mandt = sy-mandt
( email = 'michael.laender@deutsch.de' )
( email = 'ablink@usa.com' )
)
).
write / 'E-Mail erfolgreich versendet'(005).
catch cx_send_req_bcs cx_document_bcs cx_address_bcs into data(go_x).
write / go_x->get_text( ).
endtry.
class lcl_email implementation.
method send.
data lo_send_request type ref to cl_bcs.
data lo_document type ref to cl_document_bcs.
data lo_sender type ref to if_sender_bcs.
data lv_attachment_subject type so_obj_des.
data lo_recipient type ref to if_recipient_bcs.
lo_send_request = cl_bcs=>create_persistent( ).
lo_document = cl_document_bcs=>create_document(
i_type = 'RAW'
i_text = it_message_body
i_subject = iv_subject
).
loop at it_attachment into data(ls_attachment).
lv_attachment_subject = ls_attachment-subject.
lo_document->add_attachment(
i_attachment_type = ls_attachment-objtp
i_attachment_subject = lv_attachment_subject
i_att_content_hex = ls_attachment-cont_hex
).
endloop.
lo_send_request->set_document( lo_document ).
lo_sender = cl_cam_address_bcs=>create_internet_address( iv_sender_email ).
lo_send_request->set_sender( lo_sender ).
loop at it_recipient into data(ls_recipient) where email is not initial.
lo_recipient = cl_cam_address_bcs=>create_internet_address( ls_recipient-email ).
lo_send_request->add_recipient( exporting
i_recipient = lo_recipient
i_express = 'X'
).
endloop.
lo_send_request->send( abap_true ).
endmethod.
endclass.
Check transaction SOST after sending an email.
Thursday, December 22, 2016
concerning iDOCs
Transactions
| WE05 | IDOC Liste |
| WE09 | IDOC(Nach IDOCS über Inhalte bzw. Felder suchen) |
| WE20 | Partnevereinbarungen(Verb. Zwischen Belegen und IDOC Generiereung) |
| BD87 | Nachverarbeitung von IDOCS |
| WE19 | Anlage und Verarbeitung von Testidocs(Als Vorlage bestehendes IDOC) |
| WEDI | Überblick |
| WE60 | Dokumention Idoc Struktur |
Tables
| TBDBE | BAPI-ALE Interface for Inbound Processing Function modules to process inbound, per message type |
Function Modules
| BAPI_IDOC_INPUT1 | Inbound BAPI IDoc: Individual Processing |
Friday, December 9, 2016
function module to get list of application servers
call function 'TH_SERVER_LIST'
tables
list = lt_server
exceptions
no_server_list = 1
others = 2.
tables
list = lt_server
exceptions
no_server_list = 1
others = 2.
check with abap which jobs are running
select single jobname
from tbtco
into lv_jobname
where
jobname like lv_jobname_pat and
status = 'R'.
from tbtco
into lv_jobname
where
jobname like lv_jobname_pat and
status = 'R'.
create and start background jobs from abap
data lv_job_was_released type abap_bool.
data lv_ret type i.
data lv_stepcount type btcstepcnt.
call function 'JOB_OPEN'
exporting
jobname = lv_jobname
importing
jobcount = lv_jobcount
changing
ret = lv_ret
exceptions
cant_create_job = 1
invalid_job_data = 2
jobname_missing = 3
others = 4.
if sy-subrc <> 0.
" ...
return.
endif.
* submit (mo_run->ms_run-client_report)
* using selection-set mv_variant
* user sy-uname via job mv_jobname number mv_jobcount
* and return.
* Starting the report with submit, SM37 will display a
* temporary variant 0.. insteat of the created variant
call function 'JOB_SUBMIT'
exporting
authcknam = sy-uname
jobcount = lv_jobcount
jobname = lv_jobname
report = lv_client_report
variant = lv_variant
importing
step_number = lv_stepcount
exceptions
bad_priparams = 1
bad_xpgflags = 2
invalid_jobdata = 3
jobname_missing = 4
job_notex = 5
job_submit_failed = 6
lock_failed = 7
program_missing = 8
prog_abap_and_extpg_set = 9
others = 10.
if sy-subrc <> 0.
" ...
return.
endif.
call function 'JOB_CLOSE'
exporting
jobcount = lv_jobcount
jobname = lv_jobname
targetsystem = lv_server
strtimmed = 'X' " start immediately
importing
job_was_released = lv_job_was_released
changing
ret = lv_ret
exceptions
cant_start_immediate = 1
invalid_startdate = 2
jobname_missing = 3
job_close_failed = 4
job_nosteps = 5
job_notex = 6
lock_failed = 7
invalid_target = 8
others = 9.
if sy-subrc <> 0.
" ...
return.
endif.
data lv_ret type i.
data lv_stepcount type btcstepcnt.
call function 'JOB_OPEN'
exporting
jobname = lv_jobname
importing
jobcount = lv_jobcount
changing
ret = lv_ret
exceptions
cant_create_job = 1
invalid_job_data = 2
jobname_missing = 3
others = 4.
if sy-subrc <> 0.
" ...
return.
endif.
* submit (mo_run->ms_run-client_report)
* using selection-set mv_variant
* user sy-uname via job mv_jobname number mv_jobcount
* and return.
* Starting the report with submit, SM37 will display a
* temporary variant 0.. insteat of the created variant
call function 'JOB_SUBMIT'
exporting
authcknam = sy-uname
jobcount = lv_jobcount
jobname = lv_jobname
report = lv_client_report
variant = lv_variant
importing
step_number = lv_stepcount
exceptions
bad_priparams = 1
bad_xpgflags = 2
invalid_jobdata = 3
jobname_missing = 4
job_notex = 5
job_submit_failed = 6
lock_failed = 7
program_missing = 8
prog_abap_and_extpg_set = 9
others = 10.
if sy-subrc <> 0.
" ...
return.
endif.
call function 'JOB_CLOSE'
exporting
jobcount = lv_jobcount
jobname = lv_jobname
targetsystem = lv_server
strtimmed = 'X' " start immediately
importing
job_was_released = lv_job_was_released
changing
ret = lv_ret
exceptions
cant_start_immediate = 1
invalid_startdate = 2
jobname_missing = 3
job_close_failed = 4
job_nosteps = 5
job_notex = 6
lock_failed = 7
invalid_target = 8
others = 9.
if sy-subrc <> 0.
" ...
return.
endif.
save report variants for jobs
data ls_varid type varid.
data ls_varit type varit.
data lt_varit type standard table of varit with empty key.
ls_varid-mandt = sy-mandt. " Mandant
ls_varid-report = lv_client_report.
ls_varid-variant = lv_variant.
ls_varid-flag1 = ''.
ls_varid-flag2 = ''.
ls_varid-transport = ''.
ls_varid-environmnt = 'B'. " Batch
ls_varid-protected = ''.
ls_varid-secu = ''. " Berechtigungsgruppe
ls_varid-version = ''. " Versionsnummer der Variante
ls_varid-ename = sy-uname.
ls_varid-edat = sy-datum. "
ls_varid-etime = sy-uzeit. "
ls_varid-aename = sy-uname.
ls_varid-aedat = sy-datum.
ls_varid-aetime = sy-uzeit.
ls_varid-mlangu = sy-langu.
ls_varid-xflag1 = ''.
ls_varid-xflag2 = ''.
ls_varit-mandt = sy-mandt.
ls_varit-langu = sy-langu.
ls_varit-report = lv_client_report.
ls_varit-variant = lv_variant.
ls_varit-vtext = |My Variant { sy-datum date = iso } | ??
|{ sy-uzeit time = iso }|.
insert ls_varit into table lt_varit.
call function 'RS_CREATE_VARIANT'
exporting
curr_report = lv_client_report
curr_variant = lv_variant
vari_desc = ls_varid
tables
vari_contents = lt_rsparam
vari_text = lt_varit
exceptions
illegal_report_or_variant = 1
illegal_variantname = 2
not_authorized = 3
not_executed = 4
report_not_existent = 5
report_not_supplied = 6
variant_exists = 7
variant_locked = 8
others = 9.
if sy-subrc = 0.
commit work.
else.
" s...
endif.
data ls_varit type varit.
data lt_varit type standard table of varit with empty key.
ls_varid-mandt = sy-mandt. " Mandant
ls_varid-report = lv_client_report.
ls_varid-variant = lv_variant.
ls_varid-flag1 = ''.
ls_varid-flag2 = ''.
ls_varid-transport = ''.
ls_varid-environmnt = 'B'. " Batch
ls_varid-protected = ''.
ls_varid-secu = ''. " Berechtigungsgruppe
ls_varid-version = ''. " Versionsnummer der Variante
ls_varid-ename = sy-uname.
ls_varid-edat = sy-datum. "
ls_varid-etime = sy-uzeit. "
ls_varid-aename = sy-uname.
ls_varid-aedat = sy-datum.
ls_varid-aetime = sy-uzeit.
ls_varid-mlangu = sy-langu.
ls_varid-xflag1 = ''.
ls_varid-xflag2 = ''.
ls_varit-mandt = sy-mandt.
ls_varit-langu = sy-langu.
ls_varit-report = lv_client_report.
ls_varit-variant = lv_variant.
ls_varit-vtext = |My Variant { sy-datum date = iso } | ??
|{ sy-uzeit time = iso }|.
insert ls_varit into table lt_varit.
call function 'RS_CREATE_VARIANT'
exporting
curr_report = lv_client_report
curr_variant = lv_variant
vari_desc = ls_varid
tables
vari_contents = lt_rsparam
vari_text = lt_varit
exceptions
illegal_report_or_variant = 1
illegal_variantname = 2
not_authorized = 3
not_executed = 4
report_not_existent = 5
report_not_supplied = 6
variant_exists = 7
variant_locked = 8
others = 9.
if sy-subrc = 0.
commit work.
else.
" s...
endif.
Subscribe to:
Posts (Atom)
Working with the session Id // ID für den Modus
Sometimes it can be helpful to know the id of the current session CALL FUNCTION 'TH_GET_CONTEXT_ID' IMPORTING cont...
-
INCLUDE /SAPAPO/OM_ERROR_CODES * Operation erfolgreich durchgeführt om_ok ...
-
GUIDs or UUIDs can be created with the class cl_system_uuid . try . data (lv_uuid) = cl_system_uuid => if_system_uuid_static...
-
Sometimes the backend doesn't return the selected rows of an SALV. For my case get_metadata( ) was the solution: go_salv-> get_met...