Day 12

Advanced Internal Tables, Part 1


Chapter Objectives

After you complete this chapter, you should be able to:

Testing and Modifying Internal Table Contents

Use the following constructs to test and modify the contents of internal tables:

The body of an internal table is represented by the syntax it[], where it is the name of any internal table. it[] means "the body of the internal table it." There cannot be anything between the square brackets; they must be written precisely as shown. You can use this syntax to perform efficient table operations that do not require the use of a header line. These operations are described throughout this chapter.

If an internal table does not have a header line, the internal table name itself represents the body. For example, if internal table it does not have a header line, you can use either it[] or it to represent the body; they are equivalent.

Obtaining Information about an Internal Table

You can obtain the following commonly needed information about an internal table:

Determining Whether an Internal Table Is Empty

If the body of an internal table contains only initial values (blanks and spaces), it is empty. Therefore, to determine whether an internal table contains any rows, test the body with the following statement:

if it[] is initial.

If the test is true, the internal table is empty. When false, it contains at least one row.

Determining the Number of Rows in an Internal Table

To determine the number of rows in an internal table, use the sy-tfill variable. It is set by the describe table statement.

Syntax for the describe table Statement

The following is the syntax for the describe table statement.

describe table it [lines i] [occurs j].

where:

This statement fills the three system variables shown in Table 12.1.

Table 12.1  DESCRIBE TABLE Statement Fills These System Variables
Variable
Value
sy-tfillNumber of rows
sy-tlengLength of a row in bytes
sy-toccuCurrent value of the occurs clause

The following points apply:

NOTE
There is only one instance where sy-toccu will differ from the occurs clause on the table definition. When sy-tleng * sy-toccu > 8192, and after one row has been added to the internal table, sy-toccu will be zero. This indicates that memory is being allocated in 8KB chunks for this internal table.

Sample Program that Obtains Information About an Internal Table

Listing 12.1 shows a sample program that obtains information about an internal table.


Listing 12.1  The describe table Statement Uses System Variables to Quantify Table Contents

 1  report ztx1201.
 2  data: begin of it occurs 3,
 3            f1 value 'X',
 4            end of it,
 5        n type i.
 6 
 7  if it[] is initial.
 8      write: / 'it is empty'.
 9      endif.
10
11 append: it, it, it.     "same as writing 'append it' 3 times.
12
13 if not it[] is initial.
14     write: / 'it is not empty'.
15     endif.
16
17 write: / 'number of  rows from sy-tabix:', sy-tabix.
18 describe table it lines n.
19 write: / 'number of  rows from sy-tfill:', sy-tfill,
20        / 'length of a row from sy-tleng:', sy-tleng,
21        / 'occurs value    from sy-toccu:', sy-toccu.

The code in Listing 12.1 produces this output:

it is empty                              
it is not empty                          
number of  rows from sy-tabix:          3
number of  rows from sy-tfill:          3
length of a row from sy-tleng:     1     
occurs value    from sy-toccu:          3

TIP
If you only need to know whether the table contains data and not how many rows it has, use the table body operator. It is more efficient than the describe table statement.

Copying Data from one Internal Table to Another

If two internal tables have the same structure, use the following statement to duplicate the contents of one internal table in another:

it2[] = it1[].

The preceding statement copies the contents of the body of it1 and places it in the body of it2. Any existing contents in it2 are overwritten. The contents of the header lines, if either internal table has one, remain unchanged. This is the most efficient way to copy the contents from one internal table to another.

NOTE
Two internal tables have the same structure if 1) they both have the same number of components, and 2) the data type and length of each component is the same as the corresponding component of the other internal table. Only the component names do not have to match.

Copying a Portion of an Internal Table

If you want to copy a portion of an internal table to another, or if you want to leave the contents of the target table in place, use the append lines and insert lines statements.

Using the append lines Statement

Use the append lines statement when you want to append rows to the end of the target table.

Syntax for the append lines Statement
The following is the syntax for the append lines statement.
append lines of it1 [from nf] [to nt] to it2.
where: The following points apply:

TIP
Using append lines is three to four times faster than using append to add the rows one at a time.

Using the insert lines Statement

Use the insert lines statement when you want to insert rows at a place other than the end into the target table.

Syntax for the insert lines Statement
The following is the syntax for the insert lines statement.
insert lines of it1 [from nf] [to nt] into it2 [index nb].
where: All of the points that apply to the append lines statement also apply here. The difference is that rows from it1 are inserted into it2 before row number nb. If the value of nb is the number of rows in it2 plus 1, the row is appended to the end of it2. If nb is greater than that, the row is not appended and sy-subrc is set to 4. If nb is less than 1, a runtime error occurs.
You can use this statement inside or outside of loop at it2. If used outside, you must specify the index addition. Inside, index is optional. If it is not specified, the current row number in it2 is assumed.

Sample Program that Copies Data Between Internal Tables

Listing 12.2 shows a sample program that copies data from one internal table to another.


Listing 12.2  This Program Copies the Data from One Internal Table to Another Using the append lines and insert lines Statements

 1  report ztx1202.
 2  data: begin of it1 occurs 10,
 3            f1,
 4            end of it1,
 5        it2 like it1 occurs 10 with header line,
 6        alpha(10) value 'ABCDEFGHIJ'.
 7 
 8  do 10 times varying it1-f1 from alpha+0 next alpha+1.
 9      append it1.
10     enddo.
11
12 append lines of it1 from 2 to 5 to it2.
13 loop at it2.
14     write it2-f1.
15     endloop.
16
17 insert lines of it1 from 8 into it2 index 2.
18 skip.
19 loop at it2.
20     write it2-f1.
21     endloop.
22
23 loop at it2.
24     if it2-f1 >= 'E'.
25         insert lines of it1 to 1 into it2.
26         endif.
27     endloop.
28
29 skip.
30 loop at it2.
31     write it2-f1.
32     endloop.
33
34 skip.
35 it2[] = it1[].
36 loop at it2.
37     write it2-f1.
38     endloop.

The code in Listing 12.2 produces this output:

B C D E              
                     
B H I J C D E        
                     
B A H A I A J C D A E
                     
A B C D E F G H I J  

Comparing the Contents of Two Internal Tables

You can use the table body operator to compare the contents of two internal tables, as shown here:

if it1[] = it2[].

To use this construct, the internal tables must have the same structure. If they do not, you will have to compare them manually, row by row.

This statement is true when it1 and it2 contain the same number of rows and the contents of each row are the same.

TIP
The If - Equal to statement is the most efficient way to compare the con-tents of two internal tables.

Using the editor-call Statement

The editor-call statement displays the contents of an internal table to the user in an editor similar to the ABAP/4 source code editor. It is useful for debugging and as a simple interface for allowing the user to enter and modify data in tabular form.

Syntax for the editor-call Statement

The following is the syntax for the editor-call statement.

editor-call for it [title t] [display mode]

where:

The following points apply:

The display mode addition causes the data to be displayed in the editor in display mode. The user will be able to search and scroll, but will not be able to change the contents.

After viewing or modifying the internal table contents via the editor, the user presses one of these buttons: Save, Back, Exit, or Cancel. Save saves the changes made to the internal table contents and returns to the program. Back, Exit, and Cancel leave the editor and return to the program. If changes have been made, the user is prompted to save or cancel the changes.

After the editor-call statement has executed, sy-subrc is set to the values shown in Table 12.2.

Table 12.2  Values of SY-SUBRC After the EDITOR-CALL Statement
sy-subrc
Meaning
0
A save was performed. The contents of the internal table might or might not be changed.
4
The user did not perform a save. The contents of the internal table are unchanged.

Listing 12.3 shows a sample program that uses the editor-call statement. In this example, the internal table is filled with five lines and displayed in the editor so that the user can modify the data. The contents are then written out, and a message is also written to indicate whether a change was performed.


Listing 12.3  Use the editor-call Statement to View, Edit, and Debug the Contents of an Internal Table.

 1  report ztx1203.
 2  data: begin of it occurs 10,
 3            t(72),                  "text
 4            end of it,
 5        save_it like it occurs 10.  "will contain copy of the original
 6 
 7  it-t = 'Name         :'. append it.
 8  it-t = 'Address      :'. append it.
 9  it-t = 'Phone        :'. append it.
10 it-t = 'Freeform Text '. append it.
11 clear it-t with '-'.     append it.
12
13 save_it = it[].                   "same as: save_it[] = it[].
14 editor-call for it title 'Freeform Entry'.
15 if sy-subrc = 4.                  "user did not perform a save
16     write: / 'Data was not changed'.
17 elseif save_it[] <> it[].         "user performed a save
18     write: / 'Data was changed'.
19 else.
20     write: / 'Data was not changed'.
21     endif.
22 write: / sy-uline(72).
23 loop at it.
24     write: / it-t.
25     endloop.

If no data is entered when the editor is displayed, the code in Listing 12.3 produces this output:

Data was not changed                                       
-----------------------------------------------------------------------
Name         :                                                         
Address      :                                                         
Phone        :                                                         
Freeform Text                                                          
-------------------------------------------------------------------

Inserting Rows into an Internal Table

To insert a single row into an internal table, use the insert statement.

Syntax for the insert Statement

The following is the syntax for the insert statement.

insert [wa into] it [index n]

where:

The following points apply:

Listing 12.4 contains a sample program that uses the insert statement.


Listing 12.4  Use the insert Statement to Insert a Single Row into an Internal Table

 1  report ztx1204.
 2  data: begin of it occurs 5,
 3            f1 like sy-index,
 4            end of it.
 5 
 6  do 5 times.
 7      it-f1 = sy-index.
 8      append it.
 9      enddo.
10
11 it-f1 = -99.
12 insert it index 3.
13
14 loop at it.
15     write / it-f1.
16     endloop.
17
18 loop at it where f1 >= 4.
19     it-f1 = -88.
20     insert it.
21     endloop.
22
23 skip.
24 loop at it.
25     write / it-f1.
26     endloop.

The code in Listing 12.4 produces this output:

         1     
         2     
        99-    
         3     
         4     
         5     
               
         1     
         2     
        99-    
         3     
        88-    
         4     
        88-    
         5     

12

TIP
After each insert statement is executed, the system re-indexes all rows below the one inserted. This introduces overhead when you insert rows near the top of a large internal table. If you need to insert a block of rows into a large internal table, prepare another table with the rows to be inserted and use insert lines instead. The rows in the target table will only be re-indexed once, after this statement has executed.

When inserting a new row into it inside of a loop at it, the insert does not affect the internal table immediately, but instead it becomes effective on the next loop pass. When inserting a row after the current row, the table is re-indexed at the endloop, sy-tabix is incremented, and the next loop pass processes the row pointed to by sy-tabix. For example, suppose you are in the third loop pass and you insert a record before row 4. When endloop is executed, the new row becomes row 4, the old row 4 becomes row 5, and so on. Sy-tabix is incremented by 1, and the next loop pass processes the newly inserted record.

If, inside of a loop, you insert a row before the current row, the table is again re-indexed at the endloop. This time, however, sy-tabix is incremented by 1 plus the number of rows inserted before the current row. The next time through the loop, the row following the current row is processed. Suppose, for example, in the third loop pass you insert a row before row 3. At the endloop, the new row becomes row 3, row 3 becomes row 4, and so on. The row you just processed now has an index of 4. sy-tabix is incremented by 2, which gives 5. Row 4 was re-indexed to 5, so it is processed on the next loop pass.

Modifying Rows in an Internal Table

To modify the contents of one or more rows of an internal table, use the modify statement.

Syntax for the modify Statement

The following is the syntax for the modify statement.

modify it [from wa] [index n] [transporting c1 c2 ... [where exp]]

where:

The following points apply:

transporting specifies which components are to be overwritten. Without it, all are overwritten. With it, only the specified components are overwritten. The rest remain unchanged.

Specifying a where condition after transporting causes the specified components to be overwritten in all rows that satisfy the where clause. The left-hand side of each part of exp must specify a component of it. The same component can be specified both after transporting and in exp.

You can't use modify it with where:

Listing 12.5 shows a sample program that modifies the contents of an internal table.


Listing 12.5  Use modify to Overwrite the Existing Contents of One or More Rows of an Internal Table

 1  report ztx1205.
 2  data: begin of it occurs 5,
 3            f1 like sy-index,
 4            f2,
 5            end of it,
 6        alpha(5) value 'ABCDE'.
 7 
 8  do 5 times varying it-f2 from alpha+0 next alpha+1.
 9      it-f1 = sy-index.
10     append it.
11     enddo.
12
13 it-f2 = 'Z'.
14 modify it index 4.
15
16 loop at it.
17     write: / it-f1, it-f2.
18     endloop.
19
20 loop at it.
21     it-f1 = it-f1 * 2.
22     modify it.
23     endloop.
24
25 skip.
26 loop at it.
27     write: / it-f1, it-f2.
28     endloop.
29
30 it-f2 = 'X'.
31 modify it transporting f2 where f1 <> 10.
32
33 skip.
34 loop at it.
35     write: / it-f1, it-f2.
36     endloop.

The code in Listing 12.5 produces this output:

         1  A  
         2  B  
         3  C  
         5  Z  
         5  E  
               
         2  A  
         4  B  
         6  C  
        10  Z  
        10  E  
               
         2  X  
         4  X  
         6  X  
        10  Z  
        10  E  

Deleting Internal Table Contents

To delete contents of an internal table, you can use the following statements:

Using free to Delete Internal Table Contents

Use the free statement to delete all rows from an internal table and free the associated memory.

Syntax for the free Statement

The following is the syntax for the free statement.

free it.

where:

The following points apply:

Use free when you are finished using an internal table.

TIP
Although the memory for internal tables is automatically freed when your program ends, freeing it yourself is usually more efficient. The reason for this lies in the fact that when the output is displayed to the user, technically your program has not yet ended. All resources remain allocated and the pro-gram does not end until the user presses the Back button. This finally ends your program and frees all internal table contents. You can free the internal tables sooner by putting free statements at the end of your program. The internal table contents will be released before the user sees the list instead of after.

Listing 12.6 shows how to use the free statement.


Listing 12.6  Use the free Statement to Delete All Rows from an Internal Table and Free the Associated Memory

1  report ztx1206.
2  data: begin of it occurs 3,
3            f1 like sy-index,
4            end of it.
5 
6  do 3 times.
7      it-f1 = sy-index.
8      append it.
 9      enddo.
10
11 loop at it.
12     write it-f1.
13     endloop.
14
15 free it.
16 if it[] is initial.
17     write: / 'no rows exist in it after free'.
18     endif.

The code in Listing 12.6 produces this output:

         1           2           3  
no rows exist in it after free      

Line 15 deletes all rows from the internal table and frees the associated memory.

Using refresh to Delete Internal Table Contents

Use the refresh statement to delete all rows from an internal table but leave the memory allocated.

Syntax for the refresh Statement

The following is the syntax for the refresh statement.

refresh it.

where:

The following points apply:

Use refresh when you want to delete all rows but you intend to fill the internal table back up again. For example, if you are producing a sales report by department, you might fill the internal table with all sales for one department, process the data, and write it out. Then, after a refresh, you could fill the internal table with the data for the next department, write it out, and so on.

If you intend to refill a table immediately after clearing it, refresh is more efficient than free because it avoids unnecessary memory allocations.

Listing 12.7 shows how to use the refresh statement.


Listing 12.7  Use the refresh Statement to Delete All Rows from an Internal Table

 1  report ztx1207.
 2  data: begin of it occurs 3,
 3            f1 like sy-index,
 4            end of it,
 5        i like sy-index.
 6
 7  do 3 times.
 8      i = sy-index.
 9      do 3 times.
10         it-f1 = i * sy-index.
11         append it.
12         enddo.
13     write: / ''.
14     loop at it.
15         write it-f1.
16         endloop.
17     refresh it.
18     enddo.
19
20 free it.

The code in Listing 12.7 produces this output:

           1           2           3
           2           4           6
           3           6           9

Using clear with an Internal Table

You can use the clear statement to do either of the following:

Syntax for the clear Statement When Used with an Internal Table

The following is the syntax for the clear statement when used with an internal table.

clear it | clear it[]

where:

The following points apply:

The effect of clear on an internal table is summarized in Table 12.3. The effect of clear varies depending on whether the internal table has a header line or not.

Table 12.3  Effect of CLEAR on an Internal Table


Statement
If it has a
header line
If it doesn't have
a header line
clear itClears the header line Deletes all rows
clear it[]Deletes all rows Deletes all rows

The program in Listing 12.8 illustrates the use of the clear statement with an internal table.


Listing 12.8 The clear Statement Can be Used to Clear the Header Line or Delete the Contents of an Internal Table

 1  report ztx1208.
 2  data: begin of it occurs 3,
 3            f1,
 4            end of it.
 5 
 6  it-f1 = 'X'.
 7  append: it, it.
 8 
 9  clear it.         "it has a header line so clears the header line
10 write: 'f1=', it-f1.
11
12 write: / ''.
13 loop at it.
14    write it-f1.
15    endloop.
16
17 clear it[].       "same as: refresh it.
18 loop at it.
19    write it-f1.
20    endloop.
21 write: / 'sy-subrc=', sy-subrc.

The code in Listing 12.8 produces this output:

f1=            
  X X          
sy-subrc=     4

Using the delete Statement to Delete Rows from an Internal Table

Using the delete statement, you can delete one or more rows from an internal table.

Syntax for the delete Statement

The following is the syntax for the delete statement.

delete it  (a) [index n]
           (b) [from i] [to j]
           (c) [where exp]

where:

The following points apply:

Listing 12.9 shows a sample program that deletes data from an internal table using the delete statement.


Listing 12.9  Deleting Rows from an Internal Table Can also be Done Using the delete Statement

1  report ztx1209.
2  data: begin of it occurs 12,
3            f1,
4            end of it,
 5            alpha(12) value 'ABCDEFGHIJKL'.
 6 
 7  do 12 times varying it-f1 from alpha+0 next alpha+1.
 8      append it.
 9      enddo.
10
11 loop at it.
12     write: / sy-tabix, it-f1.
13     endloop.
14
15 delete it index 5.
16 skip.
17 loop at it.
18     write: / sy-tabix, it-f1.
19     endloop.
20
21 delete it from 6 to 8.
22 skip.
23 loop at it.
24     write: / sy-tabix, it-f1.
25     endloop.
26
27 delete it where f1 between 'B' and 'D'.
28 skip.
29 loop at it.
30     write: / sy-tabix, it-f1.
31     endloop.
32
33 loop at it where f1 between 'E' and 'J'.
34     delete it.
35     endloop.
36
37 skip.
38 loop at it.
39     write: / sy-tabix, it-f1.
40     endloop.
41
42 read table it with key f1 = 'K' binary search.
43 write: /, / 'sy-subrc=', sy-subrc, 'sy-tabix=', sy-tabix, / ''.
44 if sy-subrc = 0.
45     delete it index sy-tabix.
46     endif.
47
48 skip.
49 loop at it.
50     write: / sy-tabix, it-f1.
51     endloop.
52
53 free it.

The code in Listing 12.9 produces this output:

         1  A
         2  B
         3  C
         4  D
         5  E
         6  F
         7  G
         8  H
         9  I
        10  J
        11  K
        12  L

         1  A
         2  B
         3  C
         4  D
         5  F
         6  G
         7  H
         8  I
         9  J
        10  K
        11  L

         1  A
         2  B
         3  C
         4  D
         5  F
         6  J
         7  K
         8  L

         1  A
         2  F
         3  J
         4  K
         5  L

         1  A
         2  K
         3  L

sy-subrc=     0  sy-tabix=          2

         1  A
         2  L

Like inserts, deletes inside of a loop at it do not affect the internal table immediately, but instead become effective on the next loop pass. When deleting a row after the current row, the table is re-indexed at the endloop, sy-tabix is incremented, and the next loop pass processes the row pointed to by sy-tabix. For example, suppose you are in the third loop pass and you delete row 4. When endloop is executed, the row is deleted, row 5 becomes row 4, and so on. sy-tabix is incremented by 1 and the next loop pass processes the next record.

If, when inside a loop, you delete a row before the current row, the table is again re-indexed at the endloop. This time, however, sy-tabix is incremented by 1 minus the number or rows deleted before the current row. The next time through the loop, the row following the current row is processed. Suppose, for example, in the third loop pass you delete row 3. At the endloop, row 4 becomes row 3, and so on. sy-tabix is incremented by 0, giving 3. Row 4 was re-indexed to 3, so it is processed on the next loop pass.

Creating Top 10 Lists Using append sorted by

Imagine that you are asked to create a report of the top 10 sales representatives in your company. Assuming you have a way of obtaining the total sales for each rep, you could do one of the following:

This seems like a logical way to proceed. However, using the append sorted by statement often can produce the same result and be twice as efficient.

Syntax for the append sorted by Statement

The following is the syntax for the append sorted by statement.

append [wa to] it sorted by c.

where:

The following points apply:

The append sorted by statement takes a row from the work area and inserts it into the internal table at the point where it belongs in the sort order. It has two unusual properties:

The net effect is a "top n list," where n is the number on the occurs clause.

With each append, the system searches the existing table contents to determine where the new row fits. The sort order is by c descending. If there are fewer rows in the internal table than specified by n on the occurs clause, the row is as per the sort order. If there are n rows in the internal table, the row is inserted as per the sort order and the last row is discarded. If the value in c already exists in the internal table, the new row is always appended after existing rows that have the same value. Therefore, if occurs is 3 and row 3 contains 'X' in c, a new row having 'X' in c will not be appended.

Listing 12.10 shows a sample program that creates a list of the top three sales reps.


Listing 12.10  Using append sorted by to Find the Top Three Sales Reps

 1  report ztx1210.
 2  data: begin of it occurs 3,
 3            sales type p decimals 2,
 4            name(10),
 5            end of it.
 6 
 7  it-sales     = 100.
 8  it-name      = 'Jack'.
 9  append it sorted by sales.
10
11 it-sales     = 50.
12 it-name      = 'Jim'.
13 append it sorted by sales.
14
15 it-sales     = 150.
16 it-name      = 'Jane'.
17 append it sorted by sales.
18
19 it-sales     = 75.
20 it-name      = 'George'.
21 append it sorted by sales.
22
23 it-sales     = 200.
24 it-name      = 'Gina'.
25 append it sorted by sales.
26
27 it-sales     = 100.
28 it-name      = 'Jeff'.
29 append it sorted by sales.
30
31 loop at it.
32     write: / it-sales, it-name.
33     endloop.

The code in Listing 12.10 produces this output:

          200.00  Gina 
          150.00  Jane 
          100.00  Jack 

Do not mix append sorted by with any other statements that add data to an internal table (such as insert or append). If you fill it with append sorted by, that should be the only statement you use. Mixing these statements will result in unpredictable behavior.

TIP
append sorted by is more efficient when you are appending one row at a time to an internal table. If you already have the data in a database table and merely want to find the top 10 values, it is more efficient to insert the rows using an array operation and then sort. (For information on array operations, see Day 13, "Advanced Internal Tables: Part 2.")

Filling an Internal Table Using collect

Using the collect statement, you can create totals within an internal table as you fill it.

Syntax for the collect Statement

The following is the syntax for the collect statement.

collect [wa into] it.

where:

The following points apply:

When collect is executed, the system forms a key from the default key fields in the work area. The default key fields are the character fields (types c, n, d, t, and x). Therefore the key is composed of the values from all fields of type c, n, d, t, and x. It doesn't matter if they are beside one another or separated from each other by other fields.

The system then searches the body of the internal table for a row that has the same key as the key in the work area. If it doesn't find one, the row is appended to the end of the table. If it does find one, the numeric fields (types i, p, and f) in the work area are added to the corresponding fields in the found row. Listing 12.11 illustrates this concept.


Listing 12.11  collect Combines Rows as They Are Added to an Internal Table

1  report ztx1211.
2  data: begin of it occurs 10,
3            date type d,                    "    part of default key
4            tot_sales type p decimals 2,    "not part of default key
 5            name(10),                       "    part of default key
 6            num_sales type i value 1,       "not part of default key
 7            end of it.
 8 
 9  it-date      = '19980101'.
10 it-tot_sales  = 100.
11 it-name       = 'Jack'.
12 collect it.
13
14 it-date       = '19980101'.
15 it-tot_sales  = 200.
16 it-name       = 'Jim'.
17 collect it.
18
19 it-date       = '19980101'.
20 it-tot_sales  = 300.
21 it-name       = 'Jack'.
22 collect it.
23
24 it-date       = '19980101'.
25 it-tot_sales  = 400.
26 it-name       = 'Jack'.
27 collect it.
28
29 it-date       = '19980101'.
30 it-tot_sales  = 500.
31 it-name       = 'Jim'.
32 collect it.
33
34 it-date       = '19980101'.
35 it-tot_sales  = 600.
36 it-name       = 'Jane'.
37 collect it.
38
39 it-date       = '19980102'.
40 it-tot_sales  = 700.
41 it-name       = 'Jack'.
42 collect it.
43
44 loop at it.
45     write: / it-date, it-tot_sales, it-name, it-num_sales.
46     endloop.

The code in Listing 12.11 produces this output:

19980101           800.00  Jack                3
19980101           700.00  Jim                 2
19980101           600.00  Jane                1
19980102           700.00  Jack                1

CAUTION
If you use collect to add rows to an internal table, all rows should be added using collect. You should not combine collect with append or any other statement that adds data to an internal table. The results will be unpredictable. The only other statement that you can use to modify the contents of an internal table filled via collect is modify ... transporting f1 f2 ..., where f1 and f2 are numeric fields only (non-default key fields).

Summary

DO
DON'T
DO use the free statement at the end of your program for all internal tables. This explicitly frees memory that will no longer be used while the user views the output. DON'T append or insert lines one at a time if they can processed as a group using insert lines of or append lines of.
DO use the table body operator to test for the existence of data.  
DO use the append sorted by statement when creating top 10 lists, unless the list already exists and only needs to be sorted.  

Q&A

Q
In this chapter you have covered so many ways to accomplish similar tasks. In ABAP/4 there always seems to be many ways to do the same thing. I'm just learning. I can only remember so many ways of doing something. Why not just show me the best way and forget the rest?
A
I appreciate your concern. Wherever possible I leave out archaic, inefficient, rarely used, and duplicate methods. But there are two very good reasons for including the variations I have described here: 1) efficiency and 2) understanding of existing code. Due to the amount of data that resides in an R/3 system, efficiency is a primary concern in ABAP/4 programs. You should strive to use the most efficient form of each statement in a given situation. This can result in drastic performance improvements not only for your programs, but also for the entire system. It is common to have to rewrite code after it reaches production because it impacts system performance. As for the second point, programmers often spend more time reading existing code than creating new code, so you need to understand the subtle variations of these statements. They are used in abundance in SAP code. If you don't understand SAP's code, you won't be able to understand how the data got to its present state or how the output is arrived at.

Workshop

The Workshop provides you two ways for you to affirm what you've learned in this chapter. The Quiz section poses questions to help you solidify your understanding of the material covered and the Exercise section provides you with experience in using what you have learned. You can find answers to the quiz questions and exercises in Appendix B, "Answers to Quiz Questions and Exercises."

Quiz

  1. If I modify the value of sy-tabix inside a loop, does this change the current row? For example, would the insert, modify, and delete statements operate on the row in the work area or the row indicated by sy-tabix?
  2. When would I use the value of sy-toccu? Why would I need to know the value of the occurs clause at runtime?

Exercise 1

Read the contents of ztxlfa1 into an internal table (use select into table). Then modify the land1 column so that the third row contains 'US' (use modify transporting where). Also modify the regions, changing all MA to TX (use modify transporting where).