I was surprised that SUIM tx. does not offer such functionality. To keep all the comparison abilities on one place, I placed there buttons calling SUIM comparison tools too.
Because we use also an other PARID/PARVA based custom table with the same structure as USR05, I placed an option also to compare such table. You can add there as much radio buttons as you want.
How does it look like?
Input screen
Result screen
- Red - parameter exists just on one side
- Yellow - parameter exists on both sides, but the actual value differs
- Green - parameter exists on both sides and the value fits
Sorted by Parameter ID
Sorted by equality status
The source code:
*&---------------------------------------------------------------------*
*& Report Y_USER_CMP
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*
REPORT y_user_cmp.
TYPES: BEGIN OF sty_param_both.
TYPES: parid TYPE memoryid. " ID line including both sides, used later for sorting
TYPES: parid1 TYPE abap_bool.
TYPES: parva1 TYPE xuvalue.
TYPES: parid2 TYPE abap_bool. " The second id has to be stored as well because we need to distinguish the case where id is present within both tables, but empty on one side
TYPES: parva2 TYPE xuvalue.
TYPES: partext TYPE as4text.
TYPES: status TYPE c LENGTH 1. " S = successfull comparison, E = id not exists on both sides, W = ID exists but values differ
TYPES: t_color TYPE lvc_t_scol.
TYPES: END OF sty_param_both.
TYPES: tty_param_both TYPE STANDARD TABLE OF sty_param_both.
*----------------------------------------------------------------------*
* CLASS lcl_alv DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_alv DEFINITION.
PUBLIC SECTION.
METHODS:
constructor
IMPORTING
iv_usr1 TYPE xubname
iv_usr2 TYPE xubname
iv_tabname TYPE tabname
it_param TYPE tty_param_both,
generate_alv.
PRIVATE SECTION.
TYPES: BEGIN OF gt_t_heading,
operand(12) TYPE c,
valtyp TYPE char30,
client TYPE char10,
system TYPE char30,
END OF gt_t_heading.
DATA: v_usr1 TYPE xubname,
v_usr2 TYPE xubname,
v_tabname TYPE tabname,
t_param TYPE tty_param_both,
o_salv TYPE REF TO cl_salv_table,
o_header TYPE REF TO cl_salv_form_layout_grid,
o_h_label TYPE REF TO cl_salv_form_label,
o_h_flow TYPE REF TO cl_salv_form_layout_flow,
o_ex TYPE REF TO cx_root.
METHODS:
set_columns,
set_header,
set_rows_color.
ENDCLASS. "lcl_alv DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_alv IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_alv IMPLEMENTATION.
METHOD: constructor.
super->constructor( ).
v_usr1 = iv_usr1.
v_usr2 = iv_usr2.
v_tabname = iv_tabname.
t_param = it_param.
ENDMETHOD. "constructor
METHOD generate_alv.
TRY.
cl_salv_table=>factory(
IMPORTING
r_salv_table = o_salv
CHANGING
t_table = t_param
).
CATCH cx_root INTO o_ex.
MESSAGE o_ex TYPE 'E'.
ENDTRY.
me->set_header( ).
me->set_columns( ).
me->set_rows_color( ).
o_salv->display( ).
ENDMETHOD. "constructor
METHOD set_columns.
DATA: lo_columns TYPE REF TO cl_salv_columns_table,
lo_column TYPE REF TO cl_salv_column_table,
lv_title_s TYPE scrtext_s,
lv_title_m TYPE scrtext_m,
lv_title_l TYPE scrtext_l.
lo_columns = o_salv->get_columns( ).
lo_columns->set_optimize( abap_true ).
TRY.
lv_title_s = v_usr1.
CONCATENATE v_usr1 space 'value' INTO lv_title_m RESPECTING BLANKS.
CONCATENATE v_usr1 space 'value' INTO lv_title_l RESPECTING BLANKS.
lo_column ?= lo_columns->get_column( 'PARVA1' ).
lo_column->set_short_text( lv_title_s ).
lo_column->set_medium_text( lv_title_m ).
lo_column->set_long_text( lv_title_l ).
CLEAR: lv_title_s, lv_title_m, lv_title_l.
lv_title_s = v_usr2.
CONCATENATE v_usr2 space 'value' INTO lv_title_m RESPECTING BLANKS.
CONCATENATE v_usr2 space 'value' INTO lv_title_l RESPECTING BLANKS.
lo_column ?= lo_columns->get_column( 'PARVA2' ).
lo_column->set_short_text( lv_title_s ).
lo_column->set_medium_text( lv_title_m ).
lo_column->set_long_text( lv_title_l ).
lo_column ?= lo_columns->get_column( 'PARID1' ).
lo_column->set_visible( abap_false ).
lo_column ?= lo_columns->get_column( 'PARID2' ).
lo_column->set_visible( abap_false ).
lo_column ?= lo_columns->get_column( 'STATUS' ).
lo_column->set_visible( abap_false ).
CATCH cx_salv_not_found. "#EC NO_HANDLER
ENDTRY.
ENDMETHOD. "set_columns
METHOD set_header.
" Simplified RSUSR050 code for header
DATA: lo_grid TYPE REF TO cl_salv_form_layout_grid,
lo_label TYPE REF TO cl_salv_form_label, "#EC NEEDED
lo_text TYPE REF TO cl_salv_form_text, "#EC NEEDED
lv_row TYPE i,
lv_column TYPE i,
lv_title TYPE c LENGTH 100.
CONCATENATE 'Comparison of user parameters for table ' space v_tabname INTO lv_title RESPECTING BLANKS.
DATA: lt_heading TYPE STANDARD TABLE OF gt_t_heading,
ls_heading LIKE LINE OF lt_heading,
lv_lsind TYPE i.
ls_heading-operand = 'User'.
ls_heading-valtyp = 'Name'.
ls_heading-client = 'Client'.
ls_heading-system = 'System'.
APPEND ls_heading TO lt_heading.
CLEAR ls_heading.
ls_heading-operand = 'A'.
ls_heading-valtyp = v_usr1.
ls_heading-client = sy-mandt.
ls_heading-system = sy-sysid.
APPEND ls_heading TO lt_heading.
CLEAR ls_heading.
ls_heading-operand = 'B'.
ls_heading-valtyp = v_usr2.
ls_heading-client = sy-mandt.
ls_heading-system = sy-sysid.
APPEND ls_heading TO lt_heading.
CLEAR: lv_row, lv_column.
CREATE OBJECT lo_grid.
lo_grid->create_header_information(
row = 1
column = 1
colspan = 20
text = lv_title
).
lo_grid->add_row( ).
READ TABLE lt_heading INTO ls_heading INDEX 1.
lv_column = 11.
lo_label = lo_grid->create_label( row = 3
column = 2
text = ls_heading-operand ).
lo_label = lo_grid->create_label( row = 3
column = 5
text = ls_heading-valtyp ).
lv_column = lv_column + 10.
lo_label = lo_grid->create_label( row = 3
column = lv_column
text = ls_heading-client ).
lv_column = lv_column + 10.
lo_label = lo_grid->create_label( row = 3
column = lv_column
text = ls_heading-system ).
lv_row = 4.
LOOP AT lt_heading INTO ls_heading FROM 2.
lv_column = 11.
lo_text = lo_grid->create_text( row = lv_row
column = 2
text = ls_heading-operand ).
lo_text = lo_grid->create_text( row = lv_row
column = 5
text = ls_heading-valtyp ).
lv_column = lv_column + 10.
lo_text = lo_grid->create_text( row = lv_row
column = lv_column
text = ls_heading-client ).
lv_column = lv_column + 10.
lo_text = lo_grid->create_text( row = lv_row
column = lv_column
text = ls_heading-system ).
lv_row = lv_row + 1.
ENDLOOP.
o_salv->set_top_of_list( lo_grid ).
ENDMETHOD. "set_header
METHOD set_rows_color.
DATA: lo_cols_tab TYPE REF TO cl_salv_columns_table,
lt_s_color TYPE lvc_t_scol,
ls_s_color TYPE lvc_s_scol.
FIELD-SYMBOLS: <fs_param> LIKE LINE OF t_param.
LOOP AT t_param ASSIGNING <fs_param>.
IF ( <fs_param>-parid1 IS INITIAL ) OR ( <fs_param>-parid2 IS INITIAL ).
ls_s_color-color-col = col_negative.
ELSE.
IF ( <fs_param>-parva1 NE <fs_param>-parva2 ).
ls_s_color-color-col = 3. " yellow
ELSE.
ls_s_color-color-col = col_positive.
ENDIF.
ENDIF.
ls_s_color-color-int = 0.
ls_s_color-color-inv = 0.
APPEND ls_s_color TO lt_s_color.
CLEAR ls_s_color.
<fs_param>-t_color = lt_s_color.
CLEAR lt_s_color.
ENDLOOP.
lo_cols_tab = o_salv->get_columns( ).
TRY.
lo_cols_tab->set_color_column( 'T_COLOR' ).
CATCH cx_salv_data_error.
ENDTRY.
ENDMETHOD. "set_rows_color
ENDCLASS. "lcl_alv IMPLEMENTATION
*----------------------------------------------------------------------*
* CLASS lcl_user_cmp DEFINITION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_user_cmp DEFINITION.
PUBLIC SECTION.
METHODS compare_users
IMPORTING iv_usr1 TYPE xubname
iv_usr2 TYPE xubname
iv_tabname TYPE tabname
iv_sort_parid TYPE abap_bool.
CLASS-METHODS get_instance RETURNING value(ro_obj) TYPE REF TO lcl_user_cmp.
CLASS-METHODS check_authorization.
PRIVATE SECTION.
TYPES: tty_param TYPE STANDARD TABLE OF usparam.
CLASS-DATA: o_user_cmp TYPE REF TO lcl_user_cmp.
DATA: o_alv TYPE REF TO lcl_alv.
METHODS get_user_param
IMPORTING iv_usr TYPE xubname
EXPORTING et_param TYPE tty_param.
ENDCLASS. "lcl_user_cmp DEFINITION
*----------------------------------------------------------------------*
* CLASS lcl_user_cmp IMPLEMENTATION
*----------------------------------------------------------------------*
*
*----------------------------------------------------------------------*
CLASS lcl_user_cmp IMPLEMENTATION.
METHOD compare_users.
DATA: lt_param1 TYPE tty_param,
lt_param2 TYPE tty_param,
lt_param_both TYPE STANDARD TABLE OF sty_param_both,
ls_param_both LIKE LINE OF lt_param_both.
me->get_user_param(
EXPORTING
iv_usr = iv_usr1
IMPORTING
et_param = lt_param1
).
me->get_user_param(
EXPORTING
iv_usr = iv_usr2
IMPORTING
et_param = lt_param2
).
FIELD-SYMBOLS: <fs_param> TYPE usparam.
" store whole first table
LOOP AT lt_param1 ASSIGNING <fs_param>.
CLEAR ls_param_both.
ls_param_both-parid = <fs_param>-parid.
ls_param_both-parid1 = abap_true.
ls_param_both-parva1 = <fs_param>-parva.
ls_param_both-partext = <fs_param>-partext.
ls_param_both-status = 'E'. " ID does not fit by default
APPEND ls_param_both TO lt_param_both.
ENDLOOP.
" loop over second param table
LOOP AT lt_param2 ASSIGNING <fs_param>.
CLEAR ls_param_both.
READ TABLE lt_param_both INTO ls_param_both WITH KEY parid = <fs_param>-parid.
IF sy-subrc EQ 0.
" The same ID already exists, alter existing row
ls_param_both-parid2 = abap_true.
ls_param_both-parva2 = <fs_param>-parva.
IF ls_param_both-parva1 EQ <fs_param>-parva.
ls_param_both-status = 'S'.
ELSE.
ls_param_both-status = 'W'.
ENDIF.
MODIFY lt_param_both FROM ls_param_both INDEX sy-tabix TRANSPORTING parid2 parva2 status.
ELSE.
" Insert complete new row
ls_param_both-parid = <fs_param>-parid.
ls_param_both-parid2 = abap_true.
ls_param_both-parva2 = <fs_param>-parva.
ls_param_both-partext = <fs_param>-partext.
ls_param_both-status = 'E'.
APPEND ls_param_both TO lt_param_both.
ENDIF.
ENDLOOP.
IF iv_sort_parid EQ abap_true.
SORT lt_param_both BY parid.
ELSE.
SORT lt_param_both BY status.
ENDIF.
FREE o_alv.
CREATE OBJECT o_alv
EXPORTING
iv_usr1 = iv_usr1
iv_usr2 = iv_usr2
iv_tabname = iv_tabname
it_param = lt_param_both.
o_alv->generate_alv( ).
ENDMETHOD. "compare_users
METHOD get_instance.
IF o_user_cmp IS NOT BOUND.
CREATE OBJECT o_user_cmp.
ENDIF.
ro_obj = o_user_cmp.
ENDMETHOD. "get_instance
METHOD check_authorization.
CLEAR: sy-msgid, sy-msgty, sy-msgno, sy-msgv1, sy-msgv2, sy-msgv3, sy-msgv4.
CALL FUNCTION 'AUTHORITY_CHECK_TCODE'
EXPORTING
tcode = 'SU01D'
EXCEPTIONS
ok = 0
not_ok = 1
OTHERS = 2.
IF sy-subrc <> 0.
IF sy-msgid IS INITIAL OR sy-msgty IS INITIAL.
MESSAGE i172(00) DISPLAY LIKE 'I' WITH sy-tcode.
ELSE.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
DISPLAY LIKE sy-msgty
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.
LEAVE PROGRAM.
ENDIF.
ENDMETHOD. "check_authorization
METHOD get_user_param.
CALL FUNCTION 'SUSR_USER_PARAMETERS_GET'
EXPORTING
user_name = iv_usr
with_text = space
TABLES
user_parameters = et_param
EXCEPTIONS
user_name_not_exist = 1
OTHERS = 2.
ENDMETHOD. "check_authorization
ENDCLASS. "lcl_user_cmp IMPLEMENTATION
DATA: go_user_cmp TYPE REF TO lcl_user_cmp,
gv_tabname TYPE tabname.
TABLES sscrfields.
" Usernames
SELECTION-SCREEN BEGIN OF BLOCK bl_users WITH FRAME TITLE tx_01.
SELECTION-SCREEN BEGIN OF LINE.
SELECTION-SCREEN COMMENT 1(6) tx_02 FOR FIELD p_usr1.
PARAMETERS p_usr1 TYPE xubname MATCHCODE OBJECT user_addr.
SELECTION-SCREEN COMMENT 40(6) tx_03 FOR FIELD p_usr2.
PARAMETERS p_usr2 TYPE xubname MATCHCODE OBJECT user_addr.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK bl_users.
" Table choice
SELECTION-SCREEN BEGIN OF BLOCK bl_tabs WITH FRAME TITLE tx_08.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS r_tab1 RADIOBUTTON GROUP rg1.
SELECTION-SCREEN COMMENT 4(23) tx_04 FOR FIELD r_tab1.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS r_tab2 RADIOBUTTON GROUP rg1.
SELECTION-SCREEN COMMENT 4(23) tx_05 FOR FIELD r_tab2.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK bl_tabs.
" Sort choice
SELECTION-SCREEN BEGIN OF BLOCK bl_sort WITH FRAME TITLE tx_09.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS r_sort1 RADIOBUTTON GROUP rg2.
SELECTION-SCREEN COMMENT 4(24) tx_06 FOR FIELD r_sort1.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN BEGIN OF LINE.
PARAMETERS r_sort2 RADIOBUTTON GROUP rg2.
SELECTION-SCREEN COMMENT 4(24) tx_07 FOR FIELD r_sort2.
SELECTION-SCREEN END OF LINE.
SELECTION-SCREEN END OF BLOCK bl_sort.
SELECTION-SCREEN PUSHBUTTON 1(25) tx_10 USER-COMMAND onli.
************************************************************************
INITIALIZATION.
************************************************************************
" Authorization
lcl_user_cmp=>check_authorization( ).
" Get main class instance
go_user_cmp = lcl_user_cmp=>get_instance( ).
" Screen buttons for SUIM comaprison programs
SELECTION-SCREEN : FUNCTION KEY 1.
SELECTION-SCREEN : FUNCTION KEY 2.
SELECTION-SCREEN : FUNCTION KEY 3.
SELECTION-SCREEN : FUNCTION KEY 4.
" Selection screen texts
tx_01 = 'Compare user parameters for:'.
tx_02 = 'User A'.
tx_03 = 'User B'.
tx_04 = 'User parameters (USR05)'.
tx_05 = 'User parameters (ZPC01)'.
tx_06 = 'Sort by PARAM id (ABC)'.
tx_07 = 'Sort by Differences'.
tx_08 = 'Choose parameter table'.
tx_09 = 'Choose sort'.
tx_10 = 'Compare user parameters'.
sscrfields-functxt_01 = 'Compare Users'.
sscrfields-functxt_02 = 'Roles'.
sscrfields-functxt_03 = 'Profiles'.
sscrfields-functxt_04 = 'Authorizations'.
************************************************************************
AT SELECTION-SCREEN.
************************************************************************
CASE sy-ucomm.
WHEN 'FC01'.
SUBMIT rsusr050 VIA SELECTION-SCREEN USING SELECTION-SET 'SAP&_BENUTZER' AND RETURN.
WHEN 'FC02'.
SUBMIT rsusr050 VIA SELECTION-SCREEN USING SELECTION-SET 'SAP&_ROLLE' AND RETURN.
WHEN 'FC03'.
SUBMIT rsusr050 VIA SELECTION-SCREEN USING SELECTION-SET 'SAP&_PROFILE' AND RETURN.
WHEN 'FC04'.
SUBMIT rsusr050 VIA SELECTION-SCREEN USING SELECTION-SET 'SAP&_BERECHTIG' AND RETURN.
WHEN OTHERS.
IF ( p_usr1 IS INITIAL ) OR ( p_usr2 IS INITIAL ).
MESSAGE e279(01) DISPLAY LIKE 'I'.
ENDIF.
ENDCASE.
************************************************************************
START-OF-SELECTION.
************************************************************************
" Run comparison for table:
CASE abap_true.
WHEN r_tab1.
gv_tabname = 'USR05'.
WHEN r_tab2.
gv_tabname = 'ZUSER_TAB'.
ENDCASE.
go_user_cmp->compare_users( iv_usr1 = p_usr1
iv_usr2 = p_usr2
iv_tabname = gv_tabname
iv_sort_parid = r_sort1
).
END-OF-SELECTION.
No comments:
Post a Comment