I had the problem on a DEV-environment that the PY-results were a mess. I had double keys in the PCL2 table that made it impossible to remove the data via the standard SAP-programs RPUDEL20 or RPCDPU01.
That is why I created my own program that is based on the Logical database PNP.
Please handle with care, you don't want to execute this program on you Productive-systems
REPORT ZHR_DEL_PY.
TABLES: pernr.
DATA: BEGIN OF rgdir OCCURS 0.
INCLUDE STRUCTURE pc261.
DATA: END OF rgdir.
DATA: C_PERNR(8), C_SEQNR(5).
DATA: SORTFIELD(40).
RANGES: SORTFD FOR SORTFIELD.
START-OF-SELECTION.
GET PERNR.
* READ THE RGDIR
REFRESH RGDIR.
CALL FUNCTION 'CU_READ_RGDIR'
EXPORTING
persnr = pernr-pernr
no_authority_check = 'X'
TABLES
in_rgdir = rgdir
EXCEPTIONS
no_record_found = 1
OTHERS = 2.
LOOP AT rgdir.
MOVE pernr-pernr TO C_PERNR.
MOVE rgdir-SEQNR TO C_SEQNR.
CONCATENATE C_PERNR C_SEQNR INTO SORTFD-LOW.
SORTFD-SIGN = 'I'. "in
SORTFD-OPTION = 'EQ'. "equal
APPEND SORTFD.
ENDLOOP.
CHECK SY-SUBRC = 0.
DELETE FROM PCL2
WHERE RELID = 'RB'
AND SRTFD IN SORTFD.
DELETE FROM PCL2
WHERE RELID = '$$'
AND SRTFD IN SORTFD.
DELETE FROM PCL2
WHERE RELID = 'CU'
AND SRTFD = pernr-pernr.
IF SY-SUBRC = 0.
LOOP AT RGDIR.
DELETE FROM HRPY_RGDIR WHERE
PERNR = pernr-pernr AND
SEQNR = rgdir-SEQNR.
DELETE FROM HRPY_WPBP WHERE
PERNR = pernr-pernr AND
SEQNR = RGDIR-SEQNR.
DELETE FROM HRPY_GROUPING WHERE
PERNR = pernr-pernr AND
SEQNR = RGDIR-SEQNR.
DELETE FROM P01O_ZVB_RR WHERE
PERNR = pernr-pernr AND
EAPER = RGDIR-FPPER.
ENDLOOP.
ENDIF.
COMMIT WORK.
WRITE: / 'You deleted <', pernr-pernr, '>'.
END-OF-SELECTION.
donderdag 16 december 2010
Example subroutine programming: Delete content of a table
Below you can find an example of dynamically creating source-code.
For my example, I created a program that allows you to fill in a tablename and that removes all the content of the table that you've filled in.
Don't try this @ home, unless you know what you are doing.
REPORT ZHR_DELETE_TABLE_CONTENT.
DATA: lt_code(100) TYPE c OCCURS 0 WITH HEADER LINE,
lv_repid LIKE sy-repid,
mess TYPE string,
sid TYPE string.
PARAMETERS: p_table TYPE string OBLIGATORY.
INITIALIZATION.
IF sy-uname NE 'VERSTOCT'.
MESSAGE 'PROGRAM NOT ALLOWED FOR THIS USER' TYPE 'E'.
ENDIF.
IF sy-sysid NE 'DEV'.
MESSAGE 'PROGRAM NOT ALLOWED ON THIS SYSTEM' TYPE 'E'.
ENDIF.
START-OF-SELECTION.
REFRESH lt_code.
lt_code = 'PROGRAM TEMP.'.
APPEND lt_code.
lt_code = 'FORM DELETE_TAB.'.
APPEND lt_code.
CONCATENATE 'DELETE FROM' p_table '.' INTO lt_code SEPARATED BY space.
APPEND lt_code.
MOVE 'COMMIT WORK.' TO lt_code.
APPEND lt_code.
lt_code = 'ENDFORM.'.
APPEND lt_code.
GENERATE SUBROUTINE POOL lt_code NAME lv_repid
MESSAGE mess
SHORTDUMP-ID sid.
PERFORM ('DELETE_TAB') IN PROGRAM (lv_repid).
WRITE: / 'The content of table <', p_table, '> is gone.'.
For my example, I created a program that allows you to fill in a tablename and that removes all the content of the table that you've filled in.
Don't try this @ home, unless you know what you are doing.
REPORT ZHR_DELETE_TABLE_CONTENT.
DATA: lt_code(100) TYPE c OCCURS 0 WITH HEADER LINE,
lv_repid LIKE sy-repid,
mess TYPE string,
sid TYPE string.
PARAMETERS: p_table TYPE string OBLIGATORY.
INITIALIZATION.
IF sy-uname NE 'VERSTOCT'.
MESSAGE 'PROGRAM NOT ALLOWED FOR THIS USER' TYPE 'E'.
ENDIF.
IF sy-sysid NE 'DEV'.
MESSAGE 'PROGRAM NOT ALLOWED ON THIS SYSTEM' TYPE 'E'.
ENDIF.
START-OF-SELECTION.
REFRESH lt_code.
lt_code = 'PROGRAM TEMP.'.
APPEND lt_code.
lt_code = 'FORM DELETE_TAB.'.
APPEND lt_code.
CONCATENATE 'DELETE FROM' p_table '.' INTO lt_code SEPARATED BY space.
APPEND lt_code.
MOVE 'COMMIT WORK.' TO lt_code.
APPEND lt_code.
lt_code = 'ENDFORM.'.
APPEND lt_code.
GENERATE SUBROUTINE POOL lt_code NAME lv_repid
MESSAGE mess
SHORTDUMP-ID sid.
PERFORM ('DELETE_TAB') IN PROGRAM (lv_repid).
WRITE: / 'The content of table <', p_table, '> is gone.'.
GENERATE_SUBPOOL_DIR_FULL in cl_alv_table_create=>create_dynamic_table
Because the standard SAP method "Create_dynamic_table" can give the runtime error GENERATE_SUBPOOL_DIR_FULL, it should be avoided to use it.
Instead use the code below,
CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
EXPORTING
i_structure_name = 'YSDXX_CLST_DATA'
CHANGING
ct_fieldcat = lta_fcat.
CALL METHOD cl_alv_table_create=>create_dynamic_table
EXPORTING
it_fieldcatalog = lta_fcat
IMPORTING
ep_table = dr_content.
Instead use the code below,
lo_struct ?= cl_abap_typedescr=>describe_by_name( 'YSDXX_CLST_DATA' ).
lt_comp = lo_struct->get_components( ).
APPEND LINES OF lt_comp TO lt_tot_comp.
l_struc = cl_abap_structdescr=>create( lt_tot_comp ).
l_struc_table = cl_abap_tabledescr=>create(
p_line_type = l_struc
p_table_kind = cl_abap_tabledescr=>tablekind_std
p_unique = abap_false ).
CREATE DATA lw_global_data-datatab TYPE HANDLE l_struc_table.
maandag 8 november 2010
shortdump GENERATE_SUBPOOL_DIR_FULL
There's a limit on the number of sub-routines that can be generated within a program. This limit is 36 and anythng over this will create a short-dump(GENERATE_SUBPOOL_DIR_FULL).
The reason why SAP has put this limitation on it is, is to avoid an overflow of the program memory. Changing this number is not possible because it is a kernel constant and therefore, not variable and removing memory segments from the PXA is currently not supported by the kernel...
So you need to look for another solution.
There are 2 main reasons why you would want to generate a subroutine:
1. To create a dynamic structure
2. To create a dynamic program
Let me give you the solution for those 2 types of creating subroutines.
1. Create a dynamic structure:
Old Code
DATA: lt_code(100) TYPE c OCCURS 0 WITH HEADER LINE,
lv_type(100),
lv_repid LIKE sy-repid,
lw_fcat TYPE lvc_s_fcat.
* DYNAMISCH TYPES GENEREREN IN PROGRAMMA'S
lt_code = 'REPORT GENERATE_TYPES.'.
APPEND lt_code.
lt_code = 'TYPES: BEGIN OF T_DATA,'.
APPEND lt_code.
LOOP AT p_fcattab INTO lw_fcat.
CONCATENATE lw_fcat-fieldname
'('
lw_fcat-intlen
') TYPE c,'
INTO lt_code.
APPEND lt_code.
ENDLOOP.
lt_code = 'END OF T_DATA.'.
APPEND lt_code.
GENERATE SUBROUTINE POOL lt_code NAME lv_repid.
CONCATENATE '\PROGRAM=' lv_repid '\TYPE=T_DATA' INTO p_type.
New Code
*&--------------------------------------------------------------*
*& Form CREATE_INTERNAL_STRUCTURE
*&--------------------------------------------------------------*
* Create internal structure
*---------------------------------------------------------------*
FORM CREATE_INTERNAL_STRUCTURE TABLES p_fcattab TYPE lvc_t_fcat
CHANGING p_struc TYPE REF TO cl_abap_structdescr
p_struc_table TYPE REF TO cl_abap_tabledescr.
DATA: ls_comp TYPE abap_componentdescr,
lw_fcat TYPE lvc_s_fcat,
lt_comp TYPE cl_abap_structdescr=>component_table,
lv_integer TYPE i.
LOOP AT p_fcattab INTO lw_fcat.
ls_comp-name = lw_fcat-fieldname.
lv_integer = lw_fcat-intlen.
ls_comp-type = cl_abap_elemdescr=>get_c( lv_integer ).
APPEND ls_comp TO lt_comp.
ENDLOOP.
TRY.
p_struc =
cl_abap_structdescr=>create( p_components = lt_comp ).
CATCH cx_sy_struct_creation .
ENDTRY.
TRY.
p_struc_table = cl_abap_tabledescr=>create( p_struc ).
CATCH cx_sy_table_creation .
ENDTRY.
ENDFORM. " CREATE_INTERNAL_STRUCTURE
2. Create a dynamic program
Main Program
Sub Program
The reason why SAP has put this limitation on it is, is to avoid an overflow of the program memory. Changing this number is not possible because it is a kernel constant and therefore, not variable and removing memory segments from the PXA is currently not supported by the kernel...
So you need to look for another solution.
There are 2 main reasons why you would want to generate a subroutine:
1. To create a dynamic structure
2. To create a dynamic program
Let me give you the solution for those 2 types of creating subroutines.
1. Create a dynamic structure:
Old Code
DATA: lt_code(100) TYPE c OCCURS 0 WITH HEADER LINE,
lv_type(100),
lv_repid LIKE sy-repid,
lw_fcat TYPE lvc_s_fcat.
* DYNAMISCH TYPES GENEREREN IN PROGRAMMA'S
lt_code = 'REPORT GENERATE_TYPES.'.
APPEND lt_code.
lt_code = 'TYPES: BEGIN OF T_DATA,'.
APPEND lt_code.
LOOP AT p_fcattab INTO lw_fcat.
CONCATENATE lw_fcat-fieldname
'('
lw_fcat-intlen
') TYPE c,'
INTO lt_code.
APPEND lt_code.
ENDLOOP.
lt_code = 'END OF T_DATA.'.
APPEND lt_code.
GENERATE SUBROUTINE POOL lt_code NAME lv_repid.
CONCATENATE '\PROGRAM=' lv_repid '\TYPE=T_DATA' INTO p_type.
New Code
*&--------------------------------------------------------------*
*& Form CREATE_INTERNAL_STRUCTURE
*&--------------------------------------------------------------*
* Create internal structure
*---------------------------------------------------------------*
FORM CREATE_INTERNAL_STRUCTURE TABLES p_fcattab TYPE lvc_t_fcat
CHANGING p_struc TYPE REF TO cl_abap_structdescr
p_struc_table TYPE REF TO cl_abap_tabledescr.
DATA: ls_comp TYPE abap_componentdescr,
lw_fcat TYPE lvc_s_fcat,
lt_comp TYPE cl_abap_structdescr=>component_table,
lv_integer TYPE i.
LOOP AT p_fcattab INTO lw_fcat.
ls_comp-name = lw_fcat-fieldname.
lv_integer = lw_fcat-intlen.
ls_comp-type = cl_abap_elemdescr=>get_c( lv_integer ).
APPEND ls_comp TO lt_comp.
ENDLOOP.
TRY.
p_struc =
cl_abap_structdescr=>create( p_components = lt_comp ).
CATCH cx_sy_struct_creation .
ENDTRY.
TRY.
p_struc_table = cl_abap_tabledescr=>create( p_struc ).
CATCH cx_sy_table_creation .
ENDTRY.
ENDFORM. " CREATE_INTERNAL_STRUCTURE
2. Create a dynamic program
Main Program
...
EXPORT <whatever is needed> TO MEMORY ID 'ABC'.
* Execute the code generation logic in new internal mode
SUBMIT <Sub Program> AND RETURN.
Sub Program
...
IMPORT <whatever is needed> FROM MEMORY ID 'ABC'.
* Logic to generate the internal table of ABAP code
...
GENERATE SUBROUTINE POOL <codetab> NAME gv_program.
IF SY-SUBRC EQ 0.
PERFORM <generated form> IN PROGRAM (gv_program).
ENDIF.
Abonneren op:
Posts (Atom)