Showing posts with label Utility Tips. Show all posts
Showing posts with label Utility Tips. Show all posts

How to get Internal Table Components at runtime

This code can be helpful to get fields names of an Internal Table at Runtime.

The Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
*&---------------------------------------------------------------------*
*& Report ZTEST_INTERNAL_TAB_COMP
*&
*&---------------------------------------------------------------------*
*&***********DEMO Code for http://abap-explorer.blogspot.com/***********
*&
*&---------------------------------------------------------------------*

report ztest_internal_tab_comp line-size 100.
type-pools: abap.

*Declare the type of the internal table
types: begin of x_final,
matnr type matnr,
werks type werks_d,
flag type c length 1,
value type p length 10 decimals 2,
end of x_final.

data:
*The Internal table whose components are to found
i_data type sorted table of x_final with unique key matnr,
*Table to hold the components
tab_return type abap_compdescr_tab,
*Work area for the component table
components like line of tab_return.

*Call Perform to get the Int. Table Components
perform get_int_table_fields using i_data
changing tab_return.
*Display Components
loop at tab_return into components.
write: / components-name, components-type_kind,
components-length,components-decimals.
endloop.




*&---------------------------------------------------------------------*
*& Form get_int_table_fields
*&---------------------------------------------------------------------*
* Get the Components of an internal table
*----------------------------------------------------------------------*
* -->T_DATA text
* -->T_RETURN text
*----------------------------------------------------------------------*
form get_int_table_fields using t_data type any table
changing t_return type abap_compdescr_tab.

data:
oref_table type ref to cl_abap_tabledescr,
oref_struc type ref to cl_abap_structdescr,
oref_error type ref to cx_root,
text type string.
*Get the description of data object type
try.
oref_table ?=
cl_abap_tabledescr=>describe_by_data( t_data ).
catch cx_root into oref_error.
text = oref_error->get_text( ).
write: / text.
exit.
endtry.
*Get the line type
try.
oref_struc ?= oref_table->get_table_line_type( ).
catch cx_root into oref_error.
text = oref_error->get_text( ).
write: / text.
exit.
endtry.

append lines of oref_struc->components to t_return.

endform. " GET_INT_TABLE_FIELDS


Now if we test it...


The code can also be used to get components of a structure.

User Defined Conversion Exits

This post will show how to create custom user defined Conversion-Exits.

Step 1) Create a Function Group and two Function Modules:

a) Create a Function Group. For eg. ZCONVERSION_EXIT.

b) Create two Function Modules with naming convention:

CONVERSION_EXIT_xxxxx_INPUT and CONVERSION_EXIT_xxxxx_OUTPUT, where XXXXX is the name of the Conversion Routine. Here I will create a Routine ZZERO so the
name of the Function Modules will be CONVERSION_EXIT_ZZERO_INPUT and CONVERSION_EXIT_ZZERO_OUTPUT. While create the Function Module you may get some error like "Function Module name is reserved for SAP", you can ignore this.



The Function Modules should have one Import Parameter Input and one Export Parameter Output.

The FM for conversion from External Format to Internal Format:



The Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
FUNCTION conversion_exit_zzero_input.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(INPUT)
*" EXPORTING
*" REFERENCE(OUTPUT)
*"----------------------------------------------------------------------

output = input.
REPLACE ALL OCCURRENCES OF 'Ø' IN output
WITH '0' IN CHARACTER MODE.

ENDFUNCTION.


The FM for conversion from Internal Format to External Format:



The Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
FUNCTION CONVERSION_EXIT_ZZERO_OUTPUT.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(INPUT)
*" EXPORTING
*" REFERENCE(OUTPUT)
*"----------------------------------------------------------------------
output = input.
REPLACE ALL OCCURRENCES OF '0' IN output
WITH 'Ø' IN CHARACTER MODE.

ENDFUNCTION.


Step 2) Create a data Element and a Domain.

Create the Data Element ZZERO:



The Domain ZZERO:



The name of the conversion routine created has to provided here. Now if the FM's for Conversion are created, if you double click on the Routine name, it will display the FM's.



Step 3)Now we can use a sample code to test the Conversion Routine:
The Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
*&---------------------------------------------------------------------*
*& Report ZTEST_CONVERSION_EXIT
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ztest_conversion_exit.


PARAMETERS: p_value TYPE c LENGTH 20 OBLIGATORY.

DATA: v_result TYPE zzero. " data type with the Coversion Exit ZZERO

v_result = p_value.

WRITE: /5 'Input:',22 p_value,
/5
'Converted Value:',22 v_result.


Now test it, If we give an input as "345RGT00VDF4340".



When Executed:



The "0" has been replaced by "Ø"

Similarly the Input Conversion Routine can be used and tested.

The Best way to find SUM of records

In this post I would like to show which is the fastest way to find sum for a number of records.
The three possible ways to calculate a sum of records are:
  1. Using COLLECT Statement.
  2. Using SUM statement within Control-break statement AT-ENDAT.
  3. Using a variable within a parallel cursor.
The conclusion is that the second option always takes less time compared to other three.The following graph explains it:



The following code is used to calculate it.Please test it yourself and give me a feedback.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
PROGRAM ztest_sum.

TYPES:
BEGIN OF x_sbook,
carrid TYPE s_carr_id,
connid TYPE s_conn_id,
fldate TYPE s_date,
luggweight TYPE s_lugweigh,
wunit TYPE s_weiunit,
END OF x_sbook.

DATA: i_sbook TYPE STANDARD TABLE OF x_sbook INITIAL SIZE 0,
i_final1 TYPE STANDARD TABLE OF x_sbook INITIAL SIZE 0,
i_final2 TYPE STANDARD TABLE OF x_sbook INITIAL SIZE 0,
i_final3 TYPE STANDARD TABLE OF x_sbook INITIAL SIZE 0,
wa_sbook TYPE x_sbook,
rtime1 TYPE i,
rtime2 TYPE i,
rtime3 TYPE i.

PARAMETERS: p_rec TYPE i. " No. of records

SELECT carrid
connid
fldate
luggweight
wunit
FROM sbook
UP TO p_rec ROWS
INTO TABLE i_sbook.

CHECK sy-subrc = 0.
APPEND LINES OF i_sbook TO i_sbook.

SORT i_sbook BY carrid connid fldate.

PERFORM collect.

PERFORM at_end_of_sum.

PERFORM sum_by_variable.

END-OF-SELECTION.

PERFORM display.


*&---------------------------------------------------------------------*
*& Form collect
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM collect .
DATA: time1 TYPE i,
time2 TYPE i.

GET RUN TIME FIELD time1.

LOOP AT i_sbook INTO wa_sbook.
COLLECT wa_sbook INTO i_final1.
ENDLOOP.

GET RUN TIME FIELD time2.

rtime1 = time2 - time1.
ENDFORM. " collect
*&---------------------------------------------------------------------*
*& Form at_end_of_sum
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM at_end_of_sum .
DATA: time1 TYPE i,
time2 TYPE i.

GET RUN TIME FIELD time1.
LOOP AT i_sbook INTO wa_sbook.
AT END OF fldate.
SUM.
APPEND wa_sbook TO i_final2.
ENDAT.
ENDLOOP.

GET RUN TIME FIELD time2.

rtime2 = time2 - time1.
ENDFORM. " at_end_of_sum
*&---------------------------------------------------------------------*
*& Form sum_by_variable
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM sum_by_variable .
DATA: time1 TYPE i,
time2 TYPE i,
i_temp TYPE STANDARD TABLE OF x_sbook INITIAL SIZE 0,
l_index TYPE i,
wa_temp TYPE x_sbook,
l_weight TYPE s_lugweigh,
wa_final TYPE x_sbook.

GET RUN TIME FIELD time1.

i_temp = i_sbook.

DELETE ADJACENT DUPLICATES FROM i_temp
COMPARING carrid connid fldate.

LOOP AT i_temp INTO wa_temp.
READ TABLE i_sbook
TRANSPORTING NO FIELDS
WITH KEY carrid = wa_temp-carrid
connid = wa_temp-connid
fldate = wa_temp-fldate
BINARY SEARCH.
IF sy-subrc = 0.
l_index = sy-tabix.
LOOP AT i_sbook INTO wa_sbook FROM l_index.
IF wa_sbook-carrid <> wa_temp-carrid OR
wa_sbook-connid <> wa_temp-connid OR
wa_sbook-fldate <> wa_temp-fldate.
EXIT.
ENDIF.
l_weight = wa_sbook-luggweight + l_weight.
ENDLOOP.

wa_final = wa_sbook.
wa_final-luggweight = l_weight.
APPEND wa_sbook TO i_final3.
CLEAR l_weight.
ENDIF.
ENDLOOP.

GET RUN TIME FIELD time2.
rtime3 = time2 - time1.
ENDFORM. " sum_by_variable
*&---------------------------------------------------------------------*
*& Form display
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
* --> p1 text
* <-- p2 text
*----------------------------------------------------------------------*
FORM display .
DATA: wa_final TYPE x_sbook.

DATA: l_lines TYPE i.

l_lines = LINES( i_final1 ).
ULINE.
FORMAT COLOR 2 ON.
WRITE: /5 'Using COLLECT Statement',':', l_lines.
WRITE: /5 'Run Time:',rtime1,'microseconds'.
FORMAT COLOR 2 OFF.
ULINE.
l_lines = LINES( i_final2 ).
FORMAT COLOR 1 ON.
WRITE: /5 'Using Control Break statement AT-END-OF, SUM', ':',
l_lines.
WRITE: /5 'Run Time:',rtime2,'microseconds'.
FORMAT COLOR 1 OFF.
ULINE.
l_lines = LINES( i_final3 ).
FORMAT COLOR 4 ON.
WRITE: /5 'Using Parallel Cursor',':', l_lines.
WRITE: /5 'Run Time:',rtime3,'microseconds'.
FORMAT COLOR 4 OFF.
ULINE.
ENDFORM. " display

Traffic Light in ALV Reports

Many a times we have to display a traffic light in ALV report. We can do that easily using "Exceptions" parameter provided by SAP. But it has one drawback, we cannot change the column header to something meaningful. It always set as "Exception" in case of ALV Grid and an icon in case of ALV List.

Here I'll show a workaround to show the traffic lights with a meaningful column header.

The exception display:


















The workaround is to use a field of type CHAR4 and display it as Icon.
To display a field as icon, in ALV Field catalog we have to mark ICON field as 'X'. The icons for traffic lights are : icon_green_light, icon_red_light and icon_yellow_light.


















The code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
*&---------------------------------------------------------------------*
*& Report ZTEST_SOURAV_TRAFFIC_LIGHTS
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ztest_sourav_traffic_lights.
TYPE-POOLS: slis,icon.
TYPES: BEGIN OF x_sflight,
carrid TYPE s_carr_id,
connid TYPE s_conn_id,
fldate TYPE s_date,
price TYPE s_price,
currency TYPE s_currcode,
seatsmax TYPE s_seatsmax,
seatsocc TYPE s_seatsocc,
END OF x_sflight.
TYPES:BEGIN OF x_final,
icon TYPE char4.
INCLUDE TYPE x_sflight.
TYPES: END OF x_final.

DATA: i_sflight TYPE STANDARD TABLE OF x_sflight INITIAL SIZE 0,
i_final TYPE STANDARD TABLE OF x_final INITIAL SIZE 0,
i_fieldcat TYPE slis_t_fieldcat_alv,
wa_layout TYPE slis_layout_alv.


CONSTANTS: program TYPE syrepid VALUE sy-repid.

START-OF-SELECTION.
SELECT carrid " Airline Code
connid " Flight Connection Number
fldate " Flight date
price " Airfare
currency " Local currency of airline
seatsmax " Maximum capacity in economy class
seatsocc " Occupied seats in economy class
FROM sflight " Flight
INTO TABLE i_sflight.
IF sy-subrc <> 0.
MESSAGE i001(00) WITH 'No data found!'.
LEAVE LIST-PROCESSING.
ENDIF.


END-OF-SELECTION.

PERFORM populate_records.

PERFORM display_records.


*&---------------------------------------------------------------------*
*& Form populate_records
*&---------------------------------------------------------------------*
* Populate final table
*----------------------------------------------------------------------*
FORM populate_records .

DATA:
wa_sflight TYPE x_sflight,
wa_final TYPE x_final,
temp TYPE p DECIMALS 2.

LOOP AT i_sflight INTO wa_sflight.
CLEAR temp.
*Calculate Percentage of booked flights
temp = ( wa_sflight-seatsocc / wa_sflight-seatsmax ) .

IF temp > '0.9'.
*If booked more than 90%
wa_final-icon = icon_green_light.
ELSEIF temp < '0.2'.
*If booked less than 20%
wa_final-icon = icon_red_light.
ELSE.
*If its between 20% to 90 %
wa_final-icon = icon_yellow_light.
ENDIF.

wa_final-carrid = wa_sflight-carrid.
wa_final-connid = wa_sflight-connid.
wa_final-fldate = wa_sflight-fldate.
wa_final-price = wa_sflight-price.
wa_final-currency = wa_sflight-currency.
wa_final-seatsmax = wa_sflight-seatsmax.
wa_final-seatsocc = wa_sflight-seatsocc.

APPEND wa_final TO i_final.
CLEAR wa_final.
ENDLOOP.
FREE i_sflight.
ENDFORM. " populate_records
*&---------------------------------------------------------------------*
*& Form display_records
*&---------------------------------------------------------------------*
* Subroutines for Display
*----------------------------------------------------------------------*
FORM display_records .

PERFORM populate_field_catalog.

PERFORM populate_layout.

PERFORM trigger_alv.

ENDFORM. " display_records
*&---------------------------------------------------------------------*
*& Form populate_field_catalog
*&---------------------------------------------------------------------*
* Popualte Field Catalog
*----------------------------------------------------------------------*
FORM populate_field_catalog .
DATA:
wa_fieldcat TYPE slis_fieldcat_alv.
DEFINE fcat_merge.

wa_fieldcat-col_pos = &1.
wa_fieldcat-fieldname = &2.
if wa_fieldcat-fieldname = 'ICON'.
wa_fieldcat-icon = 'X'. " Display the field as ICON
wa_fieldcat-seltext_m = 'Occupency Status'. " Column Header
wa_fieldcat-inttype = 'C'.
wa_fieldcat-outputlen = '4'.
endif.

wa_fieldcat-ref_fieldname = &3.
wa_fieldcat-ref_tabname = &4.

if wa_fieldcat-fieldname = 'PRICE'.
wa_fieldcat-cfieldname = 'CURRENCY'.
wa_fieldcat-ctabname = 'I_FINAL'.
endif.

append wa_fieldcat to i_fieldcat.
clear wa_fieldcat.
END-OF-DEFINITION.

fcat_merge: '1' 'ICON' '' '',
'2' 'CARRID' 'CARRID' 'SFLIGHT',
'3' 'CONNID' 'CONNID' 'SFLIGHT',
'4' 'FLDATE' 'FLDATE' 'SFLIGHT',
'5' 'PRICE' 'PRICE' 'SFLIGHT',
'6' 'CURRENCY' 'CURRENCY' 'SFLIGHT',
'7' 'SEATSMAX' 'SEATSMAX' 'SFLIGHT',
'8' 'SEATSOCC' 'SEATSOCC' 'SFLIGHT'.

ENDFORM. " populate_field_catalog

*&---------------------------------------------------------------------*
*& Form populate_layout
*&---------------------------------------------------------------------*
* Populate LAYOUT Structure for ALV
*----------------------------------------------------------------------*
FORM populate_layout.
wa_layout-zebra = 'X'.
wa_layout-colwidth_optimize = 'X'.
ENDFORM. "populate_layout
*&---------------------------------------------------------------------*
*& Form trigger_alv
*&---------------------------------------------------------------------*
* Trigger the ALV API
*----------------------------------------------------------------------*
FORM trigger_alv .

CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY'
EXPORTING
i_callback_program = program
is_layout = wa_layout
it_fieldcat = i_fieldcat
TABLES
t_outtab = i_final
EXCEPTIONS
program_error = 1
OTHERS = 2.
IF sy-subrc <> 0.
MESSAGE i001(00) WITH 'Error while displaing ALV'.
LEAVE LIST-PROCESSING.
ENDIF.
ENDFORM. " trigger_alv