I was new to IDocs. A recent assignment forced me to learn it. I realized that certain portions of Idoc creation could be easily programmed. So, explored a bit and wrote the code to auto-generate them. It worked like a charm. The code (or report: zzz_create_idoc_wizard) is pasted below. Enjoy
The below report has 5 mandatory parameters. Refer the comments against each of the parameters. Key in valid inputs and execute the report. (Based on your logged on SAP GUI security settings, you may get a security popup to take your confirmation to create/update a file in your local system. Just confirm by clicking 'Allow' or 'OK' button). The output of this report is a text file that gets saved in the path mentioned under parameter m_path. Copy the entire content of this text file. This is it. You can directly paste this 'ready-to-use code' either into a new report or a function module or a subroutine or a class-method. (Isn't it cool? )
In the auto generated text file, refer the comments mentioned. (By default, I have set the value to 'X'. You can either use this defaulted value for testing purposes. For productive use, replace the defaulted values with your own custom SELECT SQLs or custom logic to populate the segments' internal tables of your IDoc). Save and activate this new code. You are ready. The possible limits (max and min limit for each segment is also mentioned as comments in the code). This will be handy while preparing the internal tables for each segment of the IDoc.
Both 'basic' and extended' IDoc types are supported. This saves tons of coding time of developers who intend to write, test and rewrite iDocs.
The developer only needs to add the relevant functional/business logic under the specific commented sections of the code in reference to the productive usage of the IDoc (which of course cannot be automated. Are you crazy? )
REPORT zzz_create_idoc_wizard. PARAMETERS: m_obj TYPE edi_idcobj OBLIGATORY. "Existing IDoc Object Name PARAMETERS: m_mestyp TYPE edidc-mestyp OBLIGATORY. "Message Type PARAMETERS: m_rcvprt TYPE edidc-rcvprt OBLIGATORY. "Partner Type of Receiver PARAMETERS: m_rcvprn TYPE edidc-rcvprn OBLIGATORY. "Partner Number of Receiver PARAMETERS: m_path TYPE rlgrap-filename OBLIGATORY DEFAULT 'C:\temp\idoc.txt'. "Local folder path to save the result or output file AT SELECTION-SCREEN ON VALUE-REQUEST FOR m_path. DATA: lv_path TYPE string. CALL METHOD cl_gui_frontend_services=>directory_browse EXPORTING window_title = 'Select Directory' CHANGING selected_folder = lv_path EXCEPTIONS cntl_error = 1. CALL METHOD cl_gui_cfw=>flush EXCEPTIONS cntl_system_error = 1 cntl_error = 2. m_path = lv_path && '\idoc.txt'. START-OF-SELECTION. * validate input DATA l_attributes TYPE edi_iapi01. CALL FUNCTION 'IDOCTYPE_EXISTENCE_CHECK' EXPORTING pi_idoctyp = m_obj IMPORTING pe_attributes = l_attributes EXCEPTIONS OTHERS = 1. IF l_attributes IS INITIAL. MESSAGE 'Invalid object' TYPE 'S' DISPLAY LIKE 'E'. EXIT. ENDIF. * process DATA: lt_code TYPE TABLE OF string. DATA: ls_code LIKE LINE OF lt_code. ls_code = `**** Wizard generated code to create IDoc ` && m_obj && ` ****`. APPEND ls_code TO lt_code. APPEND INITIAL LINE TO lt_code. APPEND 'DATA: control_record LIKE edidc.' TO lt_code. APPEND 'DATA: i_communication LIKE edidc OCCURS 0 WITH HEADER LINE,' TO lt_code. APPEND ' lt_data LIKE edidd OCCURS 0 WITH HEADER LINE,' TO lt_code. APPEND ' ls_data LIKE LINE OF lt_data.' TO lt_code. APPEND INITIAL LINE TO lt_code. APPEND '**** Set the control record details' TO lt_code. ls_code = 'control_record-idoctp = ''' && m_obj && '''.'. APPEND ls_code TO lt_code. ls_code = 'control_record-mestyp = ''' && m_mestyp && '''.'. APPEND ls_code TO lt_code. ls_code = 'control_record-rcvprt = ''' && m_rcvprt && '''.'. APPEND ls_code TO lt_code. ls_code = 'control_record-rcvprn = ''' && m_rcvprn && '''.'. APPEND ls_code TO lt_code. APPEND INITIAL LINE TO lt_code. APPEND '**** Logic to populate internal table LT_DATA[] ****' TO lt_code. PERFORM custom_logic USING m_obj CHANGING lt_code. APPEND INITIAL LINE TO lt_code. APPEND '**** End of logic to populate internal table LT_DATA[] ****' TO lt_code. APPEND INITIAL LINE TO lt_code. APPEND 'CHECK LT_DATA[] IS NOT INITIAL.' TO lt_code. APPEND INITIAL LINE TO lt_code. APPEND '**** IDoc creation' TO lt_code. APPEND ' CALL FUNCTION ''MASTER_IDOC_DISTRIBUTE''' TO lt_code. APPEND ' EXPORTING' TO lt_code. APPEND ' master_idoc_control = control_record' TO lt_code. APPEND ' TABLES' TO lt_code. APPEND ' communication_idoc_control = i_communication' TO lt_code. APPEND ' master_idoc_data = LT_DATA' TO lt_code. APPEND ' EXCEPTIONS' TO lt_code. APPEND ' error_in_idoc_control = 1' TO lt_code. APPEND ' error_writing_idoc_status = 2' TO lt_code. APPEND ' error_in_idoc_data = 3' TO lt_code. APPEND ' sending_logical_system_unknown = 4' TO lt_code. APPEND ' OTHERS = 5.' TO lt_code. APPEND ' IF sy-subrc <> 0.' TO lt_code. APPEND ' MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno' TO lt_code. APPEND ' WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.' TO lt_code. APPEND ' ELSE.' TO lt_code. APPEND ' LOOP AT i_communication.' TO lt_code. APPEND ' WRITE: ''IDOC GENERATED'', i_communication-docnum. "check in tcode: WE05' TO lt_code. APPEND ' ENDLOOP.' TO lt_code. APPEND ' COMMIT WORK.' TO lt_code. APPEND ' ENDIF.' TO lt_code. DATA lv_path TYPE string. lv_path = m_path. CALL METHOD cl_gui_frontend_services=>gui_download EXPORTING filename = lv_path filetype = 'DAT' CHANGING data_tab = lt_code[]. CALL METHOD cl_gui_frontend_services=>execute EXPORTING document = lv_path " m_path+Name to Document EXCEPTIONS cntl_error = 1 error_no_gui = 2 bad_parameter = 3 file_not_found = 4 path_not_found = 5 file_extension_unknown = 6 error_execute_failed = 7 synchronous_failed = 8 not_supported_by_gui = 9 OTHERS = 10. IF sy-subrc <> 0. " do nothing ENDIF. *&---------------------------------------------------------------------* *& Form GENERATE_LINES *&---------------------------------------------------------------------* * text *----------------------------------------------------------------------* * -->P_OBJ text * <--P_LT_CODE text *----------------------------------------------------------------------* FORM custom_logic USING p_obj LIKE m_obj CHANGING p_lt_code LIKE lt_code. DATA l_idoctyp TYPE edi_idoctp. DATA g_idoctyp_attr TYPE edi_iapi01. DATA : gt_idocsyn LIKE edi_iapi02 OCCURS 20 WITH HEADER LINE, gt_prev_idocsyn LIKE edi_iapi02 OCCURS 20 WITH HEADER LINE, gs_prev_idocsyn LIKE LINE OF gt_prev_idocsyn. DATA: gt_tnode LIKE snodetext OCCURS 20 WITH HEADER LINE, gt_attr LIKE sed5attr OCCURS 20 WITH HEADER LINE, gs_attr LIKE LINE OF gt_attr. * read basis type l_idoctyp = p_obj. CALL FUNCTION 'IDOCTYPE_READ' EXPORTING pi_idoctyp = l_idoctyp IMPORTING pe_attributes = g_idoctyp_attr TABLES pt_syntax = gt_idocsyn pt_pre_syntax = gt_prev_idocsyn. DATA lv_variable TYPE string VALUE 'DATA : LT_& TYPE TABLE OF &, LS_& LIKE LINE OF LT_&.'. DATA lv_variable_temp TYPE string. LOOP AT gt_idocsyn INTO gs_prev_idocsyn. lv_variable_temp = lv_variable. REPLACE ALL OCCURRENCES OF '&' IN lv_variable_temp WITH gs_prev_idocsyn-segtyp. APPEND lv_variable_temp TO p_lt_code. ENDLOOP. CALL FUNCTION 'CONVERT_IDOC_SYNTAX_TO_TREE' EXPORTING pi_idoctyp = l_idoctyp pi_descrp = ''" g_idoctyp_attr-descrp pi_e2display = '' pi_e2segrel = '' TABLES lt_idocsyn = gt_idocsyn lt_prev_idocsyn = gt_prev_idocsyn lt_tree = gt_tnode lt_attr = gt_attr. LOOP AT gt_attr INTO gs_attr. APPEND INITIAL LINE TO lt_code. lv_variable_temp = `**** Process segment: ` && gs_attr-segtyp. APPEND lv_variable_temp TO lt_code. lv_variable_temp = 'REFRESH LT_&. CLEAR LT_&[]. CLEAR LS_&.'. REPLACE ALL OCCURRENCES OF '&' IN lv_variable_temp WITH gs_attr-segtyp. APPEND lv_variable_temp TO lt_code. DATA lt_ddic_info TYPE ddfields. DATA ls_ddic_info LIKE LINE OF lt_ddic_info. *get ddic fields CALL FUNCTION 'CATSXT_GET_DDIC_FIELDINFO' EXPORTING im_structure_name = gs_attr-segtyp IMPORTING ex_ddic_info = lt_ddic_info EXCEPTIONS failed = 1 OTHERS = 2. IF sy-subrc <> 0. " do nothing ENDIF. APPEND INITIAL LINE TO lt_code. SHIFT gs_attr-occmax LEFT DELETING LEADING '0'. lv_variable_temp = `**** Write your custom logic here. Note that the maximum limit for segment ` && gs_attr-segtyp && ` = ` && gs_attr-occmax. APPEND lv_variable_temp TO lt_code. IF gs_attr-occmax > 1. lv_variable_temp = '**** You may cutom code your logic (or copy by referring below statements) for a maximum limit of #' && gs_attr-occmax && ' times'. APPEND lv_variable_temp TO lt_code. ENDIF. LOOP AT lt_ddic_info INTO ls_ddic_info. CASE ls_ddic_info-datatype. WHEN 'CHAR'. lv_variable_temp = 'X'. WHEN ''. "enhance for other types: I, P, date, time, etc WHEN OTHERS. lv_variable_temp = 'X'. "default 'X' should work for most random cases ENDCASE. lv_variable_temp = 'LS_' && gs_attr-segtyp && '-' && ls_ddic_info-fieldname && ' = ''' && lv_variable_temp && '''.'. APPEND lv_variable_temp TO lt_code. ENDLOOP. IF lt_ddic_info IS NOT INITIAL. lv_variable_temp = 'APPEND LS_& TO LT_&.'. REPLACE ALL OCCURRENCES OF '&' IN lv_variable_temp WITH gs_attr-segtyp. APPEND lv_variable_temp TO lt_code. APPEND INITIAL LINE TO lt_code. ENDIF. lv_variable_temp = 'LOOP AT LT_& INTO LS_&.'. REPLACE ALL OCCURRENCES OF '&' IN lv_variable_temp WITH gs_attr-segtyp. APPEND lv_variable_temp TO lt_code. lv_variable_temp = ` LS_DATA-segnam = '&'. LS_DATA-sdata = LS_&. APPEND LS_DATA TO LT_DATA.`. REPLACE ALL OCCURRENCES OF '&' IN lv_variable_temp WITH gs_attr-segtyp. APPEND lv_variable_temp TO lt_code. APPEND 'ENDLOOP.' TO lt_code. ENDLOOP. ENDFORM. " GENERATE_LINES