The requirement was to create two fixed width files to be sent to a third party. The selection of data is pretty straight forward. I wanted to display the data sent in an ALV and wanted to do all this in one report.
For each output format and file structure I created one dictionary structure. For the fields I didn’t bother with data elements as the file output was to be of different lengths then the existing domains lengths. So I just went for the predefined ones.
Structure 1 = File 1
Structure 2 = File 2
The logic I was going to follow was:
- Select Data
- Download data
- Create Split Container
- Display ALV in each container
For doing all this I created a local class as I want to as much coding as possible in OO. The definition of class looks as like this:
CLASS lcl_report DEFINITION.PUBLIC SECTION.METHODS:extract,build_file_names,download,display.CLASS-METHODS:get_directory RETURNING value(r_dir) TYPE localfile.PRIVATE SECTION.CONSTANTS:c_container(15) VALUE 'C_CONTROL'.METHODS:create_split_control CHANGING ch_split_container TYPE REF TO cl_gui_easy_splitter_container,display_alv IMPORTING im_o_container TYPE REF TO cl_gui_containerim_heading TYPE stringCHANGING ch_t_out_tab TYPE table,set_column_text IMPORTING im_alv TYPE REF TO cl_salv_tableim_t_out_tab TYPE table.DATA:t_candidate TYPE TABLE OF zst_cand_out,t_centre TYPE TABLE OF zst_centre_out,centre_file TYPE string,cand_file TYPE string.ENDCLASS. "lcl_report DEFINITION
In the selection option I provided a parameter to enter the directory to which the files will be downloaded. The F4 to display the directories on the local PC was implemented by the following code.
F4 event for the parameter
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_dir.p_dir = lcl_report=>get_directory( ).
Static method that does the directory display dialog
METHOD get_directory.DATA:l_t_file_table TYPE TABLE OF file_table,l_s_file_table TYPE file_table,l_subrc TYPE i,l_directory TYPE string.* CALL METHOD cl_gui_frontend_services=>file_open_dialog* CHANGING* file_table = l_t_file_table* rc = l_subrc* EXCEPTIONS* file_open_dialog_failed = 1* cntl_error = 2* error_no_gui = 3* not_supported_by_gui = 4* OTHERS = 5.* IF sy-subrc <> 0.* MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno* WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.* ENDIF.CALL METHOD cl_gui_frontend_services=>directory_browseCHANGINGselected_folder = l_directoryEXCEPTIONScntl_error = 1error_no_gui = 2not_supported_by_gui = 3OTHERS = 4.IF sy-subrc <> 0.MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgnoWITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.ENDIF.* READ TABLE l_t_file_table INTO l_s_file_table INDEX 1.* r_dir = l_s_file_table-filename.r_dir = l_directory.ENDMETHOD. "get_directory
So the report once executed will do the extract, download and display
START-OF-SELECTION.CREATE OBJECT o_report.o_report->build_file_names( ).o_report->extract( ).END-OF-SELECTION.o_report->download( ).CALL SCREEN 0100.
The ALV is display in the screen 0100. Call to the method display( ) will display the output in PBO
MODULE status_0100 OUTPUT.SET PF-STATUS 'STATUS'.SET TITLEBAR 'TITLE'.o_report->display( ).CALL METHOD cl_gui_cfw=>flush.ENDMODULE. " status_0100 OUTPUT
Within the display method we create the split screen and display the two alv’s
METHOD display.DATA:l_o_split_container TYPE REF TO cl_gui_easy_splitter_container.create_split_control( CHANGING ch_split_container = l_o_split_container ).* Display candidatesdisplay_alv( EXPORTING im_o_container = l_o_split_container->top_left_containerim_heading = 'Candidates'CHANGING ch_t_out_tab = t_candidate ).* Display centredisplay_alv( EXPORTING im_o_container = l_o_split_container->bottom_right_containerim_heading = 'Centres'CHANGING ch_t_out_tab = t_centre ).ENDMETHOD. "display
The split ALV posed one problem for me which was giving the title to each of the containers. I posted this question on SDN and got response from Naimesh Patel. The class CL_SALV_DISPLAY_SETTINGS takes care of that. The code for displaying each ALV is modularised in the method display_alv( ). Since the structure I had created did not refer to any data elements the output was coming without any column heading. For this I created another method set_cloumn_text( ) that would read the DDIC structure and get the values from there and the set the column text. I got to use the ABAP runtime classes that give data type description in that method. This works both the structures I had
METHOD display_alv.DATA:l_o_table TYPE REF TO cl_salv_table.* Get the ALV object refering to the output tableTRY.cl_salv_table=>factory(EXPORTINGr_container = im_o_containerIMPORTINGr_salv_table = l_o_tableCHANGINGt_table = ch_t_out_tab ).CATCH cx_salv_msg. "#EC NO_HANDLERENDTRY.** Add basic default functionality in the ALV report** Functions* DATA:* l_o_functions TYPE REF TO cl_salv_functions_list.** l_o_functions = l_o_table->get_functions( ).* l_o_functions->set_all( abap_true ).* Column textset_column_text( im_alv = l_o_table im_t_out_tab = ch_t_out_tab ).* HeadingDATA:l_o_display TYPE REF TO cl_salv_display_settings,l_title TYPE lvc_title.l_title = im_heading.l_o_display = l_o_table->get_display_settings( ).* Title to ALVl_o_display->set_list_header( l_title ).* Display the listl_o_table->display( ).ENDMETHOD. "display_alv
METHOD set_column_text.* ColumnsDATA:l_o_columns TYPE REF TO cl_salv_columns_table,l_o_column TYPE REF TO cl_salv_column.l_o_columns = im_alv->get_columns( ).l_o_columns->set_optimize( abap_true ).DATA:l_o_tabledescr TYPE REF TO cl_abap_tabledescr,l_o_structdescr TYPE REF TO cl_abap_structdescr,l_t_fields TYPE ddfields.FIELD-SYMBOLS:<l_field> TYPE LINE OF ddfields.l_o_tabledescr ?= cl_abap_typedescr=>describe_by_data( im_t_out_tab ).l_o_structdescr ?= l_o_tabledescr->get_table_line_type( ).CALL METHOD l_o_structdescr->get_ddic_field_list* EXPORTING* P_LANGU = SY-LANGU* P_INCLUDING_SUBSTRUCTRES = ABAP_FALSERECEIVINGp_field_list = l_t_fieldsEXCEPTIONSnot_found = 1no_ddic_type = 2OTHERS = 3.IF sy-subrc <> 0.MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgnoWITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.ENDIF.LOOP AT l_t_fields ASSIGNING <l_field>.TRY.CALL METHOD l_o_columns->get_columnEXPORTINGcolumnname = <l_field>-fieldnameRECEIVINGvalue = l_o_column.CATCH cx_salv_not_found .ENDTRY.CALL METHOD l_o_column->set_short_textEXPORTINGvalue = <l_field>-fieldtext(10).CALL METHOD l_o_column->set_medium_textEXPORTINGvalue = <l_field>-fieldtext(20).ENDLOOP.ENDMETHOD. "set_column_text
The split is created using the class CL_GUI_EASY_SPLITTER_CONTAINER this is done in:
METHOD create_split_control.DATA:l_o_container TYPE REF TO cl_gui_custom_container.* o_split_container TYPE REF TO cl_gui_easy_splitter_container.CREATE OBJECT l_o_containerEXPORTING* PARENT =container_name = c_container* STYLE =* LIFETIME = lifetime_default* REPID =* DYNNR =* NO_AUTODEF_PROGID_DYNNR =EXCEPTIONScntl_error = 1cntl_system_error = 2create_error = 3lifetime_error = 4lifetime_dynpro_dynpro_link = 5OTHERS = 6.IF sy-subrc <> 0.MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgnoWITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.ENDIF.CREATE OBJECT ch_split_containerEXPORTING* LINK_DYNNR =* LINK_REPID =* METRIC = cntl_metric_dynproparent = l_o_container* ORIENTATION = 0* SASH_POSITION = 50* WITH_BORDER = 1* name = c_containerEXCEPTIONScntl_error = 1cntl_system_error = 2OTHERS = 3.IF sy-subrc <> 0.MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgnoWITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.ENDIF.ENDMETHOD. "create_split_control
The output will look something like this
No comments:
Post a Comment