ALV Grid - Page Numbering Problem



Problem: When you prints an ALV report, you want the pagenumber and the total number of pages in the heading (E.g. Page xxx of yyy).
The total number of pages are usually calculated from the number of lines in the report table, number of lines in the report header and the number of lines
on each report page, and should not cause any problems.

However, the standard print dialog screen for the ALV grid has an option "ALV statistics". When this option ís chosen, a page with ALV statistics will be
printed before the ALV report and the total number of pages will be wrong as an extra page has been added to the report.

The solution is to use the ALV events Top Of Page, Top Of List and End Of List as demonstrated in the enclosed example.



REPORT zhfnk_alvtest.
*--------------------------------------------------------------------
* This example demonstrates a solution to a problem
* that arises when you want to include the number of pages in
* an ALV report (E.g. Pageno xxx of yyy), and choses to include
* ALV statistics when you print the report.
*
* When you count the total number of pages it is usually
* calculated from the number of lines in the report table,
* number of lines in the report header and the number of lines
* on each report page. However, if you include the ALV statistics when
* you print the report, this page will not be included in the total
* number of pages.
*
* The solution demonstrated below, is to use the ALV events
* Top Of Page, Top Of List and End Of List.
*
* 2006-10-05 Henrik Frank NNIT A/S
*
*--------------------------------------------------------------------


TYPE-POOLS: slis.


TYPES:
BEGIN OF t_makt,
matnr LIKE makt-matnr,
maktx LIKE makt-maktx,
END OF t_makt.

DATA:
it_makt TYPE STANDARD TABLE OF t_makt,
wa_makt TYPE t_makt.


******************************************************************'
* Data declarations for the ALV grid
******************************************************************'
DATA:
r_grid TYPE REF TO cl_gui_alv_grid,
alv_fieldcat TYPE slis_t_fieldcat_alv,
wa_alv_fieldcat TYPE slis_fieldcat_alv,
alv_layout TYPE slis_layout_alv,
gt_events TYPE slis_t_event.



******************************************************************'
* Other data declarations
******************************************************************'

DATA:
gd_repid LIKE sy-repid,
g_first_top_of_page(1) TYPE c, "Flag for first top of page event
g_totpages(3) TYPE n,
g_pageno(3) TYPE n,
g_start_of_list(1) TYPE c.




START-OF-SELECTION.
g_first_top_of_page = 'X'.
CLEAR g_start_of_list.

PERFORM alv_setup.
PERFORM build_events.
PERFORM read_data.



END-OF-SELECTION.
PERFORM display_alv.


*&---------------------------------------------------------------------*
*& Form read_data
*&---------------------------------------------------------------------*
FORM read_data.
SELECT matnr maktx
FROM makt
INTO TABLE it_makt
WHERE spras = 'E'.
ENDFORM. " read_data


*&---------------------------------------------------------------------*
*& Form alv_setup
*&---------------------------------------------------------------------*
*
* Setup of the columns in the ALV grid
*
*----------------------------------------------------------------------*
FORM alv_setup.

CLEAR wa_alv_fieldcat.
REFRESH alv_fieldcat.

* Matnr field
wa_alv_fieldcat-key = 'X'. "This is a key column
wa_alv_fieldcat-fieldname = 'MATNR'. "Name of the table eld
wa_alv_fieldcat-seltext_s = 'Matnr'. "Short column heading
wa_alv_fieldcat-seltext_m = 'Material nr.'. "Medium column heading
wa_alv_fieldcat-seltext_l = 'Material number'. "Long column heading
APPEND wa_alv_fieldcat TO alv_fieldcat.

* Mat text field
wa_alv_fieldcat-key = ''. "This is not a key column
wa_alv_fieldcat-fieldname = 'MAKTX'.
wa_alv_fieldcat-seltext_s = 'Mat. txt'.
wa_alv_fieldcat-seltext_m = 'Material txt'.
wa_alv_fieldcat-seltext_l = 'Material text'.
APPEND wa_alv_fieldcat TO alv_fieldcat.

ENDFORM. " alv_setup

*&------------------------------------------------------------------*
*& Form BUILD_EVENTS
*&------------------------------------------------------------------*
* Build events tabel for function module
* REUSE_ALV_GRID_DISPLAY. The events that we are interested in are:
*
* Note that each event is assigned to a sub routine that is
* executed when the event is triggered
*
*
* - Top Of List - Subroutine TOP_OF_LIST
* - End Of List - END_OF_LIST
*
*-------------------------------------------------------------------*
FORM build_events.
DATA: ls_event TYPE slis_alv_event.

CALL FUNCTION 'REUSE_ALV_EVENTS_GET'
EXPORTING
i_list_type = 0
IMPORTING
et_events = gt_events[].


READ TABLE gt_events WITH KEY name = slis_ev_top_of_list
INTO ls_event.
IF sy-subrc = 0.
MOVE 'TOP_OF_LIST' TO ls_event-form.
MODIFY gt_events INDEX sy-tabix FROM ls_event.
ENDIF.



READ TABLE gt_events WITH KEY name = slis_ev_end_of_list
INTO ls_event.
IF sy-subrc = 0.
MOVE 'END_OF_LIST' TO ls_event-form.
MODIFY gt_events INDEX sy-tabix FROM ls_event.
ENDIF.




ENDFORM. " BUILD_EVENTS

*&---------------------------------------------------------------------*
*& Form display_alv
*&---------------------------------------------------------------------*
* Display data in the ALV grid using function module
*
*----------------------------------------------------------------------*
FORM display_alv.

gd_repid = sy-repid.

* Configure layout of screen
alv_layout-colwidth_optimize = 'X'.
alv_layout-zebra = 'X'.
alv_layout-no_min_linesize = 'X'.



* Call ALV function module
CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = gd_repid
i_callback_top_of_page = 'TOP_OF_PAGE' "Ref to form
is_layout = alv_layout
it_fieldcat = alv_fieldcat
it_events = gt_events
* is_print = gd_prntparams
TABLES
t_outtab = it_makt
EXCEPTIONS
program_error = 1
OTHERS = 2.

IF sy-subrc <> 0.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.


ENDFORM. " display_alv

*------------------------------------------------------------------*
* Form TOP_OF_LIST
*------------------------------------------------------------------*
*
* This event is triggerede once at top of the actual list,
* BUT NOT at the top of the ALV Statistics page
*------------------------------------------------------------------*
FORM top_of_list.
* Set flag that indicates that print of the ALV list has begun
g_start_of_list = 'X'.
ENDFORM. "TOP_OF_LIST



*---------------------------------------------------------------------*
* Form TOP_OF_PAGE
*---------------------------------------------------------------------*
* This event is triggered at every top of page including top of
* page inclduing the top of the ALV statistics page
*
*----------------------------------------------------------------------*
FORM top_of_page.
DATA: t_header TYPE slis_t_listheader,
wa_header TYPE slis_listheader,
pagno(3) TYPE n.


*---------------------------------------------------------------------
* If the list is being printed (Not didslayed) and this is the first
* time the Top Of Page event is triggered, then caculate number
* of pages for the ALV list
*---------------------------------------------------------------------
IF sy-ucomm EQ 'PRIN' AND g_first_top_of_page = 'X'.
PERFORM get_total_number_of_pages CHANGING g_totpages.
CLEAR g_first_top_of_page.
ENDIF.



* If this is a printed list
IF sy-ucomm EQ 'PRIN'.

*---------------------------------------------------------------------
* The Start Of List event has not yet been triggered. Thsi means that
* we are at the top of an ALV statistics page. Add the
* ALV statistics page to total number of pages
*---------------------------------------------------------------------
IF g_start_of_list = ' '.
g_totpages = g_totpages + 1.
ENDIF.




* Create ALV header
wa_header-typ = 'H'.

g_pageno = sy-pagno.

CONCATENATE 'Mylist page' g_pageno 'of' g_totpages
space INTO wa_header-info SEPARATED BY space.

APPEND wa_header TO t_header.

CLEAR wa_header.

CALL FUNCTION 'REUSE_ALV_COMMENTARY_WRITE'
EXPORTING
it_list_commentary = t_header.

ENDIF.

ENDFORM. " top_of_page_setup

*-------------------------------------------------------------------
* Form END_OF_LIST
*
* Clear flags in case the user choses to reprint the report
*
*-------------------------------------------------------------------
FORM end_of_list.
g_first_top_of_page = 'X'.
CLEAR g_pageno.
CLEAR g_start_of_list.
ENDFORM. "END_OF_LIST


*---------------------------------------------------------------------*
* Form get_total_number_of_pages
*---------------------------------------------------------------------*
* Calcualtes the total page numbers from the number of lines in
* the header of the report and the number of entries in the
* input table
*----------------------------------------------------------------------*
FORM get_total_number_of_pages CHANGING p_total_number_of_pages.

DATA: l_tot_pages TYPE f ,
l_tot_lines TYPE i,
l_lines_per_page TYPE i,
l_number_of_header_lines TYPE i VALUE 13.


* Find number of lines in report table
DESCRIBE TABLE it_makt LINES l_tot_lines.


* Number of lines per pages excl. page header (13 lines)
l_lines_per_page = sy-linct - l_number_of_header_lines.


* Total number ofpages
* Round up the the page number to nearest integer
l_tot_pages = CEIL( l_tot_lines / l_lines_per_page ).

p_total_number_of_pages = l_tot_pages.

* In case that there are no data in the report
IF p_total_number_of_pages = '0'.
p_total_number_of_pages = '1'.
ENDIF.





ENDFORM. " get_total_number_of_pages
Converted from CHM to HTML with chm2web Standard 2.7 (unicode)