01-28-2008 7:33 AM
Im looking at a piece of code that uses a restricted loop on an itab and then goes on to use 'AT NEW' / 'AT END' and updates the itab on each.
It wont work of course. These constructs only work properly on an unrestricted loop and no updates.
But I still need to know the first and last record in each control group and change them before they hit the next 200 lines.
DESCRIBE will tell me how many records in an itab but I need to know how many records for a given key value.
I could run two loops of course and update the values in the first by a line by line comparason but Im looking for something a bit more elegant.
Oh yes, the loop already sits inside another bigger loop and its not indexed.
01-28-2008 11:55 AM
You could use two internal tables. The current one and a second one that
holds the control breaks counters. I suggest you to use a hashed table
for the second one.
Then all the code you have to use is the following
Data: begin of wa_hashedtable,
Your_key_fields_list_goes_here,
Counter type I,
End of wa_hashedtable,
Hashedtable like hashed table of wa_hashedtable
With unique key your_key_fields_list
With header line . "(just to simplify the coding of the collect
loop shown bellow)
simulate a collect to count the number of occurrences for a given
key.
Refresh hashedtable.
Loop at youritab
Read table hashedtable with table key ....
If sy-subrc <> 0.
Clear hashedtable.
Insert a record into hashedtable with counter1 (meaning that you have one row for that count)
Else
Add 1 to hashedtable-counter.
Modify table hasedtable transporting counter.
Endif.
Endloop
At this point hashedtable holds the key plus a counter of records for
that key. Then if you want to know how many rows are associated to a
given key (at new... or at end...) all you have to do is read table
hashedtable with table key... with the appropiated values.
As the auxliary table is of type hashed, it should run fast no matter
how many rows (how many keys) it holds.
I think this is one of the fastest ways of simulating a describe table.
satish.
01-28-2008 7:40 AM
Using AT FIRST , AT NEW, AT THE END OF , AT LAST.
DATA: BEGIN OF ITAB OCCURS 0,
F1 TYPE I,
F2(6) TYPE C,
F3(10) TYPE N,
F4(16) TYPE P DECIMALS 2,
END OF ITAB.
DATA: SUB_TOT(10) TYPE P DECIMALS 3.
**--1
ITAB-F1 = 1.
ITAB-F2 = 'ONE'.
ITAB-F3 = 10.
ITAB-F4 = '1000.00'.
APPEND ITAB.
CLEAR ITAB.
ITAB-F1 = 1.
ITAB-F2 = 'ONE'.
ITAB-F3 = 20.
ITAB-F4 = '2000.00'.
APPEND ITAB.
CLEAR ITAB.
ITAB-F1 = 1.
ITAB-F2 = 'ONE'.
ITAB-F3 = 30.
ITAB-F4 = '3000.00'.
APPEND ITAB.
CLEAR ITAB.
*--2
ITAB-F1 = 2.
ITAB-F2 = 'TWO'.
ITAB-F3 = 10.
ITAB-F4 = '1000.00'.
APPEND ITAB.
CLEAR ITAB.
ITAB-F1 = 2.
ITAB-F2 = 'TWO'.
ITAB-F3 = 20.
ITAB-F4 = '2000.00'.
APPEND ITAB.
CLEAR ITAB.
*-- 3
ITAB-F1 = 3.
ITAB-F2 = 'THREE'.
ITAB-F3 = 10.
ITAB-F4 = '1000.00'.
APPEND ITAB.
CLEAR ITAB.
ITAB-F1 = 3.
ITAB-F2 = 'THREE'.
ITAB-F3 = 20.
ITAB-F4 = '2000.00'.
APPEND ITAB.
CLEAR ITAB.
SORT ITAB BY F1.
LOOP AT ITAB.
AT FIRST.
WRITE: /35 ' MATERIAL DETAILS:'.
ULINE.
ENDAT.
AT NEW F1.
WRITE: / 'DETAILS OF MATERIAL:' COLOR 7 , ITAB-F1.
ULINE.
ENDAT.
WRITE: / ITAB-F1, ITAB-F2, ITAB-F3, ITAB-F4.
SUB_TOT = SUB_TOT + ITAB-F4.
AT END OF F1.
ULINE.
WRITE: / 'SUB TOTAL :' COLOR 3 INVERSE ON, SUB_TOT COLOR 3 INVERSE ON.
CLEAR SUB_TOT.
ENDAT.
AT LAST.
SUM.
ULINE.
WRITE: 'SUM:', ITAB-F4.
ULINE.
ENDAT.
ENDLOOP.
01-28-2008 11:55 AM
You could use two internal tables. The current one and a second one that
holds the control breaks counters. I suggest you to use a hashed table
for the second one.
Then all the code you have to use is the following
Data: begin of wa_hashedtable,
Your_key_fields_list_goes_here,
Counter type I,
End of wa_hashedtable,
Hashedtable like hashed table of wa_hashedtable
With unique key your_key_fields_list
With header line . "(just to simplify the coding of the collect
loop shown bellow)
simulate a collect to count the number of occurrences for a given
key.
Refresh hashedtable.
Loop at youritab
Read table hashedtable with table key ....
If sy-subrc <> 0.
Clear hashedtable.
Insert a record into hashedtable with counter1 (meaning that you have one row for that count)
Else
Add 1 to hashedtable-counter.
Modify table hasedtable transporting counter.
Endif.
Endloop
At this point hashedtable holds the key plus a counter of records for
that key. Then if you want to know how many rows are associated to a
given key (at new... or at end...) all you have to do is read table
hashedtable with table key... with the appropiated values.
As the auxliary table is of type hashed, it should run fast no matter
how many rows (how many keys) it holds.
I think this is one of the fastest ways of simulating a describe table.
satish.
01-28-2008 12:32 PM
hi,
hope this info helps u,
All this AT NEW, AT FIRST, AT END OF and AT LAST are called control break statements of Internal tables and are used to calculate the TOTALS based on sertain key fields in that internal table
FIrst to use these statements the ITAB has to be sorted by the key fields on whcih you need the SUM of the fields.
Some time you will get * when mopving data from this int table to other table using these commands
so you have to use
READ TABLE ITAB INDEX SY-TABIX in AT..ENDAT..if you are using other fields between them
DATA: sflight_tab TYPE SORTED TABLE OF sflight
WITH UNIQUE KEY carrid connid fldate,
sflight_wa LIKE LINE OF sflight_tab.
SELECT *
FROM sflight
INTO TABLE sflight_tab.
LOOP AT sflight_tab INTO sflight_wa.
AT NEW connid.
WRITE: / sflight_wa-carrid,
sflight_wa-connid.
ULINE.
ENDAT.
WRITE: / sflight_wa-fldate,
sflight_wa-seatsocc.
AT END OF connid.
SUM.
ULINE.
WRITE: / 'Sum',
sflight_wa-seatsocc UNDER sflight_wa-seatsocc.
SKIP.
ENDAT.
AT END OF carrid.
SUM.
ULINE.
WRITE: / 'Carrier Sum',
sflight_wa-seatsocc UNDER sflight_wa-seatsocc.
NEW-PAGE.
ENDAT.
AT LAST.
SUM.
WRITE: / 'Overall Sum',
sflight_wa-seatsocc UNDER sflight_wa-seatsocc.
ENDAT.
ENDLOOP.
plz reward, if found helpfull,
thanx,
nithin