Showing posts with label Dynpro. Show all posts
Showing posts with label Dynpro. Show all posts

Saturday, June 9, 2018

Update all dynpro/screen fields in one shot

Lazyness is one of the engines for iprovements. So this is the root cause of this short article.

Once you are trying to update a classic Dynpro you should call FM DYNP_VALUES_UPDATE. Ok, you can collect ITAB for each screen field providing name and value as on bellow example.

      ls_dynpfield-fieldname  = lv_screen_field_name.
      ls_dynpfield-fieldvalue = lv_screen_field_val.
      APPEND ls_dynpfield TO lt_dynpfield.

It is still annoying to do so for each screen field...

Imagine, you can set the screen values as you need and run just once some certain method doing the whole screen update job. Here it is, there is just one simple call. You can reuse it as many times you want. The only condition is to have screen connected to a certain structure variable. That's all.


Screen update method call

    " Update screen
     lo_ctrl_screen->update_screen_fields(
      iv_prog       sy-cprog                                                      " Program name
      iv_screen     '0200'                       " Dynpro number
      iv_struc_name 'GS_SCREEN_STRUCTURE_NAME' " Name of structure holding the screen values
      is_struc_data gs_real_structure                            " Structure variable itself
    ).




The method source code: 


  METHOD update_screen_fields.

    DATA:
      lt_dynpfield         TYPE STANDARD TABLE OF dynpread,
      ls_dynpfield         LIKE LINE OF lt_dynpfield,
      lo_struc_descr       TYPE REF TO cl_abap_structdescr.

    lo_struc_descr ?= cl_abap_structdescr=>describe_by_datais_struc_data ).
    CHECK sy-subrc 0.

    FIELD-SYMBOLS:
      <fs_comp> LIKE LINE OF lo_struc_descr->components,
      <fs_val>  TYPE any.

    LOOP AT lo_struc_descr->components ASSIGNING <fs_comp>.
      ASSIGN COMPONENT <fs_comp>-name OF STRUCTURE is_struc_data TO <fs_val>.

      IF <fs_val> IS NOT INITIAL.
        CLEAR ls_dynpfield.
        CONCATENATE iv_struc_name <fs_comp>-name INTO ls_dynpfield-fieldname.
        ls_dynpfield-fieldvalue <fs_val>.
        APPEND ls_dynpfield TO lt_dynpfield.
      ENDIF.

    ENDLOOP.

    " Update screen
    IF lt_dynpfield IS NOT INITIAL.
      CALL FUNCTION 'DYNP_VALUES_UPDATE'
        EXPORTING
          dyname     iv_prog    "Program name
          dynumb     iv_screen  "Screen number
        TABLES
          dynpfields lt_dynpfield
        EXCEPTIONS
          OTHERS     0.
    ENDIF.

  ENDMETHOD.                    "update_screen_fields


Sunday, May 6, 2018

How to refresh graph (based on CL_GUI_CHART_ENGINE / GRAPHICS_GUI_CE_DEMO)

Many of us used the sample simple nice program GRAPHICS_GUI_CE_DEMO as a pattern how to work with graphs. Unfortunately this program does not solve the question how to update/refresh  graph data, furthermore you can find misleading info on some forums.  I do not say the bellow pattern is the best, but it is working fine :)

In my case I have dedicated modal window for graph. Each time I press ALV toolbar button I want to see related graph to the grid. I have always prepared an internal table with correct graph data (see below t_graph within the coding).




Screen call e.g.


    CALL SCREEN 500 STARTING AT 13 ENDING AT 175 37.



PBO


MODULE status_0500 OUTPUT.

  SET PF-STATUS 'DEFAULT_STATUS'.
  SET TITLEBAR 'GRAPH'.

  lcl_main=>self->generate_graph).

ENDMODULE.


PAI

MODULE exit_command_0500 INPUT.

  LEAVE TO SCREEN 0" Back to main screen

ENDMODULE.


The PBO method


I am keeping just two global variables outside the method itself. There is no need to call any screen container destructor to reuse the graph object again etc. The base screen under the modal window can take care for calling destructors first and freeing the variables..


The globals


DATA
  go_ce_container   TYPE REF TO cl_gui_container.
  go_ce_viewer      TYPE REF TO cl_gui_chart_engine.



The generator method coding


The whole question is what should be setup each screen call (local variables) and what should remain in memory (global ones). The local class  lo_graph is just my rewrite of two performs/subroutines  from the demo program GRAPHICS_GUI_CE_DEMO. It's methods are responsible for filling the XML data.


  METHOD generate_graph.

    DATA:
      lo_graph           TYPE REF TO lcl_graph" custom class preparing XML data for graph
      lo_ixml_data_doc   TYPE REF TO if_ixml_document,
      lo_ixml_custom_doc TYPE REF TO if_ixml_document,
      lo_ixml            TYPE REF TO if_ixml,
      lo_ixml_sf         TYPE REF TO if_ixml_stream_factory,
      lo_ostream         TYPE REF TO if_ixml_ostream,
      lv_xstr            TYPE xstring.

    IF go_ce_container IS INITIAL.

       go_ce_container = generate_graph_container).

      CREATE OBJECT go_ce_viewer
        EXPORTING
          parent go_ce_container

    ENDIF.

    lo_ixml cl_ixml=>create).
    lo_ixml_sf lo_ixml->create_stream_factory).

    CREATE OBJECT lo_graph.

    lo_graph->create_data(
      EXPORTING
        it_graph    t_graph
        iv_ixml     lo_ixml
      CHANGING
        cv_ixml_doc lo_ixml_data_doc
    ).
    lo_ostream lo_ixml_sf->create_ostream_xstringlv_xstr ).
    lo_ixml_data_doc->renderostream lo_ostream ).
    go_ce_viewer->set_dataxdata lv_xstr ).

    CLEAR lv_xstr.

    lo_graph->create_custom(
      EXPORTING
        iv_title    v_grid_title 
        iv_ixml     lo_ixml
      CHANGING
        cv_ixml_doc lo_ixml_custom_doc
    ).
    lo_ostream lo_ixml_sf->create_ostream_xstringlv_xstr ).
    lo_ixml_custom_doc->renderostream lo_ostream ).
    go_ce_viewer->set_customizingxdata lv_xstr ).

    go_ce_viewer->render).

  ENDMETHOD.                    "generate_graph






Sunday, November 5, 2017

Calendar week - dynpro field with tuned search help

As always, I hope this article can save someones time as I wasted time by googling and debugging. Here I want to describe two different approaches how to work with calendar week input field on dynpro, especially two search help options.

Simple dynpro field with given search help


Calendar week itself has NUMC(6) data format. When you are working with dynpro field you need type input as CHAR(7), remember standard search help returns separating dot in between. I found suitable in my case to use standard search help /BI0/OCALWEEK. You have to add just conversion exit, here it is PERI6. Now we have nice working stuff.

Dynpro settings:




Dynpro result:


Everything is simple enough and works just as you would expected, but....  There is one big but for me. The search helps starts somewhere in the deep past. Today I have year 2017, the default value is 6 year ago. The user is forced to scroll down too much to reach current year.




Search help with prefilled input parameters


So we have nice character (7) input field, conversion routines works Ok. So what is painkiller of above example? The answer is search help input parameters, by these you can influence given range of values. I decided to work with DATEFROM, because sy-datum is easily reachable.

Search help input parameters:




How to provide the input parameters? In my case I used ABAP and own F4 screen module. I wanted to have a list of weeks starting just few weeks ago, but not years.


So the result now looks like:





This is what I was exactly looking for. Search help starts from week I wanted.

Here is the solution:


On the screen "Flow logic" tab define module event trigger for F4 as e.g. below.

PROCESS ON VALUE-REQUEST"F4
  FIELD gs_task_schd-cw MODULE f4_cw.

Screen settings:


Just conversion exit is still present within field properties - see below, but no search help any more. It is replaced by F4 module. Conversion exit works to convert data from screen to program (from CHAR7 to NUMC6), but not from F4 module to screen, that is why I have added manual call of conversion routine to the F4 module to display data in a correct way on the screen.




The module can looks like:


*&---------------------------------------------------------------------*
*&      Module  F4_CW  INPUT
*&---------------------------------------------------------------------*
*       Calendar week search help with preset (change week list)
*----------------------------------------------------------------------*
MODULE f4_cw INPUT.

  lcl_main=>self->o_ctrl_screen->screen_300_f4_cw(
    iv_screen_field 'GS_TASK_SCHD-CW'
  ).

ENDMODULE.                 " F4_CW  INPUT


So the miracle here is the method screen_300_f4_cw.


Method definition:


             screen_300_f4_cw
              IMPORTING
                iv_screen_field          TYPE  dynfnam.

Method implementation:


  METHOD screen_300_f4_cw.

    DATAlt_dynpfields         TYPE STANDARD TABLE OF dynpread,
          ls_dynpfields         LIKE LINE OF lt_dynpfields,
          ls_shlp_descr         TYPE shlp_descr,
          lt_shlp_return_values TYPE STANDARD TABLE OF ddshretval,
          lt_shlp_selopt        TYPE STANDARD TABLE OF ddshselopt,
          ls_shlp_selopt        LIKE LINE OF lt_shlp_selopt,
          lv_date               TYPE sydatum.

    " Get search help description
    CALL FUNCTION 'F4IF_GET_SHLP_DESCR'
      EXPORTING
        shlpname '/BI0/OCALWEEK' " Standard search help name
        shlptype 'SH'
      IMPORTING
        shlp     ls_shlp_descr.

    " Ask FM F4IF_START_VALUE_REQUEST for return values - set the sign
    FIELD-SYMBOLS<fs_interface> LIKE LINE OF ls_shlp_descr-interface.
    LOOP AT ls_shlp_descr-interface ASSIGNING <fs_interface>.
      <fs_interface>-valfield 'X'.
    ENDLOOP.

    " Note: There is internaly used build in function DATE_CONV_EXT_TO_INT that is later used, it accepts DDMMYYYY,
    " not other e.g. YYYYMMDD - it causes dumps. So sy-datum can not be used directly
    lv_date sy-datum 21" start some weeks ago
    CONCATENATE lv_date+6(2lv_date+4(2lv_date+0(4INTO ls_shlp_selopt-low.

    " Preset default week interval of initial search help screen (not to start in stone age)
    ls_shlp_selopt-shlpname  '/BI0/OCALWEEK'.
    ls_shlp_selopt-shlpfield 'DATEFROM'.
    ls_shlp_selopt-sign      'I'.
    ls_shlp_selopt-option    'GT'.
    " ls_shlp_selopt-high     = ''.
    APPEND ls_shlp_selopt TO lt_shlp_selopt.
    ls_shlp_descr-selopt lt_shlp_selopt.

    " Trigger search help popup screen
    CALL FUNCTION 'F4IF_START_VALUE_REQUEST'
      EXPORTING
        shlp          ls_shlp_descr
      TABLES
        return_values lt_shlp_return_values.

    FIELD-SYMBOLS<fs_return_value> LIKE LINE OF lt_shlp_return_values.
    LOOP AT lt_shlp_return_values ASSIGNING <fs_return_value>.

      " Run manually value conversion exit
      CALL FUNCTION 'CONVERSION_EXIT_PERI6_OUTPUT'
        EXPORTING
          input  <fs_return_value>-fieldval
        IMPORTING
          output <fs_return_value>-fieldval.

      " Fill screen field
      ls_dynpfields-fieldname  iv_screen_field.
      ls_dynpfields-fieldvalue <fs_return_value>-fieldval.
      APPEND ls_dynpfields TO lt_dynpfields.
      EXIT" process just one item

    ENDLOOP.

    " Update screen
    CALL FUNCTION 'DYNP_VALUES_UPDATE'
      EXPORTING
        dyname     '/FDSEU/HCPC'    "Program name
        dynumb     '0220'           "Screen number
      TABLES
        dynpfields lt_dynpfields
      EXCEPTIONS
        OTHERS     0.

  ENDMETHOD.                    "screen_300_f4_cw





An addition - database data type


the data type storing calendar week within database could be e.g. KWEEK or /BI0/OICALWEEK, all have type NUMC(6).




Internally the stored value looks like:





May be there are easier ways, I found this. I hope it helps someone ;-)



Sunday, October 22, 2017

Trigger standard search help and fill more dynpro fields

Yes, the easist way how to get search help functionality is just to provide its name within Screen painter beside the field name.

But what about a bit more complicated case, imagine, you would need to fill more dynpro fields based on search help result. Here you are out of standard techniques. Below example solves exactly this case.

It triggers manually standard SAP search help - in this case USER_COMP. This search help offers various selection methods how to pick a desired person, in the end it returns username.






Below F4 module gets username, reads user full name and fills both values on dynpro. Comments should be self explanatory enough ;-)


Dynpro coding:

PROCESS ON VALUE-REQUEST" F4 action
  FIELD gs_task_pool-responsible_pers MODULE f4_responsible.


Source code:


*&---------------------------------------------------------------------*
*&      Module  F4_RESPONSIBLE  INPUT
*&---------------------------------------------------------------------*
*       Transport values to dynpro/screen
*----------------------------------------------------------------------*
MODULE f4_responsible INPUT.

  DATAlt_dynpfields         TYPE STANDARD TABLE OF dynpread,
        ls_dynpfields         LIKE LINE OF lt_dynpfields,
        ls_shlp_descr         TYPE shlp_descr,
        lt_shlp_return_values TYPE STANDARD TABLE OF ddshretval,
        lv_username           TYPE xubname.

  " Get search help description
  CALL FUNCTION 'F4IF_GET_SHLP_DESCR'
    EXPORTING
      shlpname 'USER_COMP' " Standard SAP search help name
      shlptype 'SH'
    IMPORTING
      shlp     ls_shlp_descr.

  " Ask FM F4IF_START_VALUE_REQUEST for return values - set the sign
  FIELD-SYMBOLS<fs_interface> LIKE LINE OF ls_shlp_descr-interface.
  LOOP AT ls_shlp_descr-interface ASSIGNING <fs_interface>.
    <fs_interface>-valfield 'X'.
  ENDLOOP.

  " Trigger search help popup screen
  CALL FUNCTION 'F4IF_START_VALUE_REQUEST'
    EXPORTING
      shlp          ls_shlp_descr
    TABLES
      return_values lt_shlp_return_values.

  CLEAR lt_dynpfields.
  CLEAR ls_dynpfields.
  CLEAR lv_username.
  CLEAR gs_user_address.

  FIELD-SYMBOLS<fs_return_value> LIKE LINE OF lt_shlp_return_values.
  LOOP AT lt_shlp_return_values ASSIGNING <fs_return_value>.

    " Fill 1th screen field
    ls_dynpfields-fieldname  'GS_TASK_POOL-RESPONSIBLE_USR'.
    ls_dynpfields-fieldvalue <fs_return_value>-fieldval.
    APPEND ls_dynpfields TO lt_dynpfields.

    " Fill 2nd screen field
    lv_username <fs_return_value>-fieldval.
    gs_user_address lcl_main=>self->get_user_detailiv_username lv_username ).
    ls_dynpfields-fieldname  'GS_TASK_POOL-RESPONSIBLE_PERS'.
    ls_dynpfields-fieldvalue gs_user_address-fullname.
    CONDENSE  ls_dynpfields-fieldvalue.
    APPEND ls_dynpfields TO lt_dynpfields.

    EXIT" process just one item/person
  ENDLOOP.

  " Update screen fields
  CALL FUNCTION 'DYNP_VALUES_UPDATE'
    EXPORTING
      dyname     '/FDSEU/HCPC'    "Program name
      dynumb     '0220'           "Screen number
    TABLES
      dynpfields lt_dynpfields
    EXCEPTIONS
      OTHERS     0.

ENDMODULE.                 " F4_RESPONSIBLE  INPUT




Sources on net:




Wednesday, April 19, 2017

Splitter container in full screen - two ways

The Goal

is to have fully occupied space of the screen without usage of any tool of screen painter. Just the blank screen is enough, the rest is matter of below coding. In advance let me say, the second solution is much better :)

1) Docking container


The very first way is docking container, which is able to occupy whole screen very easily. See the coding below:


  DATA:
* Reference Variable for Docking Container
  go_dock_container  TYPE REF TO cl_gui_docking_container,
  go_split_container TYPE REF TO cl_gui_splitter_container.

  CREATE OBJECT go_dock_container
    EXPORTING
      repid        sy-repid " Report Name
      dynnr        sy-dynnr " Screen Number
      side                        cl_gui_docking_container=>dock_at_bottom
      extension                   cl_gui_docking_container=>ws_maximizebox

    EXCEPTIONS
      cntl_error                  1
      cntl_system_error           2
      create_error                3
      lifetime_error              4
      lifetime_dynpro_dynpro_link 5
      OTHERS                      6.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  CREATE OBJECT go_split_container
    EXPORTING
      parent            go_dock_container " Parent Container
      rows              " Number of Rows to be displayed
      columns           " Number of Columns to be Displayed
    EXCEPTIONS
      cntl_error        1
      cntl_system_error 2
      OTHERS            3.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.



The disadvantage of above solution is appearance of side resizing frame border. We need to occupy whole space, split it into two parts, but nothing else. You can not easily disable resizing on docking container.





2) Direct use of Splitter container


The the good message is that by removal of docking container we reach clean fully occupied screen without side resizing frame border.





See whole PBO coding:


  DATAgo_container_top   TYPE REF TO cl_gui_splitter_container,
        go_container_cell1 TYPE REF TO cl_gui_container,
        go_container_cell2 TYPE REF TO cl_gui_container,
        go_salv1           TYPE REF TO cl_salv_table,
        go_salv2           TYPE REF TO cl_salv_table,
        gt_data            TYPE STANDARD TABLE OF tstct,
        gx_msg             TYPE REF TO cx_salv_msg.

  CREATE OBJECT go_container_top
    EXPORTING
      link_dynnr        sy-dynnr " Screen Number
      link_repid        sy-repid " Report Name
      parent            cl_gui_container=>default_screen " Parent Container
      rows              " Number of Rows to be displayed
      columns           " Number of Columns to be Displayed
    EXCEPTIONS
      cntl_error        1
      cntl_system_error 2
      OTHERS            3.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

*   get part of splitter container for 1st table
  CALL METHOD go_container_top->get_container
    EXPORTING
      row       1
      column    1
    RECEIVING
      container go_container_cell1.

*   get part of splitter container for 2nd table
  CALL METHOD go_container_top->get_container
    EXPORTING
      row       2
      column    1
    RECEIVING
      container go_container_cell2.

  SELECT FROM tstct INTO TABLE gt_data WHERE sprsl 'E'.

  TRY.
      cl_salv_table=>factory(
      EXPORTING
        r_container go_container_cell1
      IMPORTING
        r_salv_table     go_salv1
      CHANGING
        t_table      gt_data ).
    CATCH cx_salv_msg INTO gx_msg.
      MESSAGE gx_msg TYPE 'E'.
  ENDTRY.

  TRY.
      cl_salv_table=>factory(
      EXPORTING
        r_container go_container_cell2
      IMPORTING
        r_salv_table     go_salv2
      CHANGING
        t_table      gt_data ).
    CATCH cx_salv_msg INTO gx_msg.
      MESSAGE gx_msg TYPE 'E'.
  ENDTRY.

  go_salv1->display).
  go_salv2->display).



Valuable hint taken from: http://inmyitkb.blogspot.com/2012/06/container-to-occupy-whole-screen.html