2013 May 22 9:51 AM
Hello everyone,
At the moment I'm trying to get some new possibilities for useful helps when user works with ALV-Grid (OO). On of them is the work with dateslices. I know it from the modern coded RE-FX reports in SAP, e.g. REISBE. You can see at the screenshot below how it looks like.
Now I want to insert these dateslice functions in my own-written ALV Grid as well. Now the question: Is this possible and if so, how does it work? When debugging the program in RE-FX it looks like this...
*=======================================================================
FORM dateslice_create.
*=======================================================================
DATA:
lt_daterange TYPE re_t_recadaterange,
ls_daterange TYPE recadaterange,
lf_dateslices_invalid TYPE recabool.
CHECK go_view->mf_use_dateslices = abap_true.
IF go_dateslice IS NOT BOUND.
* 1st pbo call
CREATE OBJECT go_dateslice
EXPORTING
if_no_complete_range = go_view->mf_no_complete_range.
* set handler
SET HANDLER:
lcl_event_handler=>handle_slice_changed FOR go_dateslice.
ELSE.
* further pbo call - only continue if new objects added
CHECK go_data->mf_dateslices_invalid = abap_true.
lf_dateslices_invalid = abap_true.
ENDIF.
ls_daterange-datefrom = go_view->ms_daterange-datefrom.
ls_daterange-dateto = go_view->ms_daterange-dateto.
CALL METHOD go_data->get_dateslices
IMPORTING
et_daterange = lt_daterange.
* remove duplicated time slices, delete initial time
SORT lt_daterange.
DELETE ADJACENT DUPLICATES FROM lt_daterange.
DELETE lt_daterange WHERE dateto IS INITIAL.
* compress date ranges
CALL METHOD cl_reca_date=>create_date_ranges
EXPORTING
it_dates_overlap = lt_daterange
IMPORTING
et_dates_cut = lt_daterange.
* insert selected daterange
READ TABLE lt_daterange
WITH KEY datefrom = ls_daterange-datefrom
dateto = ls_daterange-dateto
TRANSPORTING NO FIELDS.
IF sy-subrc EQ 4.
IF ( ls_daterange-datefrom IS NOT INITIAL ) OR
( ls_daterange-datefrom IS NOT INITIAL ).
APPEND ls_daterange TO lt_daterange.
ENDIF.
ENDIF.
* send slices to dateslice object
CALL METHOD go_dateslice->set_slices
EXPORTING
it_daterange = lt_daterange.
* set current time slice
IF ( ls_daterange-datefrom IS NOT INITIAL ) AND
( ls_daterange-dateto IS NOT INITIAL ).
CALL METHOD go_dateslice->set_current_slice
EXPORTING
is_current_slice = ls_daterange.
ELSEIF go_view->mf_use_current_daterange = abap_true.
go_dateslice->set_at_date( sy-datum ).
ELSE.
go_dateslice->set_current_slice_complete( ).
ENDIF.
* if dateslices are invalid set dateslice for go_data
* since refresh cannot be done by 'slice changed event'
IF lf_dateslices_invalid = abap_true.
CALL METHOD go_dateslice->get_current_slice
IMPORTING
es_current_slice = ls_daterange.
CALL METHOD go_data->set_dateslice
EXPORTING
id_validfrom = ls_daterange-datefrom
id_validto = ls_daterange-dateto.
gf_list_refresh = abap_true.
ENDIF.
ENDFORM. "do_okcode
...but for me it looks like that it is not that easy to implement it in an own report. Does anyone have experience with dateslisces in ALV Grid?
Kind Regards
Michael
2013 May 22 11:46 AM
This code has been put together just to see whether date slices can be created.
You can use it as a starting point and explore other methods of class.
Idea is to use class cl_reca_date_slices to create internal tables gt_daterange and gt_daterange_string. User will see gt_daterange_string (user-friendly intervals), and once selection is done, you can use index to get logic-friendly date range from gt_daterange.
TYPE-POOLS vrm.
DATA gt_daterange TYPE re_t_recadaterange.
DATA gs_daterange TYPE recadaterange.
DATA gt_daterange_string TYPE re_t_string.
DATA gs_daterange_string TYPE recastring.
DATA go_slices TYPE REF TO cl_reca_date_slices.
PARAMETERS p_dates TYPE char20 AS LISTBOX VISIBLE LENGTH 20.
AT SELECTION-SCREEN OUTPUT.
DATA lt_values TYPE vrm_values.
DATA ls_value TYPE vrm_value.
CREATE OBJECT go_slices.
PERFORM add_range USING sy-datum '99991231'.
PERFORM add_range USING sy-datum sy-datum.
PERFORM add_range USING '19900101' sy-datum.
PERFORM add_range USING '20130501' '20130531'.
CALL METHOD go_slices->set_slices
EXPORTING
it_daterange = gt_daterange.
CALL METHOD go_slices->get_slices
EXPORTING
if_delete_unlimited_string = abap_true
IMPORTING
et_daterange = gt_daterange
et_daterange_string = gt_daterange_string.
LOOP AT gt_daterange_string INTO gs_daterange_string.
ls_value-key = sy-tabix.
ls_value-text = gs_daterange_string.
APPEND ls_value TO lt_values.
CLEAR ls_value.
ENDLOOP.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
id = 'P_DATES'
values = lt_values.
*&---------------------------------------------------------------------*
*& Form add_range
*&---------------------------------------------------------------------*
FORM add_range USING pv_datefrom TYPE sy-datum
pv_dateto TYPE sy-datum.
gs_daterange-datefrom = pv_datefrom.
gs_daterange-dateto = pv_dateto.
APPEND gs_daterange TO gt_daterange.
CLEAR gs_daterange.
ENDFORM. "add_range
2013 May 22 11:46 AM
This code has been put together just to see whether date slices can be created.
You can use it as a starting point and explore other methods of class.
Idea is to use class cl_reca_date_slices to create internal tables gt_daterange and gt_daterange_string. User will see gt_daterange_string (user-friendly intervals), and once selection is done, you can use index to get logic-friendly date range from gt_daterange.
TYPE-POOLS vrm.
DATA gt_daterange TYPE re_t_recadaterange.
DATA gs_daterange TYPE recadaterange.
DATA gt_daterange_string TYPE re_t_string.
DATA gs_daterange_string TYPE recastring.
DATA go_slices TYPE REF TO cl_reca_date_slices.
PARAMETERS p_dates TYPE char20 AS LISTBOX VISIBLE LENGTH 20.
AT SELECTION-SCREEN OUTPUT.
DATA lt_values TYPE vrm_values.
DATA ls_value TYPE vrm_value.
CREATE OBJECT go_slices.
PERFORM add_range USING sy-datum '99991231'.
PERFORM add_range USING sy-datum sy-datum.
PERFORM add_range USING '19900101' sy-datum.
PERFORM add_range USING '20130501' '20130531'.
CALL METHOD go_slices->set_slices
EXPORTING
it_daterange = gt_daterange.
CALL METHOD go_slices->get_slices
EXPORTING
if_delete_unlimited_string = abap_true
IMPORTING
et_daterange = gt_daterange
et_daterange_string = gt_daterange_string.
LOOP AT gt_daterange_string INTO gs_daterange_string.
ls_value-key = sy-tabix.
ls_value-text = gs_daterange_string.
APPEND ls_value TO lt_values.
CLEAR ls_value.
ENDLOOP.
CALL FUNCTION 'VRM_SET_VALUES'
EXPORTING
id = 'P_DATES'
values = lt_values.
*&---------------------------------------------------------------------*
*& Form add_range
*&---------------------------------------------------------------------*
FORM add_range USING pv_datefrom TYPE sy-datum
pv_dateto TYPE sy-datum.
gs_daterange-datefrom = pv_datefrom.
gs_daterange-dateto = pv_dateto.
APPEND gs_daterange TO gt_daterange.
CLEAR gs_daterange.
ENDFORM. "add_range
2013 May 22 12:09 PM
Dear Manish,
thanks a lot I can try using this snippet and also looking for cl_reca_date_slices.
But how do I get the slices to the Grid then, so that I can just switch between actual slices and all slices and so on?
Regards
Michael
2013 May 22 12:46 PM
Case 1: Use method CL_GUI_ALV_GRID->SET_DROP_DOWN_TABLE if you want dateslice dropdown to appear in a column of ALV grid output.
Case 2: In case you want the content of ALV grid to be filtered according the chosen dateslice, change alv table content in PAI based on chose dateslice, and do ALV refresh using CL_GUI_ALV_GRID->REFRESH_TABLE_DISPLAY. Method APPLY_FILTER can also be looked at.
2013 May 22 12:53 PM
Hm okay for me it would be case 2. But I'm not quite sure how it works.
How do I get the dateslices showed in the ALV grid like in the screenshot?
Normally I just have the Grid content that is shown in the ALV container. But how to put the element for choosing timeslices in the grid?
2013 May 22 3:49 PM
Please search for working example of "dropdown list in alv".
Method SET_DROP_DOWN_TABLE would be used to set gt_daterange_string as list of values to be shown as dropdown. The field of internal table needs to be of compatible type.
2013 May 23 9:18 AM
Ok, now I had a look how it worked in SAP standard with the dropwdown box as own dynpro element above the grid. Now that's clear.
And a simple example of building my timeslices worked as well. But now I do not know how to link them with my internal table from the grid?
I got an easy example for timeslices which means
(1) All dates
(2) until sy-datum - 1
(3) from sy-datum on
my timeslice table looks fine.
But now I got my 'valid from' and 'valid to' fields in my internal table from the grid. How do I link them with these three time slices? e.g. saying when user takes time slice (2), only show the relevant table entries and so on. Do I have to work with filter methods of alv grid then?
2013 May 23 10:23 AM
Once user selects a slice, set that as current slice in object.
Loop through internal table, and check whether date range is in current slice.
Based on result, you can keep or delete record.
If going for ALV filter, you need to add hidden column to internal table which would store calculated slice. The filter would then be applied to this hidden column.
Code to check date range against selected slice would be something like this:
* assume user selected 2nd slice
CALL METHOD go_slices->set_current_slice
EXPORTING
id_tabix = 2.
* for every record in internal table, check date range
CALL METHOD go_slices->is_entry_in_current_slice
EXPORTING
id_datefrom = ls_record-datefrom
id_dateto = ls_record-dateto
RECEIVING
rf_valid = lv_result.
IF lv_result EQ abap_true.
"record is in current slice
ELSE.
"record is not in current slice
ENDIF.
2013 May 23 12:14 PM
Hm is there any other way for keeping or deleting a record?
I'm just thinking about how to get it back when deleting them from my internal table. Of course I can work with local table as copy of the global and refresh only the local after changing it. This would help in this case of the report on what I'm working at the moment.
But for implementing it in other grids, e.g. grids with editing function I think I would get some problems with indexes when updating the internal table in database in using a filtered time slice.
2013 May 24 9:04 AM
Ok now my dateslice grid works pretty good. Now its up to some extra goodies 🙂
Is it possible in any easy way to build my dateslices in the dropdown menu some kind of individual like it works in SAP standard?
For example, I got my grid with the table fields 'valid from' and 'valid to'. I want to build by dateslices in reference to all possible combinations of these both fields. This means:
grid row 1 - 00.00.0000 until 30.06.2013
grid row 2 - 01.07.2013 until 31.12.2013
grid row 3 - 01.01.2014 until 31.12.9999
Now I want the dateslices
(1) ALL
(2) until 30.06.2013
(3) 01.07.2014 until 31.12.2013
(4) from 01.01.2014
Is there any easy way with some special method? Or do I have to loop my whole grid table? If so whats the best way to create the slices then?
Regards
Michael
2013 May 25 9:21 AM
Yes, you have to loop through whole grid table to fill gt_daterange. Once this is filled, there can be some useful methods to manipulate the daterange table.
The code you found while debugging has some clues.
* compress date ranges
CALL METHOD cl_reca_date=>create_date_ranges
EXPORTING
it_dates_overlap = gt_daterange
IMPORTING
et_dates_cut = gt_daterange.
| User | Count |
|---|---|
| 4 | |
| 2 | |
| 2 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 | |
| 1 |