📄 ch10.htm
字号:
<UL>
<LI><TT><I>v1</I></TT> is a variable,
literal, or constant.
<LI><TT><I>s</I></TT> is a field
string having the components <TT><I>c1</I></TT>
and <TT><I>c2</I></TT>.
<LI><TT><I>f1</I></TT> is a variable.
The components of <TT><I>s</I></TT>
must be able to be converted to the data type and length of <TT><I>f1</I></TT>.
<LI><TT>...</TT> represents any number of complete <TT>varying</TT>
clauses.
<LI><TT><I>---</I></TT> represents
any number of lines of code.
</UL>
<P>
The following points apply:
<UL>
<LI><TT>do</TT> loops can be nested an unlimited number of times.
<LI><TT>exit</TT> prevents further <I>loop</I> processing and
exits immediately out of the current loop. It does not terminate
the program when inside of a <TT>do</TT> loop. Processing continues
at the next executable statement after the <TT>enddo</TT>.
<LI>You can create an infinite loop by coding <TT>do</TT> without
any additions. In that situation, use <TT>exit</TT> within the
loop to terminate loop processing.
<LI>Modifying the value of <TT><I>v1</I></TT>
within the loop does not affect loop processing.
</UL>
<P>
Within the loop, <TT>sy-index</TT> contains the current iteration
number. For example, the first time through the loop, <TT>sy-index</TT>
will be 1. The second time through, <TT>sy-index</TT> will be
2, and so on. After <TT>enddo</TT>, <TT>sy-index</TT> contains
the value it had before entering the loop. With nested <TT>do</TT>
loops, <TT>sy-index</TT> contains the iteration number of the
loop in which it is used (see Listing 10.7).
<P>
<IMG SRC="../button/input.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/input.gif">
<HR>
<P>
<B>Listing 10.7 </B><TT><B>SY-INDEX</B></TT><B>
Contains the Current Iteration Number<BR>
</B>
<BLOCKQUOTE>
<PRE>
1 report ztx1007.
2 sy-index = 99.
3 write: / 'before loop, sy-index =', sy-index, / ''.
4 do 5 times.
5 write sy-index.
6 enddo.
7 write: / 'after loop, sy-index =', sy-index, / ''.
8
9 do 4 times.
10 write: / 'outer loop, sy-index =', sy-index.
11 do 3 times.
12 write: / ' inner loop, sy-index =', sy-index.
13 enddo.
14 enddo.
15
16 write: / ''. "new line
17 do 10 times.
18 write sy-index.
19 if sy-index = 3.
20 exit.
21 endif.
22 enddo.
</PRE>
</BLOCKQUOTE>
<HR>
<P>
<IMG SRC="../button/output.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/output.gif">
<P>
The code in Listing 10.7 produces this output:
<BLOCKQUOTE>
<PRE>
before loop, sy-index = 99
1 2 3 4 5
after loop, sy-index = 99
outer loop, sy-index = 1
inner loop, sy-index = 1
inner loop, sy-index = 2
inner loop, sy-index = 3
outer loop, sy-index = 2
inner loop, sy-index = 1
inner loop, sy-index = 2
inner loop, sy-index = 3
outer loop, sy-index = 3
inner loop, sy-index = 1
inner loop, sy-index = 2
inner loop, sy-index = 3
outer loop, sy-index = 4
inner loop, sy-index = 1
inner loop, sy-index = 2
inner loop, sy-index = 3
1 2 3<BR>
</PRE>
</BLOCKQUOTE>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1>
<TR VALIGN=TOP><TD WIDTH=600><B>TIP</B></TD></TR>
<TR VALIGN=TOP><TD WIDTH=600>
<BLOCKQUOTE>
On rare occasions the need arises to "kill time" in a program. You should not use an empty loop to accomplish this; you will burn up CPU needlessly if you do. Instead, you should call the function module <TT>rzl_sleep</TT>.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
Changes made to the value of <TT>sy-index</TT> do not affect loop
control. For example, if you code <TT>do 10 times</TT> and during
the very first loop pass set the value of <TT>sy-index</TT> to
11, it will maintain that value until the <TT>enddo</TT> statement
is executed. At that point, the value will be reset to 1, then
incremented to 2, and the loop will continue processing as if
you had not changed it at all.
<H3><A NAME="TerminatinganEndlessLoop">
Terminating an Endless Loop</A></H3>
<P>
There will be occasions when a program you run will loop endlessly.
Listing 10.8 shows such a program.
<P>
<IMG SRC="../button/input.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/input.gif">
<HR>
<P>
<B>Listing 10.8 An Endless Loop Can Be Frustrating
If You Don't Know How to Break Out<BR>
</B>
<BLOCKQUOTE>
<PRE>
1 report ztx1008.
2 do.
3 write sy-index.
4 if sy-index = 0.
5 exit.
6 endif.
7 enddo.
</PRE>
</BLOCKQUOTE>
<HR>
<P>
If you run this program, it will loop infinitely and that session
will be clocked. Ending the SAPGUI task or even rebooting will
not interrupt the program because it runs in a work process on
the application server, not on your PC. If you reboot and then
log on again, you will find that (if you were in the editor when
you rebooted) you will not be able to even edit that program.
Your logon session is still "out there" on the application
server and it will still have the lock on your source code. After
about five or ten minutes, your logon session will time out, and
you will be able to edit your source code once again. However,
the program could still be running in the work process, which
slows the system down. Eventually, your program will consume the
maximum amount of CPU allowed in your configuration and the work
process will restart itself.
<P>
To terminate an endless loop, you must have at least two sessions
open created via the menu path System->Create Session. You
must start them <I>before</I> running your program. If you are
in an infinite loop and do not have another session running, it
is too late. Sessions created by logging on again will not work.
<P>
<img src="../button/screencam.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/screencam.gif">
<P>
Start the ScreenCam "How to Terminate an Endless Loop"
now.
<P>
To terminate an endless loop:
<OL>
<LI>When you first log on, chose the menu path System->Create
Session.
<LI>Minimize your new session and leave it in the background until
you need it. You can now test programs with impunity.
<LI>Now run a program that contains an endless loop, such as <TT>ztx1008</TT>.
You see an hourglass when your pointer is over the window. Notice
your session number in the status bar at the bottom of the window.
<LI>Hold down the Alt key and press Tab successive times until
the focus rests on the R3 icon representing your other session.
<LI>Let go of the Alt key.
<LI>Type <B>/o</B> in the Command field on the Standard toolbar.
<LI>Press the Enter key. The Overview Of Sessions dialog box appears.
It contains a list of your sessions. To the left of each is the
associated session number.
<LI>Find the session numer of the looping session, and click once
on that line.
<LI>Press the Debugging button.
<LI>Switch back to the looping session using Alt+Tab. That session
will now be stopped in the debugger. You can debug from here,
or press the Exit button on the Application toolbar to end the
program.
</OL>
<P>
If the debugger did not show up and the session is still looping,
you can end the entire session by repeating the procedure from
step 6. Then, in step 9, instead of pressing the Debugging button,
press the End Session button. This terminates the program <I>and</I>
the session containing it. You will need to open another session
to replace the one you terminated.
<H3><A NAME="UsingtheTTFONTSIZEvaryingFONTTTFONTSIZEAdditionFONT">
Using the <TT><FONT SIZE=4>varying</FONT></TT><FONT SIZE=4>
Addition</FONT></A></H3>
<P>
Use the addition <TT>varying</TT> to obtain components of a field
string in sequence. <TT>next</TT> establishes a distance (in bytes)
between two components per iteration. The receiving component
establishes the number of bytes to read from each component. This
is best explained by example, as shown in Listing 10.9.
<P>
<IMG SRC="../button/input.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/input.gif">
<HR>
<P>
<B>Listing 10.9 The Addition </B><TT><B>VARYING</B></TT><B>
Returns the Components of a Field String in Sequence<BR>
</B>
<BLOCKQUOTE>
<PRE>
1 report ztx1009.
2 data: f1,
3 begin of s,
4 c1 value 'A',
5 c2 value 'B',
6 c3 value 'C',
7 c4 value 'D',
8 c5 value 'E',
9 c6 value 'F',
10 end of s.
11
12 write / ''.
13 do 6 times varying f1 from s-c1 next s-c2.
14 write f1.
15 enddo.
16
17 write / ''.
18 do 3 times varying f1 from s-c1 next s-c3.
19 write f1.
20 enddo.
</PRE>
</BLOCKQUOTE>
<HR>
<P>
<IMG SRC="../button/output.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/output.gif">
<P>
The code in Listing 10.9 produces this output:
<BLOCKQUOTE>
<PRE>
A B C D E F
A C E
</PRE>
</BLOCKQUOTE>
<P>
<IMG SRC="../button/analysis.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/analysis.gif">
<P>
On line 13, <TT>next</TT> establishes a distance per iteration
equal to the distance between <TT>c1</TT> and <TT>c2</TT>. The
length of <TT>f1</TT> determines the number of bytes to read from
each component. <TT>Do</TT> then begins at <TT>s-c1</TT>, and
assigns its value to <TT>f1</TT>. On successive loop passes, the
previously established distance is added to the address of the
current component, causing successive values to be assigned from
<TT>s</TT> to <TT>f1</TT>.
<P>
All components of <TT>s</TT> accessed by the <TT>do</TT> loop
must be separated by exactly the same number of bytes. Data conversion
is not performed on assignment to <TT>f1</TT>.<P>
<CENTER>
<TABLE BORDERCOLOR=#000000 BORDER=1>
<TR VALIGN=TOP><TD WIDTH=600><B>CAUTION</B></TD></TR>
<TR VALIGN=TOP><TD WIDTH=600>
<BLOCKQUOTE>
It is possible to read past the end of the structure, but doing so can result in unpredictable behavior and even in program termination. You must either specify the addition <TT>times </TT>to limit the number of loop passes or use an <TT>exit </TT>statement to leave the loop before reading past the end of the field string.
</BLOCKQUOTE>
</TD></TR>
</TABLE>
</CENTER>
<P>
<P>
Some tables in R/3 are not completely normalized. Instead of having
multiple records, a single record might contain a series of fields
repeated in succession. You can use <TT>varying</TT> to retrieve
these values in sequence.
<P>
For example, table <TT>lfc1</TT> contains Vendor Master transaction
figures. Fields <TT>umNNs</TT>, <TT>umNNh</TT>, and <TT>umNNu</TT>
contain the total debit and credit postings for a month and the
sales in the posting period. This group of fields is repeated
16 times for each record in this table (<TT>NN</TT> is a sequential
number from <TT>01</TT> to <TT>16</TT>). Table <TT>knc1</TT> contains
a similar sequence of fields. In another example, table <TT>mvke</TT>
contains, within <TT>include envke</TT>, 10 fields for product
attributes: <TT>prat1</TT> through <TT>prata</TT>. They are side
by side, making them an equal distance apart, and thus able to
be accessed with <TT>varying</TT>.
<P>
A more complex example of the use of <TT>varying</TT> is shown
in Listing 10.10.
<P>
<IMG SRC="../button/input.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/input.gif">
<HR>
<P>
<B>Listing 10.10 The Addition </B><TT><B>VARYING</B></TT><B>
Can Appear More Than Once on the </B><TT><B>DO</B></TT><B>
Statement<BR>
</B>
<BLOCKQUOTE>
<PRE>
1 report ztx1010.
2 data: f1 type i,
3 f2 type i,
4 tot1 type i,
5 tot2 type i,
6 begin of s,
7 c1 type i value 1,
8 c2 type i value 2,
9 c3 type i value 3,
10 c4 type i value 4,
11 c5 type i value 5,
12 c6 type i value 6,
13 end of s.
14
15 do 3 times varying f1 from s-c1 next s-c3
16 varying f2 from s-c2 next s-c4.
17 write: / f1, f2.
18 add: f1 TO tot1,
19 f2 to tot2.
20 enddo.
21 write: / '---------- -----------',
22 / tot1, tot2.
</PRE>
</BLOCKQUOTE>
<HR>
<P>
<IMG SRC="../button/output.gif" tppabs="http://pbs.mcp.com/ebooks/0672312174/button/output.gif">
<P>
The code in Listing 10.10 produces this output:
<BLOCKQUOTE>
<PRE>
1 2
3 4
5 6
---------- -----------
9 12
</PRE>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -