📄 ch13.htm
字号:
<PRE>
total: A 3 30
1 10
2 20
total: B 7 70
3 30
4 40
</PRE>
</BLOCKQUOTE>
<P>
<IMG SRC="../button/analysis.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/analysis.gif">
<UL>
<LI>Line 13 sorts <TT>it</TT> by <TT>f1</TT> ascending. The contents
after sorting appear as shown in Figure 13.9.
<LI>The first time through the loop, the code between lines 15
and 18 is executed. The control level contains the value <TT>'A'</TT>.
<LI>Before line 16 is executed, the work area fields to the right
of the control level contain zeros. The <TT>sum</TT> statement
finds all adjacent rows that have an <TT>'A'</TT> in <TT>f1</TT>.
It sums the numeric columns to the right of the control level
and places the results in the work area (see Figure 13.9).<BR>
<A HREF="javascript:popUp('f13-9.gif')"><B>Figure 13.9 :</B> <I>This figure illustrates what occurs in
Listing 13.11. The first time through the loop the control break
is triggered and the sum statement is executed. All rows having
the same value as the control level are found and the numeric
fields to the right of the control level are summed up into the
work area</I>.</A>
<LI>In the second iteration of the loop, <TT>at new</TT> is not
triggered.
<LI>In the third loop iteration, <TT>f1</TT> contains <TT>'B'</TT>
and <TT>at new</TT> (line 15) is triggered.
<LI>Before line 16 is executed, the work area fields to the right
of the control level contain zeros. The <TT>sum</TT> statement
finds all adjacent rows that have a <TT>'B'</TT> in <TT>f1</TT>.
It sums the numeric columns to the right of the control level
and places the results in the work area (see Figure 13.10).<BR>
<A HREF="javascript:popUp('f13-10.gif')"><B>Figure 13.10:</B> <I>This figure shows what transpires the
second time the control break is triggered and the sum statement
is executed</I>.</A>
</UL>
<P>
<CENTER>
<TABLE BORDER=1>
<TR VALIGN=TOP><TD WIDTH=600><B>TIP</B></TD></TR>
<TR VALIGN=TOP><TD WIDTH=600>
<BLOCKQUOTE>
Summing can result in overflow because the total is placed into a field of the same length. Overflow causes a short dump with the error <TT>SUM_OVERFLOW</TT>. When using <TT>sum</TT>, avoid overflow by increasing the length of numeric fields before populating the internal table.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<H3><A NAME="UsingtheonchangeofStatement">
Using the on change of Statement</A></H3>
<P>
Another statement you can use to perform control break processing
is <TT>on change of</TT>. It behaves in a manner similar to <TT>at
new</TT>.
<H4>Syntax for the on change of Statement</H4>
<P>
The following is the syntax for the <TT>on change of</TT> statement.
<BLOCKQUOTE>
<PRE>
on change of <I>v1</I> [or <I>v2 </I>. . .].
---
[else.
---]
endon.
</PRE>
</BLOCKQUOTE>
<P>
where:
<UL>
<LI><TT><I>v1</I></TT> and <TT><I>v2</I></TT>
are variable or field string names.
<LI><TT>. . .</TT> indicates that any number of <TT>or</TT> conditions
might follow.
<LI><TT>---</TT> represents any number of lines of code.
</UL>
<P>
The following points apply:
<UL>
<LI>If the value of any of the variables (<TT><I>v1</I></TT>,
<TT><I>v2</I></TT>, and so on)
changes from one test to the next, the statements following <TT>on
change of</TT> are executed.
<LI>If no change is detected and <TT>else</TT> is specified, the
statements following <TT>else</TT> are executed.
</UL>
<P>
<TT>on change of</TT> differs from <TT>at new</TT> in the following
respects:
<UL>
<LI>It can be used in any loop construct, not just <TT>loop at</TT>.
For example, it can be used within <TT>select</TT> and <TT>endselect</TT>,
<TT>do</TT> and <TT>enddo</TT>, or <TT>while</TT> and <TT>endwhile</TT>,
as well as inside <TT>get</TT> events.
<LI>A single <TT>on change of</TT> can be triggered by a change
within one or more fields named after <TT>of</TT> and separated
by <TT>or</TT>. These fields can be elementary fields or field
strings. If you are within a loop, these fields do not have to
belong to the loop.
<LI>When used within a loop, a change in a field to the left of
the control level does not trigger a control break.
<LI>When used within a loop, fields to the right still contain
their original values; they are not changed to contain zeros or
asterisks.
<LI>You can use <TT>else</TT> between <TT>on change of</TT> and
<TT>endon</TT>.
<LI>You can use it with <TT>loop at <I>it</I>
where . . .</TT>.
<LI>You can use <TT>sum</TT> with <TT>on change of</TT>. It sums
all numeric fields except the one(s) named after <TT>of</TT>.
<LI>Any values changed within <TT>on change of</TT> remain changed
after <TT>endon</TT>. The contents of the header line are not
restored as they are for <TT>at</TT> and <TT>endat</TT>.
</UL>
<H4>Behind the Scenes of on change of</H4>
<P>
When a loop begins execution, the system creates a global auxiliary
field for each field named in an <TT>on change of</TT> statement
contained by the loop. On creation, these fields are given default
initial values (blanks or zeros). They are freed when the loop
ends.
<P>
Each time <TT>on change of</TT> is executed, the contents of its
fields are compared with the contents of the global auxiliary
fields. If they are different, the <TT>on change of</TT> is triggered
and the auxiliary fields are updated with the new values. If they
are the same, the code within <TT>on change of</TT> is not executed.
<P>
<CENTER>
<TABLE BORDER=1>
<TR VALIGN=TOP><TD WIDTH=600><B>NOTE</B></TD></TR>
<TR VALIGN=TOP><TD WIDTH=600>
<BLOCKQUOTE>
Because global auxiliary fields do not exist outside a loop, you cannot use <TT>on change of</TT> outside of a loop.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
This concept is graphically illustrated in Figures 13.11 through
13.16.
<P>
<A HREF="javascript:popUp('f13-11.gif')"><B>Figure 13.11:</B> <I>This is the first time though a loop using
on change of</I>.</A>
<P>
<A HREF="javascript:popUp('f13-12.gif')"><B>Figure 13.12:</B> <I>When on change of is triggered, the auxiliary
field is updated</I>.</A>
<P>
<A HREF="javascript:popUp('f13-13.gif')"><B>Figure 13.13:</B> <I>This is the second loop pass. The auxiliary
field contents match and on change of is not triggered</I>.</A>
<P>
<A HREF="javascript:popUp('f13-14.gif')"><B>Figure 13.14:</B> <I>This is the third loop pass. on change
of is triggered</I>.</A>
<P>
<A HREF="javascript:popUp('f13-15.gif')"><B>Figure 13.15:</B> <I>Here the auxiliary field is updated</I>.</A>
<P>
<A HREF="javascript:popUp('f13-16.gif')"><B>Figure 13.16:</B> <I>This is the fourth loop pass. on change
of is not triggered</I>.</A>
<H4>Using on change of</H4>
<P>
Listing 13.12 illustrates the use of <TT>on change of</TT>.
<P>
<IMG SRC="../button/input.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/input.gif">
<HR>
<P>
<B>Listing 13.12 Using on change of in Two Different
Ways: Inside of loop at and Inside of select<BR>
</B>
<BLOCKQUOTE>
<PRE>
1 report ztx1312.
2 tables ztxlfa1.
3 data: begin of it occurs 4,
4 f1 type i,
5 f2,
6 f3 type i,
7 f4,
8 end of it.
9
10 it-f1 = 1. it-f2 = 'A'. it-f3 = 11. it-f4 = 'W'. append it.
11 it-f1 = 3. it-f2 = 'A'. it-f3 = 22. it-f4 = 'X'. append it.
12 it-f1 = 1. it-f2 = 'A'. it-f3 = 33. it-f4 = 'Y'. append it.
13 it-f1 = 2. it-f2 = 'A'. it-f3 = 44. it-f4 = 'Z'. append it.
14
15 loop at it.
16 on change of it-f2.
17 write: / it-f1, it-f2, it-f3, it-f4.
18 endon.
19 endloop.
20 write: / 'End of loop'.
21
22 * executing the same code again - the aux field still contains 'A'
23 loop at it.
24 at first.
25 write: / 'Looping without a reset...'.
26 endat.
27 on change of it-f2.
28 write: / it-f1, it-f2, it-f3, it-f4.
29 else.
30 write: / 'on change of not triggered for row', sy-tabix.
31 endon.
32 endloop.
33 write: / 'End of loop'.
34
35 *reset the aux field to blanks
36 clear it-f2.
37 on change of it-f2.
38 endon.
39 loop at it.
40 at first.
41 write: / 'Looping after reset...'.
42 endat.
43 on change of it-f2.
44 write: / it-f1, it-f2, it-f3, it-f4.
45 endon.
46 endloop.
47 write: / 'End of loop'.
48 free it.
49
50 select * from ztxlfa1 where land1 = 'US'.
51 on change of ztxlfa1-land1.
52 write: / 'land1=', ztxlfa1-land1.
53 endon.
54 endselect.
55 write: / 'End of select'.
56
57 *executing the same select again without a reset works find
58 select * from ztxlfa1 where land1 = 'US'.
59 on change of ztxlfa1-land1.
60 write: / 'land1=', ztxlfa1-land1.
61 endon.
62 endselect.
63 write: / 'End of select'.
</PRE>
</BLOCKQUOTE>
<HR>
<P>
<IMG SRC="../button/output.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/output.gif">
<P>
In a 3.0F environment and above, the code in Listing 13.12 produces
this output:
<BLOCKQUOTE>
<PRE>
1 A 11 W
End of loop
Looping without a reset...
on change of not triggered for row 2
on change of not triggered for row 3
on change of not triggered for row 4
End of loop
Looping after reset...
1 A 11 W
End of loop
land1= US
End of select
land1= US
End of select
</PRE>
</BLOCKQUOTE>
<P>
<IMG SRC="../button/analysis.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/analysis.gif">
<UL>
<LI>Lines 10 through 13 seed the internal table with data. <TT>it-f2</TT>
contains value <TT>'A'</TT> in all four rows.
<LI>Line 16 writes out each row as it is processed.
<LI>Lines 17, 20, 23, and 26 are triggered the first time through
the loop. This happens because the auxiliary fields contain zeros
or blanks, so they differ from the values in the first row. The
first row values are copied to the auxiliary fields and the values
are written out by the <TT>write</TT> statements.
<LI>Line 20 is not triggered again because on all subsequent loop
passes, the value of <TT>it-f2</TT> is <TT>'A'</TT> and the global
auxiliary field also contains <TT>'A'</TT>. Notice that a change
in the value to the left of <TT>f2</TT> does not trigger <TT>on
change of</TT> as it does with <TT>at new</TT>.
<LI>The internal table is not used after line 31, so here <TT>it</TT>
is freed. This deletes all rows and releases the memory.
<LI>Line 33 selects all rows from <TT>ztxlfa1</TT> in <TT>land1</TT>
order.
<LI>Although this <TT>select</TT> returns 23 rows, as shown by
the last line of output, only five unique values of <TT>land1</TT>
exist and are written out.
</UL>
<H4>Using the Hidden Danger in on change of</H4>
<P>
The first time through a loop, the global auxiliary field is created
with initial values (blanks or zeros). If the first value in a
loop happens to be blank or zero, <TT>on change of</TT> will not
be triggered. Listing 13.13 illustrates this problem and offers
a solution.
<P>
<IMG SRC="../button/input.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/input.gif">
<HR>
<P>
<B>Listing 13.13 The First Row of Loop #1 Does Not
Trigger on change of<BR>
</B>
<BLOCKQUOTE>
<PRE>
1 report ztx1313.
2 data: begin of it occurs 4,
3 f1 type i,
4 end of it.
5
6 it-f1 = 0. append it.
7 it-f1 = 3. append it.
8 it-f1 = 1. append it.
9 it-f1 = 2. append it.
10
11 loop at it. "loop #1
12 write: / '==new row==', 12 it-f1.
13 on change of it-f1.
14 write: / 'f1 changed:', 12 it-f1.
15 endon.
16 endloop.
17
18 skip.
19 loop at it. "loop #2
20 write: / '==new row==', 12 it-f1.
21 on change of it-f1.
22 write: / 'f1 changed:', 12 it-f1.
23 else.
24 if sy-tabix = 1.
25 write: / 'f1 changed:', 12 it-f1.
26 endif.
27 endon.
28 endloop.
29 free it.
</PRE>
</BLOCKQUOTE>
<HR>
<P>
<IMG SRC="../button/output.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/output.gif">
<P>
The code in Listing 13.13 produces this output:
<BLOCKQUOTE>
<PRE>
==new row== 0
==new row== 3
f1 changed: 3
==new row== 1
f1 changed: 1
==new row== 2
f1 changed: 2
==new row== 0
f1 changed: 0
==new row== 3
f1 changed: 3
==new row== 1
f1 changed: 1
==new row== 2
f1 changed: 2
</PRE>
</BLOCKQUOTE>
<P>
<IMG SRC="../button/analysis.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/analysis.gif">
<UL>
<LI>Lines 6 though 9 fill the internal table with four rows. The
value of <TT>it-f1</TT> in the first row is zero.
<LI>On line 13, the first loop pass does not trigger the <TT>on
change of</TT> because the global auxiliary field contains zero.
<LI>Lines 23 and 24 have been added to loop #2 to detect the error.
Notice that <TT>at first</TT> cannot be used to det
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -