Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
jrgkraus
Active Contributor

Reports with class


 

In MVC (model view controller) framework for ABAP part 1 you can find the "starter kit" for a framework you can use to create applications that are using dynpros and CFW controls that the framework is able to control. In this second part I will introduce only one further class that can be used for report programming. In my daily work, I am using this report very frequently as a template for new ones.

 

The demo application


 

Just like the demo application in the first part, the application contains the framework class that you can extract to a public class for reusing the code.

 

Application screen You can upload the screen 0001 from the file attached. Other than in the first part, we do not need a subscreen here. All we need is an empty screen that is able to carry the docking container in which we will place an ALV with the result list.

 

Selection screen controller The selection screen is controlled by the new class ZCL_MVCFW_CON_SELSCR. The controller derives from the class ZCL_MVCFW_CON_DYNPRO and extends it only with two methods

 

How it works


 

In order to get everything to work, a few steps are necessary. Let's go through it step by step.

 

Selection screen interface To simplify the passing of selection screen parameters between the classes, I use always a local interface that contains a structured type with all input elements from the selection screen

 



 

You can see that I use the same names for the components as for the selection screen elements:

 



 

Global data Some global variables are indispensible:



 

 

INITIALIZATION Here the main controller is instantiated. After that, the get_con_dynpro method is called to create a controller for the actual dynpro, which is the selection screen.

 

PAI The PAI event of a selection screen is at selection-screen, so we call the PAI of the screen controller, which is a framework method that does the following:

  • Ask the main controller to fetch the screen data.

    • Therefore, the method get_screen_data of the main controller must be redefined:

      As you see, the data is stored in an attribute of the main controller. This can be useful, if you want to react to user inputs during PBO, i.e. switching on/of field attributes and so on.



  • Invoke the PAI of the super class, which will compare all component values from the screen with the stored ones in the memory of the framework class ZCL_MVCFW_DYNPRO and call PAI_FIELD_CHANGE on change of values.


 

START-OF-SELECTION The method run of the selection-screen controller is called.

 

RUN The control is passed to the main controller (run_program), where the main logic of the report begins to work.

 

Batch/Online processing As you can see in run_program, there are two branches, one for background processing and one for online. The online branch is similar to the demo in part 1. For the batch processing, a list has to be created instead of calling a screen. Therefore, a list controller has been added to the program, which we derive from the generic CFW controller.

 



 

Of course we do not have any CFW control here. But the framework class can be used even without container. In method refresh the output is coded. In this case, I use CL_SALV_TABLE to produce an output list.

 

Some notes


 

I some of my use cases, I use more than one model class because of complexity of the application. In this case, it comes handy to declare common used data types in the interface lif_report.

 

All the best

Jörg
*&---------------------------------------------------------------------*
*& Report ZP_MVCFW_REPORT_DEMO
*&
*&---------------------------------------------------------------------*
report zp_mvcfw_report_demo.

interface lif_report.
types:
begin of gty_s_selscreen,
s_carrid type range of sflight-carrid,
s_connid type range of sflight-connid,
s_fldate type range of sflight-fldate,
p_batch type abap_bool,
end of gty_s_selscreen.
endinterface.

class lcl_model definition.

public section.
methods:
read_db
importing is_selection type lif_report=>gty_s_selscreen,
get_out_tab
exporting et_out type standard table.


private section.

data: mt_main_output type table of sflight,
ms_selection type lif_report=>gty_s_selscreen.

endclass. "lcl_model DEFINITION

class lcl_con_selscr_1000 definition deferred.

class lcl_con_main definition inheriting from zcl_mvcfw_con_main.

public section.

constants:
cv_con_alv_out type char32 value 'LCL_CON_ALV_OUT',
cv_con_selscreen_1000 type char32 value 'LCL_CON_SELSCR_1000',
cv_con_list type char32 value 'LCL_CON_LIST'.
methods:
constructor
importing iv_program type syrepid,
pai_main
importing
iv_ucomm type syucomm,
pbo_main redefinition,
run_program,
get_selections redefinition.

protected section.
methods:
create_con_dynpro redefinition,
create_one_controller redefinition.

private section.
data: mo_model type ref to lcl_model,
ms_selscreen type lif_report=>gty_s_selscreen.

endclass. "lcl_con_main DEFINITION

class lcl_con_selscr_1000 definition inheriting from zcl_mvcfw_con_selscr.

public section.
methods:
constructor
importing io_model type ref to lcl_model
io_con_main type ref to lcl_con_main
is_selections type lif_report=>gty_s_selscreen,
run redefinition.

protected section.
methods:
pai_field_change redefinition.

private section.
data: mo_model type ref to lcl_model,
mo_main type ref to lcl_con_main,
" only for background run:
mt_out type table of sflight.

endclass. "lcl_con_selscr_1000 DEFINITION

class lcl_con_alv_out definition inheriting from zcl_mvcfw_con_alv.
public section.
methods:
refresh redefinition,
constructor
importing
io_container type ref to cl_gui_container
io_model type ref to lcl_model
io_main type ref to lcl_con_main
raising zcx_mvcfw_error.

protected section.
methods:
prepare_layout redefinition,
on_double_click redefinition,
on_toolbar redefinition,
on_ucomm redefinition,
prepare_exclude redefinition.

private section.
data: mo_model type ref to lcl_model,
mo_main type ref to lcl_con_main.

endclass. "lcl_con_alv_out DEFINITION

class lcl_con_list definition inheriting from zcl_mvcfw_con_cfw.

public section.

methods:
constructor
importing
io_model type ref to lcl_model
io_main type ref to lcl_con_main,
refresh redefinition.

protected section.

private section.

data: mo_model type ref to lcl_model,
mo_main type ref to lcl_con_main,
mt_out type table of sflight.

endclass.


tables sflight.

select-options: s_carrid for sflight-carrid,
s_connid for sflight-connid,
s_fldate for sflight-fldate.

parameters p_batch as checkbox.

data: gv_okcode type syucomm,
go_sel_screen type ref to lcl_con_selscr_1000,
go_main type ref to lcl_con_main.

*--------------------------------------------------------------------*
* report events
*--------------------------------------------------------------------*

initialization.
" start point: create main and sel.screen controllers
go_main ?= lcl_con_main=>get_instance( ).
go_sel_screen ?= go_main->get_con_dynpro( ).

at selection-screen.
" call pai of sel.screen controller
go_sel_screen->pai( ).

start-of-selection.
" call run routine of sel.screen controller
go_sel_screen->run( ).

class lcl_model implementation.

method read_db.

ms_selection = is_selection.
select * from sflight into table mt_main_output
where carrid in ms_selection-s_carrid and
connid in ms_selection-s_connid and
fldate in ms_selection-s_fldate.

endmethod. "read_db

method get_out_tab.

et_out = mt_main_output.

endmethod. "get_out_tab

endclass. "lcl_model IMPLEMENTATION

class lcl_con_main implementation.
method constructor.

" the report name is needed in the framework
super->constructor( |{ sy-repid }| ).
try.
create object mo_model.
" set parameters of the controller for the GUI interface
set_gui_interface(
exporting
iv_gui_status = 'MAIN' " IV_GUI_STATUS
iv_titlebar = 'MAIN'
).
catch cx_static_check.
leave program.
endtry.
endmethod. "constructor

method pbo_main.
" pbo_main is for screen 0001, NOT for the selection screen
try.
get_con( cv_con_alv_out )->refresh( ).
rv_res = super->pbo_main( ).
catch cx_static_check.
" error handling here
endtry.
endmethod.

method pai_main.
case iv_ucomm.
when 'EXIT' or 'BACK' or 'CANC'.
set screen 0.
leave screen.
endcase.

endmethod. "pai_main

method create_con_dynpro.
case sy-dynnr.
when '1000'.
create object ro_res
type lcl_con_selscr_1000
exporting
io_model = mo_model
io_con_main = me
is_selections = ms_selscreen. " propagate the selection structure
" store the controller object
endcase.

endmethod. "get_con_dynpro

method create_one_controller.
" create each output controller on request
case iv_type.
when cv_con_alv_out.
create object ro_res
type (iv_type)
exporting
io_container = new cl_gui_docking_container(
extension = 9999
)
io_main = me
io_model = mo_model.
when cv_con_list.
" special case list: no container needed
create object ro_res
type (iv_type)
exporting
io_main = me
io_model = mo_model.
endcase.
endmethod. "create_one_controller

method get_selections.
" the only access to the global fields in the selection screen
ms_selscreen-s_carrid = s_carrid[].
ms_selscreen-s_connid = s_connid[].
ms_selscreen-s_fldate = s_fldate[].
ms_selscreen-p_batch = p_batch.
if es_data is supplied.
es_data = ms_selscreen.
endif.
endmethod.

method run_program.

try.
mo_model->read_db( ms_selscreen ).
" decide how to present the data
if sy-batch = abap_true or
ms_selscreen-p_batch = abap_true.
" a list is used
get_con( cv_con_list )->refresh( ).
else.
" an interactive grid is used
call screen 1.
endif.
catch cx_static_check.
" error handling here
endtry.

endmethod.

endclass.

class lcl_con_selscr_1000 implementation.

method constructor.
data: lt_fname type lvc_t_fnam.

" 1. call the general constructor with the structure name
" 2. set the model object
super->constructor( is_selections = is_selections
io_con_main = io_con_main ).
mo_model = io_model.
" concrete main controller from generic via casting
mo_main ?= mo_con_main.

endmethod. "constructor

method pai_field_change.

* try.
* mo_model->perform_field_check( iv_fieldname = iv_fieldname
* iv_source = iv_source ).
* catch zcx_mvcfw_error into data(lo_err).
* message lo_err type 'S' display like 'E'.
* endtry.
endmethod. "pai_field_change

method run.
" pass the control to the main controller
mo_main->run_program( ).
endmethod. "pbo

endclass. "create_con_dynpro

class lcl_con_alv_out implementation.
method constructor.
super->constructor(
io_container = io_container
iv_structure_name = 'sflight' ).

mo_model = io_model.
mo_main = io_main..
endmethod. "constructor

*
method prepare_exclude.
* Example
* append:
* cl_gui_alv_grid=>mc_fc_graph to et_tab.

endmethod. "prepare_exclude

method prepare_layout.
rs_res-cwidth_opt = abap_true.
rs_res-grid_title = 'Flights table'.
endmethod. "prepare_layout

method on_double_click.

field-symbols: <ls_list> type sflight,
<lt_tab> type standard table.

try.
assign mr_table->* to <lt_tab>.
read table <lt_tab> assigning <ls_list> index es_row_no-row_id.
if sy-subrc = 0 .
" include double click functions
endif.
catch zcx_mvcfw_error into data(lo_err).
message lo_err type 'S' display like 'E'.
endtry.

endmethod. "on_double_click

method refresh.

field-symbols: <lt_table> type standard table.
data: ls_layout type lvc_s_layo.

assign mr_table->* to <lt_table>.

mo_model->get_out_tab( importing et_out = <lt_table> ).
refresh_table( ).

endmethod. "refresh
*
method on_toolbar.
data: ls_toolbar type stb_button.

" create user buttons
ls_toolbar-function = 'CLOSE'.
ls_toolbar-icon = icon_close.
append ls_toolbar to e_object->mt_toolbar.

endmethod. "on_toolbar

method on_ucomm.

data: lv_line_index type i.

try.
case e_ucomm.
when 'CLOSE'.
hide( ).
endcase.
catch zcx_mvcfw_error into data(lo_err).
message lo_err type 'S' display like 'E'.
endtry.
endmethod. "on_ucomm_equi

endclass. "lcl_con_alv_out IMPLEMENTATION

class lcl_con_list implementation.

method constructor.
super->constructor( ).
mo_model = io_model.
mo_main = io_main.
endmethod.

*--------------------------------------------------------------------*
* Redefinition: create a abap list (used for batch run)
*--------------------------------------------------------------------*
method refresh.
data lo_salv type ref to cl_salv_table.

mo_model->get_out_tab( importing et_out = mt_out ).
cl_salv_table=>factory(
exporting
list_display = if_salv_c_bool_sap=>true " ALV Displayed in List Mode
importing
r_salv_table = lo_salv " Basis Class Simple ALV Tables
changing
t_table = mt_out
).
lo_salv->get_columns( )->set_optimize( ).
lo_salv->display( ).

endmethod.

endclass.

module pbo_0001 output.
go_main->pbo_main( ).
endmodule.

module pai_0001 input.
go_main->pai_main( iv_ucomm = gv_okcode ).
endmodule.


****************************************************************																																
* THIS FILE IS GENERATED BY THE SCREEN PAINTER. *
* NEVER CHANGE IT MANUALLY, PLEASE ! *
****************************************************************
%_DYNPRO
ZP_MVCFW_REPORT_DEMO
0001
740
40
%_HEADER
ZP_MVCFW_REPORT_DEMO 0001 0001 0 0192 37 0 0200255 0G E 20160804115046
%_DESCRIPTION
Main screen
%_FIELDS
GV_OKCODE CHAR 20 80 10 00 00 00 255 1 O 0 0 0 0 0 0 ____________________
%_FLOWLOGIC
process before output.
" empty dummy screen that carries a docking container
module pbo_0001.

*
process after input.
module pai_0001 at exit-command.
module pai_0001.
%_PARAMS


class ZCL_MVCFW_CON_SELSCR definition
public
inheriting from ZCL_MVCFW_CON_DYNPRO
abstract
create public .

public section.

*"* public components of class ZCL_MVCFW_CON_SELSCR
*"* do not include other source files here!!!
methods RUN
abstract
raising
CX_STATIC_CHECK .
methods CONSTRUCTOR
importing
!IV_STRUC_NAME type TABNAME optional
!IS_SELECTIONS type ANY optional
!IO_CON_MAIN type ref to ZCL_MVCFW_CON_MAIN optional
preferred parameter IV_STRUC_NAME .

methods PAI
redefinition .
protected section.
*"* protected components of class ZCL_MVCFW_CON_SELSCR
*"* do not include other source files here!!!
private section.
*"* private components of class ZCL_MVCFW_CON_SELSCR
*"* do not include other source files here!!!
ENDCLASS.



CLASS ZCL_MVCFW_CON_SELSCR IMPLEMENTATION.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_SELSCR->CONSTRUCTOR
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_STRUC_NAME TYPE TABNAME(optional)
* | [--->] IS_SELECTIONS TYPE ANY(optional)
* | [--->] IO_CON_MAIN TYPE REF TO ZCL_MVCFW_CON_MAIN(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method CONSTRUCTOR.

super->constructor(
iv_struc_name = iv_struc_name
io_con_main = io_con_main
).

if iv_struc_name is initial.
if is_selections is supplied.
data(lo_structdescr) = cast cl_abap_structdescr( cl_abap_typedescr=>describe_by_data( is_selections ) ).
loop at lo_structdescr->components into data(ls_struc_line).
append INITIAL LINE TO mt_field_list ASSIGNING FIELD-SYMBOL(<ls_field_list>).
<ls_field_list>-fieldname = ls_struc_line-name.
endloop.

create data mr_screen_data like is_selections.
endif.
endif.
endmethod.


* <SIGNATURE>---------------------------------------------------------------------------------------+
* | Instance Public Method ZCL_MVCFW_CON_SELSCR->PAI
* +-------------------------------------------------------------------------------------------------+
* | [--->] IV_UCOMM TYPE SYUCOMM(optional)
* | [<-->] C_DATA TYPE ANY(optional)
* +--------------------------------------------------------------------------------------</SIGNATURE>
method PAI.
field-symbols <ls_screen_local> type any.
data: lr_screen_local type ref to data.

assign mr_screen_data->* to field-symbol(<ls_screen>).


if mo_con_main is bound.
create data lr_screen_local like <ls_screen>.
assign lr_screen_local->* to <ls_screen_local>.

mo_con_main->get_selections(
importing es_data = <ls_screen_local> ).

super->pai(
exporting iv_ucomm = iv_ucomm
changing c_data = <ls_screen_local> ).
else.
super->pai(
exporting iv_ucomm = iv_ucomm
changing c_data = c_data ).

endif.


endmethod.
ENDCLASS.
10 Comments