Quelquepart

Blog d'un développeur ABAP

Vous êtes ici : Accueil>Show code in Nugget

Show code in Nugget ZLISTCUBE.nugg

Table of content

Program ZLISTCUBE: Advanced Listviewer for InfoProvider

Text Elements

Text symbols

Text symbolLanguageTextLength
M01EDynamic selection50
M02EFields to display50
M03ESwitch to standard LISTCUBE50
M04EChoose file50
M05EPlease select the file to import50
M06EPlease select the file for export50
M07ECannot read the remote file50
M08EKey Figure24
M09EFree selection70
M10ESelection55
M11EType55
M12EInfo objet55
M13EDescription55
M14EInput file does not have the right structure50
M15ECSV File (*.csv)|*.csv50
M16ECannot create the remote file50
M17ECannot build fieldcat to display result50
M18EError when querrying the provider50
M19ELoaded by ZLISTCUBE80
M20EKey55
M21EPlease select an infoprovider50
M22ECan only import file generated with "export file" without column restriction79
M23ENo field selection managed for import50
M24EFile created50
M25EFilter selection cancelled by user50
M26EDim55
M27EField selection cancelled by user50
M28ECancelled by user50
M29ENumber of Entries30
M30EDisplay results for provider:50
M31ENumber of entries that match selection criteria :50
M32EDefault values50
T01EAction50
T02ETarget50
T03ETechnical - do not change50
T04EImport/Export options50
T05EDisplay options50

Selection texts

NameLanguageText
P_CUBEEInfoprovider
P_DBAGGEDB Aggregation
P_DISPLYEDisplay
P_EXPORTEExport to file
P_FILEEFile name
P_FILOCELocal file
P_HEADEREFile have 1 header line
P_IMPORTEImport from file
P_LIMITEMax. no. of hits
P_PKSIZEEPacket size
P_SELECTEDynamic selection
P_SERIALERead/write by packet
P_TECHEShow technical names
P_VARIEALV Variant
SO_FIELDEExcluded fields

GUI Status

GUI Status

CodeModalTitle
DISPLAY_FIELDSPItem_selection in Dialog Box with Checkbox
DYNSELPDynamic selections as dialog box (with execute)

Function code

CodeTextIcon
%SCFind@13@
%SC+Find next@4E@
&AC1Cancel@0W@
&ALLSelect all@4B@
&CRBFirst Column@0B@
&CRELast column@0C@
&CRLColumn left@0D@
&CRRColumn right@0E@
&ELPHelp@35@
&ETADetails@16@
&IC1Choose@16@
&ILTSet filter@4G@
&NT1Copy@0V@
&ODNSort in descending order@3F@
&OL0Change...@LZ@
&OUPSort in Ascending Order@3E@
&RNTPrint@0X@
&SALDeselect all@4D@
&XTRExtract management
CRETExecute@0V@
CRETExecute@0V@
DBACBack
DCANCancel@0W@
DELADelete All Selections@11@
DELSDelete Selection Row@18@
DENDExit
ECANCancel
ENDEExit
HIDETREEHide Field Selection
INTVRanges
NOINTSingle Values Only
NONECheck Entries@38@
OPTISelection Options@7X@
P+Next page
P++Last Page
P-Previous Page
P--First Page
PRINExecute and Print@0X@
REVERTDelete Selected Entries@11@
SCRHSelection Screen Help@0S@
SHOWTREENew Field Selection@3M@
SJOBExecute in Background
SWITCH_CHASwitch characteristics selection@4C@
SWITCH_DPASwitch datapack infoobjects selection@4C@
SWITCH_DTASelect DTA@4C@
SWITCH_KYFSelect KYF@4C@
SWITCH_TIMSwitch time infoobjects selection@4C@
SWITCH_UNISwitch unit infoobjects selection@4C@
SWITCH_ZKFSwitch key figure selection@4C@
TAKEAdopt Field Selection@0E@

Title bar

CodeText
DISPLAY_FIELDSChoose fields to display

ABAP Code

*&---------------------------------------------------------------------*
*& Program : ZLISTCUBE
*& Author  : S. Hermann
*& Date    : 30.06.2015
*& Version : 1.2.1
*&---------------------------------------------------------------------*
*  This program replace (and enhance) the standard listcube transaction
*  It allow you to :
*  - Display content of any infoprovider, as well as listcube does
*  - Choose dynamically selection fields you want to use
*  - Select dynamically which field you want to display
*  - Filter on key figure value
*  - Save or Load selection variant
*  - Use ALV display variant
*  - Count number en entries that match criteria
*  - Export infoprovider content to file (local/server)
*    It could be batched and is a very easy solution to export data
*    from BW to another system
*    If you dont specify any excluded field, nav attribute will also
*    be kept in the file (but always empty) : file format used by import
*  - Load infocube directly from file (local/server)
*    Import file must have the same structure as complete export file
*    with nav attributes
*    You can use the filter field to define restriction displayed in
*    Infoprovider management window for the load
*  - Extract huge amount of data by using serialization & server file
*  - If a complex query is not managed, you can switch to the standard
*    listcube directly from selection screen
*
*  Please Send comment & improvements to http://quelquepart.biz
*&---------------------------------------------------------------------*
* Limitations : It is not possible to filter on keyfigure for lines in
*               cube or DSO, only possible on result of the query
*               It mean that if db aggregation is choosen, filter is
*               done on aggregated value
*-
*               To extract huge amount of data, you need to use server
*               file and to use the "packet" option
*&---------------------------------------------------------------------*
* How to replace standard listcube (on BI 7.3):
*
* Class CL_RSAWBN_TOOLS_DTA - Method fcode_display_data.
* Replace (line 127)
*  SUBMIT rsdd_show_icube       WITH p_dta   = l_dta
*                               WITH p_ssids = 'X'
*                               WITH p_sdims = 'X'
*                               WITH p_dbagg = l_dbagg
*                               WITH p_tchnm = ' '
*                               AND RETURN.
* By
*  SUBMIT zlistcube WITH p_cube = l_dta
*                   WITH p_dbagg = l_dbagg
*                   VIA SELECTION-SCREEN AND RETURN.
*
* Program LRSM1F03 - Form rsm1_show_se16
* Replace (line 2047)
*  SUBMIT rsdd_show_icube "with p_cubet = l_s_cube-cubetype
*                          with p_dta   = l_s_cube-infocube
*                          with p_ssids = 'X'
*                          with p_sdims = 'X'
*                          with p_dbagg = ' '
*                          with p_tchnm = ' '
*                          and return.
* By
*  SUBMIT zlistcube WITH p_cube = l_s_cube-infocube
*                   WITH p_dbagg = space
*                   VIA SELECTION-SCREEN AND RETURN.
*
* Program LRSM1F13 - Form se16_ods
* Replace (line 3474)
*  SUBMIT rsdd_show_icube "with p_cubet = rsd_c_cubetype-basic_ic
*                          with p_dta   = p_ods
*                          with p_ssids = ' '
*                          with p_sdims = ' '
*                          with p_dbagg = ' '
*                          with p_tchnm = ' '
*                          and return.
* By
*  SUBMIT zlistcube WITH p_cube = p_ods
*                   WITH p_dbagg = space
*                   VIA SELECTION-SCREEN AND RETURN.
*
* Program LRSM1I02 - Module user_command_0310
* Replace (line 170)
* SUBMIT rsdd_show_icube "with p_cubet = l_s_cube-cubetype
*                        WITH p_dta   = l_s_cube-infocube
*                        WITH p_ssids = 'X'
*                        WITH p_sdims = 'X'
*                        WITH p_dbagg = ' '
*                        WITH p_tchnm = ' '
*                        AND RETURN.
* By
*  SUBMIT zlistcube WITH p_cube = l_s_cube-infocube
*                   WITH p_dbagg = space
*                   VIA SELECTION-SCREEN AND RETURN.
*
*&---------------------------------------------------------------------*
* How to fix SAP issue on recall previous selected values in sel.screen
* BE CARREFUL, THIS FIX IS EXPERIMENTAL
* Seem work on BI 7.30
*
* Function module FREE_SELECTIONS_INIT
* Insert after
*   LOOP AT FIELD_RANGES_INT INTO LS_RANGE.
*     IF LS_RANGE-TABLENAME = 'RSDS_DUMMY'.     " ALV or 'F'
*       CLEAR LS_RANGE-TABLENAME.
*     ENDIF.
* The following code
*   IF CURRENT_INFO-KIND = 'G'. "SHN for ZLISTCUBE
*     DATA ls_nota like line of CURRENT_INFO-nota.
*     CLEAR ls_nota.
*     READ TABLE CURRENT_INFO-nota into ls_nota
*                with key ldbnode = LS_RANGE-TABLENAME.
*   ENDIF.
*
* Insert after
*   if sy-subrc = 0.
*     <l_frange>-FIELDSEL  = LS_FRANGE-SELOPT_T.
*   else.
*     L_FRANGE-TABLENAME = LS_RANGE-TABLENAME.
* The following code
*   IF CURRENT_INFO-KIND = 'G' and not ls_nota is initial. "SHN for ZLISTCUBE
*     L_FRANGE-TABLENAME = ls_nota-structure.
*     L_FRANGE-ldbnode = LS_RANGE-TABLENAME.
*   ENDIF.
*
* Include LSSELFXX
* In context
*  LOOP AT P_FIELD_SEL_T INTO L_FIELD_SEL.
*    L_TABIX = SY-TABIX.
*    MOVE-CORRESPONDING L_FIELD_SEL TO L_FIKEY.
* Replace (Line 1557)
*   IF CURRENT_INFO-KIND = 'N' OR
*      CURRENT_INFO-KIND = 'G' AND CURRENT_INFO-QU_KEY-DBNA NE SPACE.
* By
*   IF CURRENT_INFO-KIND = 'N'.  "SHN for ZLISTCUBE
*
* In context
*   LOOP AT CURRENT_INFO-GROUPS INTO L_QU_GROUP_FI.
*     READ TABLE L_QU_GROUP_FI-FIELDS
* Replace (line 1588)
*          WITH KEY   LDBNODE   = P_FIELDS-TABLENAME
* By
*          WITH KEY   LDBNODE   = L_FIELD_SEL-LDBNODE "SHN for ZLISTCUBE
*
* In context
*   LOOP AT P_FIELDS.
*     if current_info-kind eq 'F'.
*       read table f_not_selected with key
*                  tablename = P_FIELDS-TABLENAME
*                  FIELDNAME = P_FIELDS-FIELDNAME
*                  transporting no fields.
*       l_not_selected_subrc = sy-subrc.
*     endif.
* Replace (line 1809)
*   IF CURRENT_INFO-KIND = 'N' OR
*      CURRENT_INFO-KIND = 'G' AND CURRENT_INFO-QU_KEY-DBNA NE SPACE.
* By
*   IF CURRENT_INFO-KIND = 'N'.  "SHN for ZLISTCUBE
*
*&---------------------------------------------------------------------*
*& History :
*& 2015.06.30 v1.2.1: Fix bug on selection screen recall variable
*& 2015.06.05 v1.2  : Add new standard modification point to fix a
*&                        selection screen issue
*&                    Add remember of previous selection for targets
*& 2014.03.09 v1.1  : Add a count entries button
*& 2013.12.10 v1.04 : Add new standard modification point in header
*& 2013.10.03 v1.03 : Cancel execution on popup cancellation
*& 2013.09.05 v1.02 : Fix button display on dynamic selection popup
*&                    Fix display techname in dynamic selection
*&                    Fix Remember filter/fields value if selected
*                     after executions
*& 2013.09.01 v1.01 : Add provider in title of the ALV
*&                    Add "Max no of rows" parameter
*&                    Fix error with non-cumul ratio
*&                    Add option to display tech. name in alv display
*&                    Add dim/key info on field selection popup
*& 2013.09.01 v1.0  : Initial release
*&---------------------------------------------------------------------*
* todo : navigation attribute

REPORT zlistcube.
TABLES sscrfields. "for button on selection screen

TYPES ty_dsqfn TYPE STANDARD TABLE OF rsdsqfn.
DATA : w_iobj TYPE rsdiobjnm,
       s_variant TYPE disvariant.                           "#EC NEEDED
DATA : BEGIN OF s_fields,                                   "#EC NEEDED
         selkz(1) TYPE c,
         type(3) TYPE c,
         iobjnm(30) TYPE c,
         txtlg(60) TYPE c,
         key(4) TYPE c,
       END OF s_fields,
       t_fields LIKE TABLE OF s_fields,                     "#EC NEEDED
       BEGIN OF s_default,
         cube TYPE rsinfoprov,
         sel TYPE string,
         t_fields LIKE RANGE OF w_iobj,
       END OF s_default,
       t_default LIKE TABLE OF s_default,
       w_shared_param(30) TYPE c,
       w_init(1) TYPE c.

CONSTANTS : c_separator TYPE abap_char1
                        VALUE cl_abap_char_utilities=>horizontal_tab,
            c_msg_error(1) TYPE c VALUE 'E',
            c_msg_success(1) TYPE c VALUE 'S',
            c_msg_info(1) TYPE c VALUE 'I',
            c_true(1) TYPE c VALUE 'X',
            c_line_separator(1) TYPE c VALUE '|',
            c_field_separator(1) TYPE c VALUE ';',
            c_variant_save(1) TYPE c VALUE 'A',
            c_dimension_key_dso TYPE rsdimension VALUE 'KEY',
            c_numb_key TYPE rsdsqgt-numb VALUE '1',
            c_numb_kf TYPE rsdsqgt-numb VALUE 'Z',
            c_max_popup_endline TYPE i VALUE 25,
            c_header_na TYPE abap_compname VALUE '#'.

SELECTION-SCREEN FUNCTION KEY 1.
SELECTION-SCREEN FUNCTION KEY 2.
SELECTION-SCREEN FUNCTION KEY 3.
SELECTION-SCREEN FUNCTION KEY 4.

* Target+general options
SELECTION-SCREEN BEGIN OF BLOCK two WITH FRAME TITLE text-t02.
PARAMETERS p_cube TYPE rsinfoprov OBLIGATORY.
* DB aggregation
PARAMETERS p_dbagg AS CHECKBOX DEFAULT 'X'. "used when call listcube
PARAMETERS p_limit TYPE i DEFAULT 0.
SELECTION-SCREEN END OF BLOCK two.

* Action
SELECTION-SCREEN BEGIN OF BLOCK one WITH FRAME TITLE text-t01.
PARAMETERS p_disply RADIOBUTTON GROUP act DEFAULT 'X'.
PARAMETERS p_export RADIOBUTTON GROUP act.
PARAMETERS p_import RADIOBUTTON GROUP act.
SELECTION-SCREEN COMMENT 36(79) text-m22.
PARAMETER p_count NO-DISPLAY.
SELECTION-SCREEN END OF BLOCK one.

* Display option
SELECTION-SCREEN BEGIN OF BLOCK for WITH FRAME TITLE text-t05.
* Display tech name instead of label
PARAMETERS p_tech AS CHECKBOX.
* ALV Variant
PARAMETERS p_vari TYPE disvariant-variant.
SELECTION-SCREEN END OF BLOCK for.

* File options
SELECTION-SCREEN BEGIN OF BLOCK tri WITH FRAME TITLE text-t04.
* Use local file instead of server ?
* Usercommand to refresh screen when option change
PARAMETERS p_filoc AS CHECKBOX USER-COMMAND dummy.
* File folder/name (local or server)
PARAMETERS p_file TYPE string LOWER CASE.
* Header line for the file
PARAMETERS p_header AS CHECKBOX.
* Read/write by packet (server file only)
PARAMETERS p_serial AS CHECKBOX.
* Packet size for read/write on server
PARAMETERS p_pksize TYPE i DEFAULT 10000 OBLIGATORY.
SELECTION-SCREEN END OF BLOCK tri.

* Technical fields
SELECTION-SCREEN SKIP 1.
SELECTION-SCREEN BEGIN OF BLOCK fiv WITH FRAME TITLE text-t03.
PARAMETERS p_select TYPE string.
SELECT-OPTIONS so_field FOR w_iobj NO INTERVALS.
SELECTION-SCREEN END OF BLOCK fiv.

INITIALIZATION.
* Define text of button on selection-screen
  CONCATENATE '@7Z@' 'Dynamic selection'(m01)
              INTO sscrfields-functxt_01 SEPARATED BY space.

  CONCATENATE '@LZ@' 'Fields to display'(m02)
              INTO sscrfields-functxt_02 SEPARATED BY space.

  CONCATENATE '@46@' 'Default values'(m32)
              INTO sscrfields-functxt_03 SEPARATED BY space.

  CONCATENATE '@2Q@' 'Switch to standard LISTCUBE'(m03)
              INTO sscrfields-functxt_04 SEPARATED BY space.

  CONCATENATE '@3Z@' 'Number of Entries'(m29)
              INTO sscrfields-functxt_05 SEPARATED BY space.

AT SELECTION-SCREEN OUTPUT.
* Get default value at first PBO (after got data from submit variable)
  IF w_init IS INITIAL.
    w_init = 'X'.
    PERFORM get_default_values.
  ENDIF.

* ALV variant selection search-help
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_vari.
  DATA: l_exit.
  CLEAR s_variant.
  s_variant-report  = sy-repid.
  s_variant-variant = p_vari.

  CALL FUNCTION 'REUSE_ALV_VARIANT_F4'
    EXPORTING
      is_variant         = s_variant
      i_save             = c_variant_save
      i_display_via_grid = c_true
    IMPORTING
      e_exit             = l_exit
      es_variant         = s_variant
    EXCEPTIONS
      not_found          = 2.
  IF sy-subrc = 0.
    IF l_exit = space.
      p_vari = s_variant-variant.
    ENDIF.
  ENDIF.

* File search-help
AT SELECTION-SCREEN ON VALUE-REQUEST FOR p_file.
  PERFORM prompt_for_file USING 'Choose file'(m04) p_filoc
                          CHANGING p_file.

AT SELECTION-SCREEN.
  DATA : l_return TYPE i.
  IF sy-ucomm = 'FC01'.
    PERFORM display_selection CHANGING l_return.
  ELSEIF sy-ucomm = 'FC02'.
    PERFORM display_fields CHANGING l_return.
  ELSEIF sy-ucomm = 'FC03'.
    PERFORM get_default_values.
  ELSEIF sy-ucomm = 'FC04'.
    SUBMIT rsdd_show_icube       WITH p_dta   = p_cube
                                 WITH p_ssids = c_true
                                 WITH p_sdims = c_true
                                 WITH p_dbagg = p_dbagg
                                 WITH p_tchnm = space
                                 AND RETURN.
  ELSEIF sy-ucomm = 'FC05'.
* For export/display, If no selection done, display selection popup
    IF p_import = space AND p_select IS INITIAL.
      PERFORM display_selection CHANGING l_return.
      IF NOT l_return IS INITIAL.
        MESSAGE 'Cancelled by user'(m28) TYPE c_msg_success
                DISPLAY LIKE c_msg_error.
        STOP.
      ENDIF.
    ENDIF.
* For export/display, If no field restriction, display field list
    IF p_import = space AND so_field IS INITIAL.
      PERFORM display_fields CHANGING l_return.
      IF NOT l_return IS INITIAL.
        MESSAGE 'Cancelled by user'(m28) TYPE c_msg_success
                DISPLAY LIKE c_msg_error.
        STOP.
      ENDIF.
    ENDIF.
    p_count = c_true.
    PERFORM export_cube.
  ELSEIF sy-ucomm = 'ONLI'.
* For export/display, If no selection done, display selection popup
    IF p_import = space AND p_select IS INITIAL.
      PERFORM display_selection CHANGING l_return.
      IF NOT l_return IS INITIAL.
        MESSAGE 'Cancelled by user'(m28) TYPE c_msg_success
                DISPLAY LIKE c_msg_error.
        STOP.
      ENDIF.
    ENDIF.
* For export/display, If no field restriction, display field list
    IF p_import = space AND so_field IS INITIAL.
      PERFORM display_fields CHANGING l_return.
      IF NOT l_return IS INITIAL.
        MESSAGE 'Cancelled by user'(m28) TYPE c_msg_success
                DISPLAY LIKE c_msg_error.
        STOP.
      ENDIF.
    ENDIF.
  ENDIF.

START-OF-SELECTION.
  CLEAR p_count.

  IF p_cube IS INITIAL.
    MESSAGE 'Please select an infoprovider'(m21)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    RETURN.
  ENDIF.

  IF p_import NE space.
    IF p_file IS INITIAL.
      MESSAGE 'Please select the file to import'(m05)
              TYPE c_msg_success DISPLAY LIKE c_msg_error.
      RETURN.
    ELSEIF NOT so_field IS INITIAL.
      MESSAGE 'No field selection managed for import'(m23)
              TYPE c_msg_success DISPLAY LIKE c_msg_error.
      RETURN.
    ELSE.
      PERFORM import_cube.
    ENDIF.
  ELSE.
    IF p_file IS INITIAL AND p_export NE space.
      MESSAGE 'Please select the file for export'(m06)
              TYPE c_msg_success DISPLAY LIKE c_msg_error.
      RETURN.
    ELSE.
      PERFORM set_default_values.
      PERFORM export_cube.
    ENDIF.
  ENDIF.

*&---------------------------------------------------------------------*
*&      Form  EXPORT_CUBE
*&---------------------------------------------------------------------*
*       Write content of a cube in a file
*----------------------------------------------------------------------*
FORM export_cube .
  DATA : lo_dta TYPE REF TO if_rsd_dta,
         lt_dta_pro TYPE rsd_t_dta_pro,
         ls_dta_pro LIKE LINE OF lt_dta_pro,
         ls_dta TYPE rsd_s_dta,
         lt_ioinf TYPE rsdq_t_iobj_info,
         ls_ioinf LIKE LINE OF lt_ioinf,
         lt_sfc TYPE rsdd_th_sfc, "characteristics
         lt_sfk TYPE rsdd_th_sfk, "key figures
         ls_sfk LIKE LINE OF lt_sfk,
         lt_tsx_sel TYPE rsdd_tsx_seldr, "selection criteria
         ls_tsx_sel LIKE LINE OF lt_tsx_sel,
         lt_key_sel TYPE rsdrc_t_selk,
         ls_key_sel LIKE LINE OF lt_key_sel,
         ls_range LIKE LINE OF ls_tsx_sel-range-range,
         lo_data_full TYPE REF TO data,
         lo_data_pack TYPE REF TO data,
         lt_prov TYPE rsdr0_ts_provrq,
         lo_state TYPE REF TO cl_rsdrc_infoprov_state,
         lw_eod TYPE rs_bool,
         lw_range_string TYPE string,
         lt_range TYPE TABLE OF string,
         lw_index TYPE i,
         lw_exec_mode TYPE rsdr0_exec,
         lw_first_write(1) TYPE c,
         lt_where TYPE rsds_where_tab,
         lo_error TYPE REF TO cx_root,
         lw_nblines TYPE i,
         lw_nblinespack TYPE i,
         lw_message TYPE string.

  FIELD-SYMBOLS : <lft_data_full> TYPE STANDARD TABLE,
                  <lft_data_pack> TYPE STANDARD TABLE.
  FIELD-SYMBOLS : <fs_sfc> TYPE rrsfc01,
                  <fs_sfk> TYPE rrsfk01.

  PERFORM get_cube_receiver CHANGING lo_data_full.
  ASSIGN lo_data_full->* TO <lft_data_full>.
  CREATE DATA lo_data_pack LIKE <lft_data_full>.
  ASSIGN lo_data_pack->* TO <lft_data_pack>.

* Get field list
  lo_dta = cl_rsd_dta=>factory( p_cube ).
  CALL METHOD lo_dta->dta_get_info
    EXPORTING
      i_with_atr_nav = space
    IMPORTING
      e_t_dta_pro    = lt_dta_pro
      e_s_dta        = ls_dta.

* Delete Non-cumulative ratio (that are not in the cube)
  DELETE lt_dta_pro WHERE NOT ncumfl IS INITIAL.

* Fill filter tables
  IF NOT p_select IS INITIAL.
    SPLIT p_select AT c_line_separator INTO TABLE lt_range.
    LOOP AT lt_range INTO lw_range_string.
      CLEAR : ls_range, ls_tsx_sel, ls_key_sel.
      SPLIT lw_range_string AT c_field_separator
            INTO ls_tsx_sel-chanm ls_range-sign ls_range-opt
                 ls_range-low ls_range-high.
      READ TABLE lt_dta_pro INTO ls_dta_pro
                            WITH KEY iobjnm = ls_tsx_sel-chanm.
      CHECK sy-subrc = 0.
* For key figure, add filter to lt_key_sel
      IF ls_dta_pro-iobjtp = rsd_c_objtp-keyfigure.
        ls_key_sel-kyfnm = ls_tsx_sel-chanm.
        ls_key_sel-compop = ls_range-opt.
        ls_key_sel-low = ls_range-low.
        ls_key_sel-high = ls_range-high.
        ls_key_sel-level = 0.
        ls_key_sel-isolate = 0.
        ls_key_sel-numfl = c_true.

        IF ls_range-sign = rs_c_range_sign-excluding.
          IF lt_key_sel IS INITIAL.
            ls_key_sel-boolop = rsdrs_c_boolop-not.
          ELSE.
            ls_key_sel-boolop = rsdrs_c_boolop-and_not.
          ENDIF.
        ELSE.
          IF lt_key_sel IS INITIAL.
            ls_key_sel-boolop = rsdrs_c_boolop-none.
          ELSE.
            ls_key_sel-boolop = rsdrs_c_boolop-and.
          ENDIF.
        ENDIF.
        APPEND ls_key_sel TO lt_key_sel.
* For characteristics, add filter to lt_tsx_sel
      ELSE.
        ls_tsx_sel-seltyp = rsdd_c_seltyp-range.
        ls_tsx_sel-cum_used = 1.
        ls_range-keyfl = c_true.
        READ TABLE lt_tsx_sel INTO ls_tsx_sel
                              WITH KEY chanm = ls_tsx_sel-chanm.
        lw_index = sy-tabix.
        IF sy-subrc = 0.
          APPEND ls_range TO ls_tsx_sel-range-range.
          MODIFY lt_tsx_sel FROM ls_tsx_sel INDEX lw_index.
        ELSE.
          APPEND ls_range TO ls_tsx_sel-range-range.
          INSERT ls_tsx_sel INTO TABLE lt_tsx_sel.
        ENDIF.
      ENDIF.
    ENDLOOP.
    CALL METHOD cl_rsdrc_seldr_srvs=>set_seldr_chanmid
      CHANGING
        c_tsx_seldr = lt_tsx_sel.
  ENDIF.

* Transcode field list into char/kf
  LOOP AT lt_dta_pro INTO ls_dta_pro.
    MOVE-CORRESPONDING ls_dta_pro TO ls_ioinf.
    ls_ioinf-show_val = c_true.
    ls_ioinf-selname = ls_ioinf-iobjnm.
    APPEND ls_ioinf TO lt_ioinf.
  ENDLOOP.
  PERFORM build_sf_tables IN PROGRAM saplrsdq
          USING p_cube lt_tsx_sel space space
          CHANGING lt_ioinf lt_sfc lt_sfk.

* Do not query on excluded fields
  IF NOT so_field[] IS INITIAL.
    LOOP AT lt_sfc ASSIGNING <fs_sfc> WHERE chanm IN so_field.
      CLEAR : <fs_sfc>-keyret,
              <fs_sfc>-keyret_0,
              <fs_sfc>-keyret_n,
              <fs_sfc>-keyret_c0,
              <fs_sfc>-keyreturnnm.
    ENDLOOP.
    LOOP AT lt_sfk ASSIGNING <fs_sfk> WHERE kyfnm IN so_field.
* Keep key figure in case of post-query filter
      IF ( ls_dta-tlogo = 'ODSO' OR p_dbagg = space )
      AND NOT lt_key_sel IS INITIAL.
        READ TABLE lt_key_sel WITH KEY kyfnm = <fs_sfk>-kyfnm
                   TRANSPORTING NO FIELDS.
        CHECK sy-subrc NE 0.
      ENDIF.
      <fs_sfk>-value_returnnm = space.
      <fs_sfk>-kyfret = space.
    ENDLOOP.
  ENDIF.

* Built infoprovider header
  lt_prov = cl_rsdrc_provrq_srvs=>get_provrq(
              i_infoprov   = p_cube
              i_th_sfk     = lt_sfk
              i_tsx_seldr  = lt_tsx_sel
              i_with_nls   = space
              i_actualdata = rsrcd_c_actualdata-dirty
            ).

* Update keyfigure filter to add aggr
  IF NOT lt_key_sel IS INITIAL.
    LOOP AT lt_key_sel INTO ls_key_sel.
      READ TABLE lt_sfk INTO ls_sfk WITH KEY kyfnm = ls_key_sel-kyfnm.
      IF sy-subrc = 0.
        ls_key_sel-aggr = ls_sfk-aggrgen.
        MODIFY lt_key_sel FROM ls_key_sel TRANSPORTING aggr.
      ENDIF.
    ENDLOOP.
  ENDIF.

* Save in file by packet is only used with serial mode
  IF p_serial = space.
    lw_exec_mode = 'A'. "parallel
  ELSE.
    lw_exec_mode = space. "serial
  ENDIF.

* Key figure restriction is not allowed without db aggregation
* Standard query restriction : keyfigure restriction is done in having
* clause that require a group by that is done only if db aggregation
* To bypass this problem, restriction is done after querying
* DSO cannot also filter keyfigure, same bypass used
  IF ( ls_dta-tlogo = 'ODSO' OR p_dbagg = space )
  AND NOT lt_key_sel IS INITIAL.
    PERFORM get_where_clause_from_key_sel USING lt_key_sel
                                                ls_dta-viewtiobjnm2
                                          CHANGING lt_where.
    REFRESH lt_key_sel.
  ENDIF.

  lw_eod = space.
  lw_first_write = c_true.
  lw_nblines = 0.
  WHILE lw_eod = space.
    TRY.
*        lw_exec_mode = space. "Force serial mode for debug purpose
        CALL FUNCTION 'RSDRC_INFOPROV_READ'
          EXPORTING
            i_ts_provrq          = lt_prov
            i_tsx_seldr          = lt_tsx_sel "selection criteria IOBJ
            i_t_selk             = lt_key_sel "selection criteria KF
            i_th_sfc             = lt_sfc "displayed iobj
            i_th_sfk             = lt_sfk "displayed kf
            i_use_db_aggregation = p_dbagg "not work without dbagg
            i_packagesize        = p_pksize
            i_maxrows            = p_limit
*           I_AUTHORITY_CHECK    = RSDRC_C_AUTHCHK-READ
            i_exec_mode          = lw_exec_mode
*           i_show_report        = c_true "display sql for debug purpose
          IMPORTING
            e_t_data             = <lft_data_pack>
            e_end_of_data        = lw_eod
          CHANGING
            c_r_state            = lo_state.
      CATCH cx_rs_not_authorized
            cx_rsdr_cube_locked
            cx_static_check
            cx_rsr_x_message INTO lo_error.
* If error occurs, you can check SM21 to see detailed information
        lw_range_string = lo_error->get_text( ).
        MESSAGE lw_range_string TYPE c_msg_error.
        lw_eod = c_true.
        EXIT.
    ENDTRY.

    IF NOT lt_where IS INITIAL.
      DELETE <lft_data_pack> WHERE (lt_where).
    ENDIF.

* Transfer file by packet (usefull for huge extraction)
* Query dump if transfer local file
    IF p_count = c_true.
      DESCRIBE TABLE <lft_data_pack> LINES lw_nblinespack.
      lw_nblines = lw_nblines + lw_nblinespack.
    ELSEIF p_filoc = space AND p_export NE space.
      PERFORM write_file USING lo_data_pack
                               p_filoc
                               p_file
                               lw_first_write
                               p_header
                               lt_dta_pro.
      lw_first_write = space.
    ELSE.
      APPEND LINES OF <lft_data_pack> TO <lft_data_full>.
    ENDIF.
    REFRESH <lft_data_pack>.
  ENDWHILE.

* Write the file
  IF p_count = c_true.
    lw_message = lw_nblines.
    CONCATENATE 'Number of entries that match selection criteria :'(m31)
                lw_message INTO lw_message SEPARATED BY space.
    CONDENSE lw_message.
    MESSAGE lw_message TYPE c_msg_info.
  ELSEIF p_export NE space.
    IF NOT <lft_data_full> IS INITIAL.
      PERFORM write_file USING lo_data_full
                               p_filoc
                               p_file
                               c_true
                               p_header
                               lt_dta_pro.
    ENDIF.
    MESSAGE 'File created'(m24) TYPE c_msg_success.
* Or Display data
  ELSE.
    PERFORM display_alv USING lo_data_full
                              lt_dta_pro
                              ls_dta-viewtiobjnm2.

  ENDIF.
ENDFORM.                    " EXPORT_CUBE

*&---------------------------------------------------------------------*
*&      Form  IMPORT_CUBE
*&---------------------------------------------------------------------*
*       Write content of the file in the cube
*----------------------------------------------------------------------*
FORM import_cube.
  DATA : lo_data TYPE REF TO data,
         lw_line TYPE string,
         lt_line TYPE TABLE OF string,
         lw_lines TYPE i,
         lw_controled(1) TYPE c,
         lw_in_fields TYPE i,
         lw_out_fields TYPE i,
         lo_descr TYPE REF TO cl_abap_structdescr,
         lt_file TYPE TABLE OF string,
         lw_requid TYPE rsrequnr,
         lr_requid TYPE RANGE OF rsrequnr,
         ls_requid LIKE LINE OF lr_requid,
         lw_selopt TYPE rsstatmanpartt-selopt,
         lw_error(1) TYPE c,
         ls_rscedst TYPE rscedst.

  FIELD-SYMBOLS : <lft_data> TYPE STANDARD TABLE,
                  <lfs_data> TYPE any,
                  <lf_data> TYPE any.

  DEFINE append_lw_requid.
    ls_requid = 'IEQ'.
    ls_requid-low = lw_requid.
    append ls_requid to lr_requid.
  END-OF-DEFINITION.

* Create data receiver
  PERFORM get_cube_receiver CHANGING lo_data.
  ASSIGN lo_data->* TO <lft_data>.
  CREATE DATA lo_data LIKE LINE OF <lft_data>.
  ASSIGN lo_data->* TO <lfs_data>.

* Read the file
  IF p_filoc = space.
*  Server file
    OPEN DATASET p_file FOR INPUT IN TEXT MODE ENCODING DEFAULT.
    IF sy-subrc NE 0.
      MESSAGE 'Cannot read the remote file'(m07) TYPE c_msg_error.
      RETURN.
    ENDIF.
    lw_lines = 0.
    lw_controled = space.
* If header line, skip it
    IF p_header NE space.
      READ DATASET p_file INTO lw_line.
    ENDIF.
* Read the file, line by line
    DO.
      READ DATASET p_file INTO lw_line.
      IF sy-subrc NE 0.
        EXIT.
      ENDIF.
      SPLIT lw_line AT c_separator INTO TABLE lt_line.

* For 1st line, Check file have the right number of columns
      IF lw_controled NE c_true.
        DESCRIBE TABLE lt_line LINES lw_in_fields.
        lo_descr ?= cl_abap_typedescr=>describe_by_data( <lfs_data> ).
        DESCRIBE TABLE lo_descr->components LINES lw_out_fields.
        IF lw_in_fields NE lw_out_fields.
          MESSAGE 'Input file does not have the right structure'(m14)
                  TYPE c_msg_error.
          RETURN.
        ENDIF.
        lw_controled = c_true.
      ENDIF.

      LOOP AT lt_line INTO lw_line.
        ASSIGN COMPONENT sy-tabix OF STRUCTURE <lfs_data> TO <lf_data>.
        IF sy-subrc NE 0.
          EXIT.
        ENDIF.
        <lf_data> = lw_line.
      ENDLOOP.
      APPEND <lfs_data> TO <lft_data>.

* Manage write by packet
      IF p_serial NE space.
        ADD 1 TO lw_lines.
        IF lw_lines GE p_pksize.
          CALL FUNCTION 'RSDRI_CUBE_WRITE_PACKAGE'
            EXPORTING
              i_infocube        = p_cube
              i_curr_conversion = rs_c_false
            IMPORTING
              e_requid          = lw_requid
            CHANGING
              c_t_data          = <lft_data>
            EXCEPTIONS
              OTHERS            = 0.
          append_lw_requid.
          CLEAR lw_lines.
          REFRESH <lft_data>.
        ENDIF.
      ENDIF.
    ENDDO.
    CLOSE DATASET p_file.

*  Local file file
  ELSE.
* It may be possible to read file directly into <lft_data> to be faster
* but header line was not managed, and there was no controle possible
    CALL METHOD cl_gui_frontend_services=>gui_upload
      EXPORTING
        filename = p_file
      CHANGING
        data_tab = lt_file
      EXCEPTIONS
        OTHERS   = 0.
    IF p_header NE space.
      DELETE lt_file INDEX 1.
    ENDIF.
    lw_lines = 0.
    lw_controled = space.
    LOOP AT lt_file INTO lw_line.
      SPLIT lw_line AT c_separator INTO TABLE lt_line.

* For 1st line, Check file have the right number of columns
      IF lw_controled NE c_true.
        DESCRIBE TABLE lt_line LINES lw_in_fields.
        lo_descr ?= cl_abap_typedescr=>describe_by_data( <lfs_data> ).
        DESCRIBE TABLE lo_descr->components LINES lw_out_fields.
        IF lw_in_fields NE lw_out_fields.
          MESSAGE 'Input file does not have the right structure'(m14)
                  TYPE c_msg_error.
          RETURN.
        ENDIF.
        lw_controled = c_true.
      ENDIF.

      LOOP AT lt_line INTO lw_line.
        ASSIGN COMPONENT sy-tabix OF STRUCTURE <lfs_data> TO <lf_data>.
        IF sy-subrc NE 0.
          EXIT.
        ENDIF.
        <lf_data> = lw_line.
      ENDLOOP.
      APPEND <lfs_data> TO <lft_data>.

* Manage write by packet
      IF p_serial NE space.
        ADD 1 TO lw_lines.
        IF lw_lines GE p_pksize.
          CALL FUNCTION 'RSDRI_CUBE_WRITE_PACKAGE'
            EXPORTING
              i_infocube        = p_cube
              i_curr_conversion = rs_c_false
            IMPORTING
              e_requid          = lw_requid
            CHANGING
              c_t_data          = <lft_data>
            EXCEPTIONS
              OTHERS            = 0.
          append_lw_requid.
          CLEAR lw_lines.
          REFRESH <lft_data>.
        ENDIF.
      ENDIF.
    ENDLOOP.
  ENDIF.

* Write file content in the cube
  IF NOT <lft_data> IS INITIAL.
    CALL FUNCTION 'RSDRI_CUBE_WRITE_PACKAGE'
      EXPORTING
        i_infocube        = p_cube
        i_curr_conversion = rs_c_false
      IMPORTING
        e_requid          = lw_requid
      CHANGING
        c_t_data          = <lft_data>
      EXCEPTIONS
        OTHERS            = 0.
    append_lw_requid.
  ENDIF.

* Update request info
  IF NOT lr_requid[] IS INITIAL.
    IF NOT p_select IS INITIAL.
      lw_selopt = p_select.
    ENDIF.

* Flush standard request info update to avoid further overwrite
    PERFORM rsm1_init_parttab IN PROGRAM saplrsm1
                              USING p_cube c_true ls_rscedst space
                              CHANGING lw_error.

    UPDATE rsstatmanpartt
           SET infopak = 'Loaded by ZLISTCUBE'(m19)
               selopt = lw_selopt
           WHERE rnr IN lr_requid.
  ENDIF.
ENDFORM.                    " IMPORT_CUBE

*&---------------------------------------------------------------------*
*&      Form  GET_CUBE_RECEIVER
*&---------------------------------------------------------------------*
*       Create a data receiver for the cube
*----------------------------------------------------------------------*
*      <--FO_DATA Table with cube structure
*----------------------------------------------------------------------*
FORM get_cube_receiver CHANGING fo_data TYPE REF TO data.
  DATA : lo_dta TYPE REF TO if_rsd_dta,
         ls_dta TYPE rsd_s_dta.
  FIELD-SYMBOLS <lfs_data> TYPE any.

* Get flat structure of the cube fields

  lo_dta = cl_rsd_dta=>factory( p_cube ).
  CALL METHOD lo_dta->dta_get_info
    EXPORTING
      i_with_atr_nav = space
    IMPORTING
      e_s_dta        = ls_dta.
  IF ls_dta IS INITIAL.
    MESSAGE ID 'R7' TYPE c_msg_error NUMBER 791 WITH p_cube.
    RETURN.
  ENDIF.

* Create data receiver
  CREATE DATA fo_data TYPE (ls_dta-viewtiobjnm2).
*  CREATE DATA fo_data TYPE (ls_dta-VIEWIOBJ). "w/o nav attr
  ASSIGN fo_data->* TO <lfs_data>.
  CREATE DATA fo_data LIKE STANDARD TABLE OF <lfs_data>
                      WITH DEFAULT KEY.
ENDFORM.                    " GET_CUBE_RECEIVER

*&---------------------------------------------------------------------*
*&      Form  DISPLAY_SELECTION
*&---------------------------------------------------------------------*
*       Display dynamic selection screen popup
*----------------------------------------------------------------------*
FORM display_selection CHANGING fp_subrc TYPE i.
  DATA : lw_selid TYPE rsdynsel-selid,
         lt_fields TYPE TABLE OF rsdsfields,
         ls_fields LIKE LINE OF lt_fields,
         lt_field_ranges TYPE rsds_trange,
         ls_range LIKE LINE OF lt_field_ranges,
         ls_frange LIKE LINE OF ls_range-frange_t,
         ls_group TYPE rsdsqcat,
         ls_rsdsqgt TYPE rsdsqgt,
         dsqgn TYPE TABLE OF rsdsqgn WITH HEADER LINE,
         dsqtn TYPE TABLE OF rsdsqtn WITH HEADER LINE,
         dsqfn TYPE TABLE OF rsdsqfn WITH HEADER LINE,
         lw_dim_length TYPE i,
*         BEGIN OF ls_iobj,
*           dimension TYPE rsddimeiobj-dimension,
*           posit TYPE rsddimeiobj-posit,
*           iobjnm TYPE rsddimeiobj-iobjnm,
*         END OF ls_iobj,
*         lt_iobj LIKE TABLE OF ls_iobj,
         ls_ldbn TYPE ldbn,
         lo_dta TYPE REF TO if_rsd_dta,
         lt_dta_pro TYPE rsd_t_dta_pro,
         ls_dta_pro LIKE LINE OF lt_dta_pro,
         lt_dime TYPE rsd_t_dta_dime,
         ls_dime LIKE LINE OF lt_dime,
         ls_dta TYPE rsd_s_dta,
         lw_fsname(30),
         ls_gui TYPE rsdspfkey,
         lt_field_texts	LIKE TABLE OF rsdstexts,
         ls_field_texts LIKE LINE OF lt_field_texts.

  FIELD-SYMBOLS <lfs_table> TYPE STANDARD TABLE.

  CLEAR fp_subrc.

* Get information about infoprovider
  lo_dta = cl_rsd_dta=>factory( p_cube ).
  CALL METHOD lo_dta->dta_get_info
    EXPORTING
      i_with_atr_nav = space
    IMPORTING
      e_t_dta_pro    = lt_dta_pro
      e_t_dta_dime   = lt_dime
      e_s_dta        = ls_dta.

* Delete Non-cumulative ratio (that are not in the cube)
  DELETE lt_dta_pro WHERE NOT ncumfl IS INITIAL.

* Create the selection view :
* - rsdsqcat : header of the view
* - rsdsqgt : group+names of the view
* - ldbn : logical DB : structure linked to group
* - dsqgn : group of the view
* - dsqfn : Fields of the view with group
  ls_group-origin = 'CUS'.
  CONCATENATE 'LISTCUBE' sy-uname INTO ls_group-dbna.
  ls_group-name = p_cube. "'STANDARD'.
  SELECT SINGLE origin dbna name
         INTO ls_group
         FROM rsdsqcat
         WHERE origin = ls_group-origin
         AND dbna = ls_group-dbna
         AND name = ls_group-name.
  IF sy-subrc NE 0.
    INSERT rsdsqcat FROM ls_group.
  ENDIF.

  DELETE FROM rsdsqgt
         WHERE origin = ls_group-origin
         AND dbna = ls_group-dbna
         AND name = ls_group-name.

  ls_rsdsqgt-origin = ls_group-origin.
  ls_rsdsqgt-dbna = ls_group-dbna.
  ls_rsdsqgt-name = ls_group-name.
  LOOP AT lt_dime INTO ls_dime.
    IF ls_dime-dimension = c_dimension_key_dso. "Key part of DSO
      dsqgn = ls_rsdsqgt-numb = c_numb_key.
    ELSE.
      lw_dim_length = strlen( ls_dime-dimension ) - 1.
      dsqgn = ls_rsdsqgt-numb = ls_dime-dimension+lw_dim_length(1).
    ENDIF.
    ls_rsdsqgt-gtext = ls_dime-txtlg.
    ls_rsdsqgt-lang = ls_dime-langu.
    INSERT rsdsqgt FROM ls_rsdsqgt.
    APPEND dsqgn.
  ENDLOOP.
  dsqgn = ls_rsdsqgt-numb = c_numb_kf.
  ls_rsdsqgt-gtext = 'Key Figure'(m08).
  ls_rsdsqgt-lang = sy-langu.
  INSERT rsdsqgt FROM ls_rsdsqgt.
  APPEND dsqgn.

  SORT lt_dta_pro BY dimension posit.
  LOOP AT lt_dta_pro INTO ls_dta_pro.
    CLEAR dsqfn.
    IF ls_dta_pro-dimension IS INITIAL. "key figure
      dsqfn-numb = c_numb_kf.
      dsqfn-tab = 'KF'.
    ELSE.
      IF ls_dta_pro-dimension = c_dimension_key_dso. "Key part of DSO
        dsqfn-numb = c_numb_key.
      ELSE.
        lw_dim_length = strlen( ls_dta_pro-dimension ) - 1.
        dsqfn-numb = ls_dta_pro-dimension+lw_dim_length(1).
      ENDIF.
      dsqfn-tab = ls_dta_pro-dimension.
    ENDIF.
    dsqfn-fname = ls_dta_pro-iobjnm.
    APPEND dsqfn.
  ENDLOOP.

  EXPORT dsqgn dsqtn dsqfn TO DATABASE rsdsqobj(sv) ID ls_group.

  DELETE FROM ldbn
         WHERE ldbname = ls_group-dbna.
  CLEAR ls_ldbn.
  ls_ldbn-type = 'S'. "structure
  ls_ldbn-ldbname = ls_group-dbna.
  ls_ldbn-structure = ls_dta-viewtiobjnm2.
  LOOP AT lt_dime INTO ls_dime.
    ls_ldbn-ldbnode = ls_dime-dimension.
    ls_ldbn-currnumb = ls_ldbn-currnumb + 1.
    INSERT ldbn FROM ls_ldbn.
  ENDLOOP.
  ls_ldbn-ldbnode = 'KF'.
  ls_ldbn-currnumb = ls_ldbn-currnumb + 1.
  INSERT ldbn FROM ls_ldbn.

  COMMIT WORK AND WAIT.

* As the program reuse always the same selection view name,
* Buffer table of the selection view function need to be cleaned
  lw_fsname = '(SAPLSSEL)ldbs'.
  ASSIGN (lw_fsname) TO <lfs_table>.
  IF sy-subrc = 0.
    REFRESH <lfs_table>.
  ENDIF.

* Retrieve selected values => has a bug on BW 7.3
* Cannot define initial values, can only display selected fields
  IF NOT p_select IS INITIAL.
    PERFORM convert_string_trange USING p_select dsqfn[]
                                  CHANGING lt_field_ranges.
    LOOP AT lt_field_ranges INTO ls_range.
      LOOP AT ls_range-frange_t INTO ls_frange.
        ls_fields-tablename = ls_dta-viewtiobjnm2.
        ls_fields-fieldname = ls_frange-fieldname.
        APPEND ls_fields TO lt_fields.
      ENDLOOP.
    ENDLOOP.
    SORT lt_fields BY tablename fieldname.
    DELETE ADJACENT DUPLICATES FROM lt_fields
                               COMPARING tablename fieldname.
  ENDIF.

* Add tech name to field name
  IF p_tech NE space.
    LOOP AT lt_dta_pro INTO ls_dta_pro.
      ls_field_texts-tablename = ls_dta-viewtiobjnm2.
      ls_field_texts-fieldname = ls_dta_pro-iobjnm.
      CONCATENATE ls_dta_pro-iobjnm '-' ls_dta_pro-txtlg
                  INTO ls_field_texts-text.
      APPEND ls_field_texts TO lt_field_texts.
    ENDLOOP.
  ENDIF.

* Initialize dynamic selection popup
  CALL FUNCTION 'FREE_SELECTIONS_INIT'
    EXPORTING
      kind             = 'G'
      field_groups_key = ls_group
      field_ranges_int = lt_field_ranges
    IMPORTING
      selection_id     = lw_selid
    TABLES
      fields_tab       = lt_fields
      field_texts      = lt_field_texts
    EXCEPTIONS
      OTHERS           = 8.
  IF sy-subrc NE 0.
    RETURN.
  ENDIF.

* Define more usual buttons for the selection screen popup
  ls_gui-pfkey = 'DYNSEL'.
  ls_gui-program = sy-cprog.

* Display dynamic selection popup
  CALL FUNCTION 'FREE_SELECTIONS_DIALOG'
    EXPORTING
      selection_id = lw_selid
      title        = 'Free selection'(m09)
      as_window    = c_true
      pfkey        = ls_gui
    IMPORTING
      field_ranges = lt_field_ranges
    TABLES
      fields_tab   = lt_fields
    EXCEPTIONS
      OTHERS       = 5.
  IF sy-subrc NE 0.
    MESSAGE 'Filter selection cancelled by user'(m25)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    fp_subrc = 8.
    RETURN.
  ENDIF.

* Update p_select
  PERFORM convert_trange_string USING lt_field_ranges
                                CHANGING p_select.

ENDFORM.                    " DISPLAY_SELECTION

*&---------------------------------------------------------------------*
*&      Form  CONVERT_TRANGE_STRING
*&---------------------------------------------------------------------*
*       Explode table of range to string separated by '|' and ';'
*----------------------------------------------------------------------*
*      -->FP_TRANGES  Input table of ranges
*      <--FP_STRING   Output string
*----------------------------------------------------------------------*
FORM convert_trange_string  USING    fp_tranges TYPE rsds_trange
                            CHANGING fp_string TYPE string.
  DATA : ls_trange LIKE LINE OF fp_tranges,
         ls_frange LIKE LINE OF ls_trange-frange_t,
         ls_selopt LIKE LINE OF ls_frange-selopt_t.

  CLEAR fp_string.
  LOOP AT fp_tranges INTO ls_trange.
    LOOP AT ls_trange-frange_t INTO ls_frange.
      LOOP AT ls_frange-selopt_t INTO ls_selopt.

        CONCATENATE fp_string c_line_separator ls_frange-fieldname
                    INTO fp_string.
        CONCATENATE fp_string ls_selopt-sign ls_selopt-option
                    ls_selopt-low ls_selopt-high
                    INTO fp_string SEPARATED BY c_field_separator.
        CONDENSE fp_string.
      ENDLOOP.
    ENDLOOP.
  ENDLOOP.

  IF NOT fp_string IS INITIAL.
    fp_string = fp_string+1.
  ENDIF.
ENDFORM.                    " CONVERT_TRANGE_STRING

*&---------------------------------------------------------------------*
*&      Form  CONVERT_STRING_TRANGE
*&---------------------------------------------------------------------*
*       Implode string separated by '|' and ';' into table of range
*----------------------------------------------------------------------*
*      -->FP_STRING   Input string
*      <--FP_TRANGES  Output table of ranges
*----------------------------------------------------------------------*
FORM convert_string_trange  USING    fp_string TYPE string
                                     dsqfn TYPE ty_dsqfn
                            CHANGING fp_tranges TYPE rsds_trange.
  DATA : ls_trange LIKE LINE OF fp_tranges,
         ls_frange LIKE LINE OF ls_trange-frange_t,
         ls_selopt LIKE LINE OF ls_frange-selopt_t,
         lw_cond TYPE string,
         lt_cond TYPE TABLE OF string,
         ls_dsqfn TYPE rsdsqfn,
         lw_fieldname TYPE string,
         lw_index_table TYPE i,
         lw_index_field TYPE i.

  REFRESH fp_tranges.
  SPLIT fp_string AT c_line_separator INTO TABLE lt_cond.
  LOOP AT lt_cond INTO lw_cond.
    CLEAR : ls_trange, ls_frange, ls_selopt.
*    SPLIT lw_cond AT c_field_separator INTO ls_frange-fieldname
*                                            ls_selopt-sign
*                                            ls_selopt-option
*                                            ls_selopt-low
*                                            ls_selopt-high.
    SPLIT lw_cond AT c_field_separator INTO lw_fieldname
                                            ls_selopt-sign
                                            ls_selopt-option
                                            ls_selopt-low
                                            ls_selopt-high.
    READ TABLE dsqfn INTO ls_dsqfn
                     WITH KEY fname = lw_fieldname.
    CHECK sy-subrc = 0.
    READ TABLE fp_tranges INTO ls_trange
               WITH KEY tablename = ls_dsqfn-tab.
    IF sy-subrc = 0.
      lw_index_table = sy-tabix.
      READ TABLE ls_trange-frange_t INTO ls_frange
                 WITH KEY fieldname = lw_fieldname.
      IF sy-subrc = 0.
        lw_index_field = sy-tabix.
        APPEND ls_selopt TO ls_frange-selopt_t.
        MODIFY ls_trange-frange_t FROM ls_frange INDEX lw_index_field.
        MODIFY fp_tranges FROM ls_trange INDEX lw_index_table.
      ELSE.
        ls_frange-fieldname = lw_fieldname.
        APPEND ls_selopt TO ls_frange-selopt_t.
        APPEND ls_frange TO ls_trange-frange_t.
        MODIFY fp_tranges FROM ls_trange INDEX lw_index_table.
      ENDIF.
    ELSE.
      ls_frange-fieldname = lw_fieldname.
      APPEND ls_selopt TO ls_frange-selopt_t.
      APPEND ls_frange TO ls_trange-frange_t.
      ls_trange-tablename = ls_dsqfn-tab.
      APPEND ls_trange TO fp_tranges.
    ENDIF.
  ENDLOOP.
ENDFORM.                    " CONVERT_STRING_TRANGE

*&---------------------------------------------------------------------*
*&      Form  DISPLAY_FIELDS
*&---------------------------------------------------------------------*
*       Display popup with list of fields to restrict
*----------------------------------------------------------------------*
FORM display_fields CHANGING fp_subrc TYPE i.
  DATA : lt_fieldcat TYPE kkblo_t_fieldcat, "slis_t_fieldcat_alv,
         ls_fieldcat LIKE LINE OF lt_fieldcat,
         lo_dta TYPE REF TO if_rsd_dta,
         lt_dta_pro TYPE rsd_t_dta_pro,
         ls_dta_pro LIKE LINE OF lt_dta_pro,
         lw_exit(1) TYPE c,
         ls_layout TYPE kkblo_layout,
         ls_exit TYPE kkblo_exit_by_user,
         lw_endline TYPE i,
         lw_dim_length TYPE i,
         ls_dta TYPE rsd_s_dta.

  REFRESH t_fields.
  CLEAR fp_subrc.

* Get information about infoprovider
  lo_dta = cl_rsd_dta=>factory( p_cube ).
  CALL METHOD lo_dta->dta_get_info
    EXPORTING
      i_with_atr_nav = space
    IMPORTING
      e_t_dta_pro    = lt_dta_pro
      e_s_dta        = ls_dta.

* Delete Non-cumulative ratio (that are not in the cube)
  DELETE lt_dta_pro WHERE NOT ncumfl IS INITIAL.

  LOOP AT lt_dta_pro INTO ls_dta_pro.
    CLEAR s_fields.
    s_fields-iobjnm = ls_dta_pro-iobjnm.
    s_fields-txtlg = ls_dta_pro-txtlg.
* prefix key figure by Z to display them after all other info objects
    IF ls_dta_pro-iobjtp = rsd_c_objtp-keyfigure.
      s_fields-type = 'ZKF'.
    ELSE.
      s_fields-type = ls_dta_pro-iobjtp.
    ENDIF.
    IF so_field[] IS INITIAL OR NOT s_fields-iobjnm IN so_field.
      s_fields-selkz = c_true.
    ENDIF.
    IF ls_dta-tlogo = 'ODSO'.
      IF ls_dta_pro-dimension = c_dimension_key_dso.
        s_fields-key = '@3V@'.
      ENDIF.
    ELSEIF ls_dta_pro-dimension IS INITIAL.
      s_fields-key = c_numb_kf.
    ELSE.
      lw_dim_length = strlen( ls_dta_pro-dimension ) - 1.
      s_fields-key = ls_dta_pro-dimension+lw_dim_length(1).
    ENDIF.
    APPEND s_fields TO t_fields.
  ENDLOOP.
  IF ls_dta-tlogo = 'ODSO'.
    SORT t_fields BY key DESCENDING type iobjnm.
  ELSE.
    SORT t_fields BY key type iobjnm.
  ENDIF.

* Build fieldcat
  ls_fieldcat-fieldname = 'SELKZ'.
  ls_fieldcat-checkbox = c_true.
  ls_fieldcat-reptext_ddic = 'Selection'(m10).
  ls_fieldcat-datatype = 'CHAR'.
  ls_fieldcat-fix_column = c_true.
  ls_fieldcat-outputlen = 3.
  APPEND ls_fieldcat TO lt_fieldcat.

  CLEAR ls_fieldcat.
  ls_fieldcat-fieldname = 'KEY'.
  ls_fieldcat-datatype = 'CHAR'.
  ls_fieldcat-outputlen = 3.
  IF ls_dta-tlogo = 'ODSO'.
    ls_fieldcat-icon = c_true.
    ls_fieldcat-reptext_ddic = 'Key'(m20).
  ELSE.
    ls_fieldcat-reptext_ddic = 'Dim'(m26).
  ENDIF.
  APPEND ls_fieldcat TO lt_fieldcat.

  CLEAR ls_fieldcat.
  ls_fieldcat-fieldname = 'TYPE'.
  ls_fieldcat-reptext_ddic = 'Type'(m11).
  ls_fieldcat-datatype = 'CHAR'.
  ls_fieldcat-outputlen = 3.
  APPEND ls_fieldcat TO lt_fieldcat.
  ls_fieldcat-fieldname = 'IOBJNM'.
  ls_fieldcat-reptext_ddic = 'Info objet'(m12).
  ls_fieldcat-datatype = 'CHAR'.
  ls_fieldcat-outputlen = 20.
  APPEND ls_fieldcat TO lt_fieldcat.
  ls_fieldcat-fieldname = 'TXTLG'.
  ls_fieldcat-reptext_ddic = 'Description'(m13).
  ls_fieldcat-lowercase = c_true.
  ls_fieldcat-datatype = 'CHAR'.
  ls_fieldcat-outputlen = 60.
  APPEND ls_fieldcat TO lt_fieldcat.

  ls_layout-box_fieldname = 'SELKZ'.

* Calculate end line of display popup
  DESCRIBE TABLE t_fields LINES lw_endline.
  lw_endline = lw_endline + 2.
  IF lw_endline > c_max_popup_endline.
    lw_endline = c_max_popup_endline.
  ENDIF.

* Use deep function used by REUSE_ALV_POPUP_TO_SELECT
* to add some buttons in toolbar
  CLEAR : lw_exit, ls_exit.
  CALL FUNCTION 'K_KKB_LIST_DISPLAY'
    EXPORTING
      i_callback_program       = 'ZLISTCUBE'
      i_callback_user_command  = 'DISPLAY_FIELDS_USER_COMMAND'
      i_callback_pf_status_set = 'DISPLAY_FIELDS_PF_STATUS'
      i_tabname                = 'T_FIELDS'
      is_layout                = ls_layout
      it_fieldcat              = lt_fieldcat
      i_screen_start_column    = 10
      i_screen_start_line      = 1
      i_screen_end_column      = 103
      i_screen_end_line        = lw_endline
    IMPORTING
      e_exit_caused_by_caller  = lw_exit
      es_exit_caused_by_user   = ls_exit
    TABLES
      t_outtab                 = t_fields.
  IF lw_exit IS INITIAL AND ls_exit IS INITIAL.
    REFRESH so_field.
    LOOP AT t_fields INTO s_fields WHERE selkz = space.
      so_field = 'IEQ'.
      so_field-low = s_fields-iobjnm.
      APPEND so_field.
    ENDLOOP.
  ELSE.
    MESSAGE 'Field selection cancelled by user'(m27)
            TYPE c_msg_success DISPLAY LIKE c_msg_error.
    fp_subrc = 8.
  ENDIF.
ENDFORM.                    " DISPLAY_FIELDS

*&---------------------------------------------------------------------*
*&      Form  DISPLAY_FIELDS_USER_COMMAND
*&---------------------------------------------------------------------*
*       User command for the selection fields popup
*       Called dynamically by K_KKB_LIST_DISPLAY
*----------------------------------------------------------------------*
*      -->FP_UCOMM     Function code
*      -->FP_SELFIELD  Selection structure informations
*----------------------------------------------------------------------*
FORM display_fields_user_command
     USING fp_ucomm TYPE sy-ucomm                           "#EC CALLED
           fp_selfield TYPE kkblo_selfield.

  CASE fp_ucomm.
    WHEN '&IC1'.
* Select/unselect line
      IF NOT fp_selfield-tabindex IS INITIAL.
        READ TABLE t_fields INTO s_fields INDEX fp_selfield-tabindex.
        IF sy-subrc = 0.
          IF s_fields-selkz = space.
            s_fields-selkz = c_true.
          ELSE.
            s_fields-selkz = space.
          ENDIF.
          MODIFY t_fields FROM s_fields INDEX fp_selfield-tabindex
                 TRANSPORTING selkz.
        ENDIF.
      ENDIF.
      fp_selfield-refresh = c_true.
      fp_selfield-col_stable = c_true.
      fp_selfield-row_stable = c_true.

    WHEN '&NT1'.
* Check at least 1 field is selected and close popup
      READ TABLE t_fields WITH KEY selkz = c_true TRANSPORTING NO FIELDS.
      IF sy-subrc NE 0.
        MESSAGE e006(0k).
        RETURN.
      ENDIF.
      LEAVE TO SCREEN 0.
    WHEN OTHERS.
      IF fp_ucomm(7) = 'SWITCH_'.
* Switch selection for all CHA/ZKF iobj
        LOOP AT t_fields INTO s_fields WHERE type = fp_ucomm+7(3).
          IF s_fields-selkz = space.
            s_fields-selkz = c_true.
          ELSE.
            s_fields-selkz = space.
          ENDIF.
          MODIFY t_fields FROM s_fields TRANSPORTING selkz.
        ENDLOOP.
        fp_selfield-refresh = c_true.
        fp_selfield-col_stable = c_true.
        fp_selfield-row_stable = c_true.
      ENDIF.
  ENDCASE.
ENDFORM.                    "DISPLAY_FIELDS_USER_COMMAND

*&---------------------------------------------------------------------*
*&      Form  DISPLAY_FIELDS_PF_STATUS
*&---------------------------------------------------------------------*
*       Set pf-status for the selection fields popup
*       Called dynamically by K_KKB_LIST_DISPLAY
*----------------------------------------------------------------------*
*      -->FT_EXTAB   Excluded functions table
*----------------------------------------------------------------------*
FORM display_fields_pf_status
     USING ft_extab TYPE kkblo_t_extab.                     "#EC CALLED
* Filter is bugged : all checkbox is reseted when you filter
* It's not really a bug as SAP hardcoded this "functionnality"
* but it's not the way i want to use. I have no other choice than
* disable the filter function
  APPEND '&ILT' TO ft_extab.

* Exclude selection block button if not iobj from this block
  READ TABLE t_fields WITH KEY type = 'CHA' TRANSPORTING NO FIELDS.
  IF sy-subrc NE 0.
    APPEND 'SWITCH_CHA' TO ft_extab.
  ENDIF.

  READ TABLE t_fields WITH KEY type = 'DPA' TRANSPORTING NO FIELDS.
  IF sy-subrc NE 0.
    APPEND 'SWITCH_DPA' TO ft_extab.
  ENDIF.

  READ TABLE t_fields WITH KEY type = 'TIM' TRANSPORTING NO FIELDS.
  IF sy-subrc NE 0.
    APPEND 'SWITCH_TIM' TO ft_extab.
  ENDIF.

  READ TABLE t_fields WITH KEY type = 'UNI' TRANSPORTING NO FIELDS.
  IF sy-subrc NE 0.
    APPEND 'SWITCH_UNI' TO ft_extab.
  ENDIF.

  READ TABLE t_fields WITH KEY type = 'ZKF' TRANSPORTING NO FIELDS.
  IF sy-subrc NE 0.
    APPEND 'SWITCH_ZKF' TO ft_extab.
  ENDIF.

  SET PF-STATUS 'DISPLAY_FIELDS' EXCLUDING ft_extab.
  SET TITLEBAR 'DISPLAY_FIELDS'. "Choose fields to display
ENDFORM.                    "DISPLAY_FIELDS_PF_STATUS

*&---------------------------------------------------------------------*
*&      Form  prompt_for_file
*&---------------------------------------------------------------------*
*       Searchhelp for input file
*----------------------------------------------------------------------*
*      -->FP_TITLE      Title of the search-help
*      -->FP_LOCAL_FILE Space = server file / X = local file
*      -->FP_FILENAME   Returning path+filename
*----------------------------------------------------------------------*
FORM prompt_for_file  USING fp_title TYPE string
                            fp_local_file TYPE c
                      CHANGING fp_filename TYPE string.
  DATA : lt_file_f4 TYPE filetable,
         ls_file_f4 LIKE LINE OF lt_file_f4,
         l_rc TYPE i,
         l_filter TYPE string.

  l_filter = 'CSV File (*.csv)|*.csv'(m15).

* Server File
  IF fp_local_file = space.
    CALL FUNCTION '/SAPDMC/LSM_F4_SERVER_FILE'
      EXPORTING
        filemask   = l_filter
      IMPORTING
        serverfile = fp_filename.

* Local file
  ELSE.
    CALL METHOD cl_gui_frontend_services=>file_open_dialog
      EXPORTING
        window_title = fp_title
        file_filter  = l_filter
      CHANGING
        file_table   = lt_file_f4
        rc           = l_rc
      EXCEPTIONS
        OTHERS       = 0.
    READ TABLE lt_file_f4 INTO ls_file_f4 INDEX 1.
    IF sy-subrc = 0.
      fp_filename = ls_file_f4.
    ENDIF.
  ENDIF.
ENDFORM.                    " PROMPT_FOR_FILE

*&---------------------------------------------------------------------*
*&      Form  WRITE_FILE
*&---------------------------------------------------------------------*
*       Write file local or server
*----------------------------------------------------------------------*
*      -->FO_DATA       Pointer to data table to write
*      -->FP_LOCAL_FILE Space = server file / X = local file
*      -->FP_FILE       Filename to write
*      -->FP_OVERWRITE  'X' to replace existing file, space to append
*      -->FP_HEADER     'X' to write header
*----------------------------------------------------------------------*
FORM write_file  USING fo_data TYPE REF TO data
                       fp_local_file TYPE c
                       fp_file TYPE string
                       fp_overwrite TYPE c
                       fp_header TYPE c
                       ft_dta_pro TYPE rsd_t_dta_pro.
  DATA : lw_line TYPE string,
         lw_field TYPE string,
         lw_append TYPE char01,
         lo_descr_table TYPE REF TO cl_abap_tabledescr,
         lo_descr_struc TYPE REF TO cl_abap_structdescr,
         ls_compx TYPE abap_compdescr,
         lt_string TYPE TABLE OF string,
         lt_index_export TYPE TABLE OF i,
         lw_index_export TYPE i.

  FIELD-SYMBOLS : <lft_data> TYPE STANDARD TABLE,
                  <lfs_data> TYPE any,
                  <lf_data> TYPE any.

  ASSIGN fo_data->* TO <lft_data>.

* Build list of index of column to export
  lo_descr_table ?= cl_abap_typedescr=>describe_by_data_ref( fo_data ).
  lo_descr_struc ?= lo_descr_table->get_table_line_type( ).
* If no restriction, keep all columns
  IF so_field[] IS INITIAL.
    LOOP AT lo_descr_struc->components INTO ls_compx.
      APPEND sy-tabix TO lt_index_export.
    ENDLOOP.
  ELSE.
* If field restriction, export only fields required
    LOOP AT lo_descr_struc->components INTO ls_compx.
      lw_index_export = sy-tabix.
      CHECK NOT ls_compx-name IN so_field.
* exclude also nav attr
      READ TABLE ft_dta_pro
                     WITH KEY iobjnm = ls_compx-name
                     TRANSPORTING NO FIELDS.
      CHECK sy-subrc = 0.
      APPEND lw_index_export TO lt_index_export.
    ENDLOOP.
  ENDIF.

*  Server file
  IF fp_local_file = space.
    IF fp_overwrite = space.
      OPEN DATASET fp_file FOR APPENDING IN TEXT MODE ENCODING DEFAULT.
    ELSE.
      OPEN DATASET fp_file FOR OUTPUT IN TEXT MODE ENCODING DEFAULT.
    ENDIF.
    IF sy-subrc NE 0.
      MESSAGE 'Cannot create the remote file'(m16) TYPE c_msg_error.
      RETURN.
    ENDIF.

* Write header at the begin of the file
    IF fp_overwrite NE space AND fp_header NE space.
      CLEAR lw_line.
      LOOP AT lt_index_export INTO lw_index_export.
        READ TABLE lo_descr_struc->components INTO ls_compx
                   INDEX lw_index_export.
        CHECK sy-subrc = 0.
* Change header name for nav attr
        READ TABLE ft_dta_pro
                       WITH KEY iobjnm = ls_compx-name
                       TRANSPORTING NO FIELDS.
        IF sy-subrc NE 0.
          ls_compx-name = c_header_na.
        ENDIF.
        IF lw_line IS INITIAL.
          lw_line = ls_compx-name.
        ELSE.
          CONCATENATE lw_line ls_compx-name INTO lw_line
                      SEPARATED BY c_separator.
        ENDIF.
      ENDLOOP.
      TRANSFER lw_line TO fp_file.
    ENDIF.

* Write the file content
    LOOP AT <lft_data> ASSIGNING <lfs_data>.
      CLEAR lw_line.
      LOOP AT lt_index_export INTO lw_index_export.
        ASSIGN COMPONENT lw_index_export OF STRUCTURE <lfs_data> TO <lf_data>.
        CHECK sy-subrc = 0.
        IF lw_line IS INITIAL.
          lw_line = <lf_data>.
        ELSE.
          lw_field = <lf_data>.
          CONCATENATE lw_line lw_field INTO lw_line
                      SEPARATED BY c_separator.
        ENDIF.
      ENDLOOP.
      TRANSFER lw_line TO fp_file.
    ENDLOOP.
    CLOSE DATASET fp_file.

*  Local file
  ELSE.
    REFRESH lt_string.
    IF fp_overwrite = space.
      lw_append = c_true.
    ELSE.
      lw_append = space.
    ENDIF.

* Write header line at the top of the file if required
    IF fp_header NE space.
      CLEAR lw_line.
      LOOP AT lt_index_export INTO lw_index_export.
        READ TABLE lo_descr_struc->components INTO ls_compx
                   INDEX lw_index_export.
        CHECK sy-subrc = 0.
* Change header name for nav attr
        READ TABLE ft_dta_pro
                       WITH KEY iobjnm = ls_compx-name
                       TRANSPORTING NO FIELDS.
        IF sy-subrc NE 0.
          ls_compx-name = c_header_na.
        ENDIF.
        IF lw_line IS INITIAL.
          lw_line = ls_compx-name.
        ELSE.
          CONCATENATE lw_line ls_compx-name INTO lw_line
                      SEPARATED BY c_separator.
        ENDIF.
      ENDLOOP.
      APPEND lw_line TO lt_string.
    ENDIF.

* Write the file content
    LOOP AT <lft_data> ASSIGNING <lfs_data>.
      CLEAR lw_line.
      LOOP AT lt_index_export INTO lw_index_export.
        ASSIGN COMPONENT lw_index_export OF STRUCTURE <lfs_data> TO <lf_data>.
        CHECK sy-subrc = 0.
        IF lw_line IS INITIAL.
          lw_line = <lf_data>.
        ELSE.
          lw_field = <lf_data>.
          CONCATENATE lw_line lw_field INTO lw_line
                      SEPARATED BY c_separator.
        ENDIF.
      ENDLOOP.
      APPEND lw_line TO lt_string.
    ENDLOOP.

    CALL METHOD cl_gui_frontend_services=>gui_download
      EXPORTING
        filename = fp_file
        append   = lw_append
      CHANGING
        data_tab = lt_string
      EXCEPTIONS
        OTHERS   = 0.
  ENDIF.
ENDFORM.                    " WRITE_FILE

*&---------------------------------------------------------------------*
*&      Form  DISPLAY_ALV
*&---------------------------------------------------------------------*
*       Display table content in ALV format
*----------------------------------------------------------------------*
*      -->FO_DATA      Pointer to data table
*      -->FT_DTA_PRO   Table of field description
*      -->FP_STRUCTURE Structure of data table
*----------------------------------------------------------------------*
FORM display_alv  USING fo_data TYPE REF TO data
                        ft_dta_pro TYPE rsd_t_dta_pro
                        fp_structure TYPE rsviewtiobjnm2.
  DATA : lt_fieldcat TYPE slis_t_fieldcat_alv,
         ls_fieldcat LIKE LINE OF lt_fieldcat,
         lw_tabix TYPE i.
  FIELD-SYMBOLS <lft_data> TYPE STANDARD TABLE.
  ASSIGN fo_data->* TO <lft_data>.
  IF sy-subrc NE 0.
    RETURN.
  ENDIF.

  CALL FUNCTION 'REUSE_ALV_FIELDCATALOG_MERGE'
    EXPORTING
      i_structure_name = fp_structure
    CHANGING
      ct_fieldcat      = lt_fieldcat
    EXCEPTIONS
      OTHERS           = 3.
  IF sy-subrc <> 0.
    MESSAGE 'Cannot build fieldcat to display result'(m17)
            TYPE c_msg_error.
  ENDIF.

* Delete fields excluded
  IF NOT so_field[] IS INITIAL.
    DELETE lt_fieldcat WHERE fieldname IN so_field.
  ENDIF.

  LOOP AT lt_fieldcat INTO ls_fieldcat.
    lw_tabix = sy-tabix.
* Exclude nav attr
    READ TABLE ft_dta_pro
               WITH KEY iobjnm = ls_fieldcat-fieldname
               TRANSPORTING NO FIELDS.
    IF sy-subrc NE 0.
      DELETE lt_fieldcat.
      CONTINUE.
    ENDIF.

* All dimension field are defined as key
* this customizing avoid to display key figure => remove it
    IF ls_fieldcat-key = c_true.
      ls_fieldcat-key = space.
    ENDIF.

* By default, display 100 first fields
    IF lw_tabix LT 100.
      ls_fieldcat-no_out = space.
    ELSE.
      ls_fieldcat-no_out = c_true.
    ENDIF.

* Display techname + label in tooltip over header column
    CONCATENATE ls_fieldcat-fieldname '-' ls_fieldcat-seltext_l
                INTO ls_fieldcat-reptext_ddic SEPARATED BY space.

* Change header text if technical display required
    IF p_tech NE space.
      ls_fieldcat-seltext_s = ls_fieldcat-seltext_m
      = ls_fieldcat-seltext_l = ls_fieldcat-fieldname.
    ENDIF.

    MODIFY lt_fieldcat FROM ls_fieldcat
           TRANSPORTING key no_out reptext_ddic
                        seltext_l seltext_m seltext_s.
  ENDLOOP.

* Default ALV variant get
  s_variant-report  = sy-repid.
  s_variant-variant = p_vari.
  CONCATENATE 'Display results for provider:'(m30) p_cube
              INTO sy-title SEPARATED BY space.
  CALL FUNCTION 'REUSE_ALV_VARIANT_DEFAULT_GET'
    EXPORTING
      i_save     = c_variant_save
    CHANGING
      cs_variant = s_variant
    EXCEPTIONS
      OTHERS     = 0. "dont care if cannot get default alv variant

* Display data in ALV
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
    EXPORTING
      it_fieldcat = lt_fieldcat
      i_default   = c_true
      i_save      = c_variant_save
      is_variant  = s_variant
    TABLES
      t_outtab    = <lft_data>.
ENDFORM.                    " DISPLAY_ALV

*&---------------------------------------------------------------------*
*&      Form  GET_WHERE_CLAUSE_FROM_KEY_SEL
*&---------------------------------------------------------------------*
*       Build dynamic where clause for key figure restriction
*----------------------------------------------------------------------*
*      -->PT_KEY_SEL Keyfigure restriction
*      -->PF_TABLE   Name of the ddic table to refer
*      <--PT_WHERE   Table of where clause restriction
*----------------------------------------------------------------------*
FORM get_where_clause_from_key_sel
     USING    pt_key_sel TYPE rsdrc_t_selk
              pf_table TYPE rsd_s_dta-viewtiobjnm2
     CHANGING pt_where TYPE rsds_where_tab.
* type used in standard program saplssel
  TYPES: BEGIN OF lty_field_sel_type,
           tablename   TYPE rsdstabs-prim_tab,
           fieldname   TYPE rsdstabs-prim_fname,
           ldbnode     TYPE ldbn-ldbnode,
           qu_prefix(1) TYPE c,
           qu_num      TYPE rsdsqfn-numb,
           fieldnumber TYPE sy-tabix,
           text        TYPE rsdstexts-text,
           convert TYPE rsconvert,
           f4availabl TYPE dfies-f4availabl,
           checktable TYPE dfies-checktable,
           valexi   TYPE dfies-valexi,
           at_on      TYPE rsdsevflds-at_on,
           at_on_end  TYPE rsdsevflds-at_on_end,
           f1         TYPE rsdsevflds-f1,
           f4         TYPE rsdsevflds-f4,
           protected(1) TYPE c,
           vtype(1) TYPE c,
           fieldsel    TYPE rsdsselopt OCCURS 5,
           reffield    TYPE rsscr-dbfield,
         END OF lty_field_sel_type.

  DATA : lt_dfies TYPE TABLE OF dfies,
         ls_dfies LIKE LINE OF lt_dfies.
  DATA : lt_where TYPE rsds_where_tab,
         ls_field_sel TYPE lty_field_sel_type,
         lw_subrc TYPE sy-subrc,
         ls_fieldsel LIKE LINE OF ls_field_sel-fieldsel,
         ls_key_sel LIKE LINE OF pt_key_sel,
         lw_kyfnm_prev LIKE ls_key_sel-kyfnm,
         lw_index TYPE i.

  SORT pt_key_sel BY kyfnm.
  CLEAR lw_kyfnm_prev.
  LOOP AT pt_key_sel INTO ls_key_sel.
    lw_index = sy-tabix.
* at new kyfnm
    IF lw_kyfnm_prev NE ls_key_sel-kyfnm.
      lw_kyfnm_prev = ls_key_sel-kyfnm.

      CALL FUNCTION 'DDIF_FIELDINFO_GET'
        EXPORTING
          tabname   = pf_table
          fieldname = ls_key_sel-kyfnm
        TABLES
          dfies_tab = lt_dfies
        EXCEPTIONS
          OTHERS    = 3.
      CHECK sy-subrc = 0.
      READ TABLE lt_dfies INTO ls_dfies INDEX 1.
      CLEAR ls_field_sel.
      ls_field_sel-fieldname = ls_key_sel-kyfnm.
      CHECK NOT ls_dfies IS INITIAL.

* Fill ls_field_sel-CONVERT-WHERE_LENG
      PERFORM set_ilength IN PROGRAM saplssel
                          USING    ls_dfies-inttype
                                   ls_dfies-leng
                                   ls_dfies-leng
                                   0 "not used
                                   ls_dfies-decimals
                                   ls_dfies-sign
                          CHANGING ls_field_sel-convert-where_leng.
    ENDIF.
    CHECK NOT ls_dfies IS INITIAL.

    CLEAR ls_fieldsel.
    IF ls_key_sel-boolop = rsdrs_c_boolop-not
    OR ls_key_sel-boolop = rsdrs_c_boolop-and_not.
      ls_fieldsel-sign = rs_c_range_sign-excluding.
    ELSE.
      ls_fieldsel-sign = rs_c_range_sign-including.
    ENDIF.

    ls_fieldsel-option = ls_key_sel-compop.
    ls_fieldsel-low = ls_key_sel-low.
    ls_fieldsel-high = ls_key_sel-high.
    APPEND ls_fieldsel TO ls_field_sel-fieldsel.

* Fill where table
*      AT END OF kyfnm.
    lw_index = lw_index + 1.
    READ TABLE pt_key_sel INTO ls_key_sel INDEX lw_index.
    IF sy-subrc NE 0 OR lw_kyfnm_prev NE ls_key_sel-kyfnm.
      PERFORM where_for_one_field IN PROGRAM saplssel
                                  USING    ls_field_sel
                                  CHANGING lt_where
                                           lw_subrc.
      IF NOT pt_where IS INITIAL.
        APPEND 'AND' TO pt_where.
      ENDIF.
      APPEND LINES OF lt_where TO pt_where.
    ENDIF.
  ENDLOOP.
  IF NOT pt_where IS INITIAL.
    INSERT 'NOT (' INTO pt_where INDEX 1.
    APPEND ')' TO pt_where.
  ENDIF.
ENDFORM.                    " GET_WHERE_CLAUSE_FROM_KEY_SEL

*&---------------------------------------------------------------------*
*&      Form  GET_DEFAULT_VALUES
*&---------------------------------------------------------------------*
*       Get default values in shared memory
*----------------------------------------------------------------------*
FORM get_default_values .
  CONCATENATE 'ZLISTCUBE_' sy-uname INTO w_shared_param.
  IMPORT t_default FROM SHARED BUFFER indx(st) ID w_shared_param.
  IF NOT p_cube IS INITIAL AND NOT t_default IS INITIAL.
    READ TABLE t_default INTO s_default
               WITH KEY cube = p_cube.
    IF sy-subrc = 0.
      p_select = s_default-sel.
      so_field[] = s_default-t_fields[].
    ENDIF.
  ENDIF.
ENDFORM.                    " GET_DEFAULT_VALUES
*&---------------------------------------------------------------------*
*&      Form  SET_DEFAULT_VALUES
*&---------------------------------------------------------------------*
*       Set default values in shared memory
*----------------------------------------------------------------------*
FORM set_default_values .
  CONCATENATE 'ZLISTCUBE_' sy-uname INTO w_shared_param.
  s_default-cube = p_cube.
  s_default-sel = p_select.
  s_default-t_fields[] = so_field[].
  DELETE t_default WHERE cube = p_cube.
  APPEND s_default TO t_default.
  EXPORT t_default TO SHARED BUFFER indx(st) ID w_shared_param.
ENDFORM.                    " SET_DEFAULT_VALUES