Sams Teach Yourself ABAP/4® in 21 Days


Day 9

Assignments, Conversions, and Calculations


Chapter Objectives

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

Before Proceeding

Programs in this and the following chapters use input and output formats that are set in the user defaults and can be different for each user. Before proceeding, it is a good idea to set your user defaults to match those in this book so that your output matches the output listings in this book.

Please set your user defaults now by following this procedure:

  1. If you are currently in the R/3 system, save all your work now.
  2. From any screen, choose the menu path System->User Profile->User Defaults. The Maintain User: Defaults screen is displayed.
  3. In the Date Format group box, choose the YYYY/MM/DD radio button.
  4. In the Decimal Notation group box, choose the Period radio button.
  5. Press the Save button on the Application toolbar. At the bottom of the window, the message Values for user xxxxx saved is displayed. Changes to your user profile are not effective until the next time you log on.
  6. Choose the menu path System->Log Off. The Log Off dialog box is displayed.
  7. Press the Yes button. You are logged off of the system.

Your new user defaults will be in effect the next time you log on.

Working with System Variables

There are 176 system variables available within every ABAP/4 program. You do not have to define them; they are automatically defined and are always available.

To display a list of system variables, display the DDIC structure syst. You can display it by using the Dictionary: Initial Screen, or by double-clicking on the name of any system variable in your program. The first page of syst is shown in Figure 9.1.

Figure 9.1 : This is the structure syst. It contains the definitions for all system variables. The Column Right; Next . . . button scrolls right one column at a time, causing the entire length of the Short Text to scroll into view.

In Figure 9.1, the field names appear in the first column and the descriptions are on the right in the Short Text column. To view the entire description, scroll to the right by clicking on the Column Right; Next . . . button at the bottom of the screen.

To find a field by name, press the Find button on the Standard toolbar. The Find Field screen will appear, asking for the name of the field that you want to find.

The alias for syst is sy (pronounced sigh). In your code, you can use either name. For example, you can code either sy-datum or syst-datum; they are exactly equivalent. Most programmers use sy. Table 9.1 contains a short list of commonly used system variables. Additional variables are introduced throughout the book.

Table 9.1  Commonly Used System Variables
Name
Description
sy-datum
Current date
sy-uzeit
Current time
sy-uname
Current user id
sy-subrc
Last return code
sy-mandt
Logon client
sy-pagno
Current output page number
sy-colno
Current output column number
sy-linno
Current output list line number
sy-vline
Vertical line
sy-uline
Horizontal line
sy-repid
Current report name
sy-cprog
Main program name
sy-tcode
Current transaction code
sy-dbcnt
Within a select, contains the current iteration counter. After the endselect, contains number of rows that match the where clause.

Listing 9.1 shows a sample program that uses system variables.


Listing 9.1  Using Basic System Variables

 1 report ztx0901.
 2 tables ztxlfa1.
 3 parameters `land1 like ztxlfa1-land1 obligatory default 'US'.
 4 write: / 'Current date:', sy-datum,
 5        / 'Current time:', sy-uzeit,
 6        / 'Current user:', sy-uname,
 7        / 'Vendors having country code', `land1,
 8        /.
 9 select * from ztxlfa1
10     where land1 = `land1
11     order by lifnr.
12     write: / sy-dbcnt, ztxlfa1-lifnr.
13     endselect.
14 write: / sy-dbcnt, 'records found'.
15 if sy-subrc <> 0.
16     write: / 'No vendors exist for country', 'land1.
17     endif.

The code in Listing 9.1 produces this output:

Current date: 1998/02/22
Current time: 14:38:24
Current user: KENGREENWOOD
Vendors having country code US

         1  1040
         2  1080
         3  1090
         4  2000
         5  V1
         6  V2
         7  V3
         8  V4
         9  V5
        10  V7
        10  records found

Finding System Variables

Suppose you need to write a program that, given a country code as an input parameter, writes out the country description from table ztxt005t in the user's current logon language. As you might recall, ztxt005t is a text table containing country code descriptions in multiple languages. The primary key is mandt, spras (language), and land1. A sample solution is shown in Listing 9.2, but it is missing one crucial piece of information on line 5: the value of the current logon language.

Listing 9.2 is missing a variable at the position indicated by the question mark. When working with ABAP/4, you are often faced with the challenge of finding variables containing the information you need.


Listing 9.2  A Sample Program with a sy Variable Missing

 1 report ztx0902.
 2 tables ztxt005t.
 3 parameters `land1 like ztxlfa1-land1 obligatory default 'US'.
 4 select single * from ztxt005t
 5     where spras = ?             "current logon language
 6     and   land1 = `land1.
 7 if sy-subrc = 0.
 8     write: 'Description:', ztxt005t-landx.
 9 else.
10     write: 'No description exists for', `land1.
11     endif.

The current logon language is available from a system variable. Unfortunately, to use the Find button on the Application toolbar you need to know the name of the field. You do not know the name of the field, so the Find button is of little use. Instead, use the following procedure to search the descriptions of the syst structure.

TIP
This procedure is very handy because it can be used to search the descrip-tions of any structure or table.

Start the ScreenCam "How to Search the Descriptions of a Structure or Table" now.

To search the descriptions of a structure or table:

  1. Begin at the Dictionary: Table/Structure: Display Fields screen.
  2. Choose the menu path Table->Print. The Print Table Manual screen is displayed. Here you specify which details you want to see.
  3. Tickmark all fields and press the Continue button. The Print: screen is displayed.
  4. If the Output Device field is blank, position your cursor in the field, press the down arrow, and choose any output device. (It doesn't matter which device you choose; it won't be used.)
  5. Press the Print Preview button at the bottom of the screen. The Print Preview for xxxx Page 00001 of nnnnn screen is displayed.
  6. Choose the menu path Goto->List Display. The Print Preview for xxxx screen is displayed.
  7. Type %sc in the Command field on the Standard toolbar.
  8. Press the Enter key. The Find screen is displayed.
  9. In the Search For field, type a character string to be found. If you are searching for the current logon language, you might type language. Wildcard characters are not permitted.
  10. Press the Find button. A second Find screen appears showing the lines that contain the text you typed. Matches are highlighted.
  11. To select a match, click once on a highlighted word. You are returned to the Print Preview for xxxx screen; the list is scrolled to the line you selected and the cursor is positioned on that line.
  12. To search again, press the down arrow at the end of the Command field on the Standard toolbar. A drop-down box appears containing the most recently entered commands.
  13. Scroll, if necessary, to the %sc command and click on it. %sc appears in the command field.
  14. Press the Enter key. The Find screen is redisplayed.
  15. Press the Find button. The search is performed starting at the current line. The second Find screen is redisplayed and the matches are shown.
  16. Click once on any highlighted word to display it.

TIP
For future reference, you can save the list on the Print Preview for xxxx to a text file on your hard drive. To do this, from the Print Preview for xxxx screen, choose the menu path System->List->Save->Local File. On the Save List in File. . . screen, choose the Unconverted radio button and press the Continue button. On the Transfer List to a Local File screen, type the name of a text file, for example, c:\temp\syst.txt, and then press the OK button. This creates the file on your hard drive. You can open and search through it using WordPad at any time, without having to use the "How to Search the Descriptions of a Structure or Table" procedure shown above.

By following the preceding procedure, you have found that the current logon language is stored in sy-langu. The completed program appears in Listing 9.3.


Listing 9.3  Listing 9.2 with the Missing SY Variable Added on Line 5

 1 report ztx0903.
 2 tables ztxt005t.
 3 parameters `land1 like ztxlfa1-land1 obligatory default 'US'.
 4 select single * from ztxt005t
5     where spras = sy-langu           "current logon language
 6     and   land1 = `land1.
 7 if sy-subrc = 0.
 8     write: 'Description:', ztxt005t-landx.
 9 else.
10     write: 'No description exists for', `land1.
11     endif.

The code in Listing 9.3 produces this output:

Description: United States

Line 5 limits the select to return only records from ztxt005t that have a language code equal to the current logon language. Because mandt is automatically added at the beginning of every where, the primary key is now fully specified and a single, unique record is returned. Notice that the primary index supports this select, so the fields of the where clause have been specified in the same order as they appear in the primary index.

Assignment Statements

An assignment statement assigns a value to a variable or field string. Three assignment statements are commonly used:

Using the clear Statement

The clear statement sets the value of a variable or a field string to zeros. If the data type is c, the value is instead set to blanks. Blanks and zeros are known as default initial values. It is often said that clear assigns default initial values to variables.

Syntax for the clear Statement

The following is the syntax for the clear statement.

clear v1 [with v2 | with 'A' | with NULL]

where:

The following points apply:

Listing 9.4 shows a sample program that clears variables and field strings.

NOTE
Listing 9.4 uses a new addition called no-gap on the write statement. No-gap causes the next output value to be written immediately after the current one without an intervening space.


Listing 9.4  Variables Set to Blanks or Zeros by the CLEAR Statement

 1 report ztx0904.
 2 tables ztxlfa1.
 3 data: f1(2) type c value 'AB',
 4       f2    type i value 12345,
 5       f3    type p value 12345,
 6       f4    type f value '1E1',
 7       f5(3) type n value '789',
 8       f6    type d value '19980101',
 9       f7    type t value '1201',
10       f8    type x value 'AA',
11       begin of s1,
12           f1(3) type c value 'XYZ',
13           f2    type i value 123456,
14           end of s1.
15 ztxlfa1-lifnr = 'XXX'.
16 ztxlfa1-land1 = 'CA'.
17 write: / 'f1=''' no-gap, f1 no-gap, '''',
18        / 'f2=''' no-gap, f2 no-gap, '''',
19        / 'f3=''' no-gap, f3 no-gap, '''',
20        / 'f4=''' no-gap, f4 no-gap, '''',
21        / 'f5=''' no-gap, f5 no-gap, '''',
22        / 'f6=''' no-gap, f6 no-gap, '''',
23        / 'f7=''' no-gap, f7 no-gap, '''',
24        / 'f8=''' no-gap, f8 no-gap, '''',
25        / 's1-f1=''' no-gap, s1-f1 no-gap, '''',
26        / 's1-f2=''' no-gap, s1-f2 no-gap, '''',
27        / 'ztxlfa1-lifnr=''' no-gap, ztxlfa1-lifnr no-gap, '''',
28        / 'ztxlfa1-land1=''' no-gap, ztxlfa1-land1 no-gap, ''''.
29 clear: f1, f2, f3, f4, f5, f6, f7, f8, s1, ztxlfa1.
30 write: / 'f1=''' no-gap, f1 no-gap, '''',
31        / 'f2=''' no-gap, f2 no-gap, '''',
32        / 'f3=''' no-gap, f3 no-gap, '''',
33        / 'f4=''' no-gap, f4 no-gap, '''',
34        / 'f5=''' no-gap, f5 no-gap, '''',
35        / 'f6=''' no-gap, f6 no-gap, '''',
36        / 'f7=''' no-gap, f7 no-gap, '''',
37        / 'f8=''' no-gap, f8 no-gap, '''',
38        / 's1-f1=''' no-gap, s1-f1 no-gap, '''',
39        / 's1-f2=''' no-gap, s1-f2 no-gap, '''',
40        / 'ztxlfa1-lifnr=''' no-gap, ztxlfa1-lifnr no-gap, '''',
41        / 'ztxlfa1-land1=''' no-gap, ztxlfa1-land1 no-gap, ''''.

The code in Listing 9.4 produces this output:

f1='AB'
f2='    12,345 '
f3='         12,345 '
f4=' 1.000000000000000E+01'
f5='789'
f6='19980101'
f7='120100'
f8='AA'
s1-f1='XYZ'
s1-f2='   123,456 '
ztxlfa1-lifnr='XXX       '
ztxlfa1-land1='CA '
f1='  '
f2='         0 '
f3='              0 '
f4=' 0.000000000000000E+00'
f5='000'
f6='00000000'
f7='000000'
f8='00'
s1-f1='   '
s1-f2='         0 '
ztxlfa1-lifnr='          '
ztxlfa1-land1='   '

Listing 9.5 shows a sample program that fills variables and components of field strings with values other than spaces or zeros.


Listing 9.5  Variables Filled with Characters Other than Blanks or Zeros Using the WITH Addition of the CLEAR Statement

 1 report ztx0905.
 2 tables ztxlfa1.
 3 data: f1(2) type c value 'AB',
 4       f2(2) type c,
 5       f3    type i value 12345,
 6       begin of s1,
 7           f1(3) type c value 'XYZ',
 8           f2    type i value 123456,
 9           end of s1.
10 write: / 'f1=''' no-gap, f1 no-gap, '''',
11        / 'f2=''' no-gap, f2 no-gap, '''',
12        / 'f3=''' no-gap, f3 no-gap, '''',
13        / 's1-f1=''' no-gap, s1-f1 no-gap, '''',
14        / 's1-f2=''' no-gap, s1-f2 no-gap, '''',
15        / 'ztxlfa1-lifnr=''' no-gap, ztxlfa1-lifnr no-gap, '''',
16        / 'ztxlfa1-land1=''' no-gap, ztxlfa1-land1 no-gap, '''',
17        /.
18 clear: f1 with 'X',
19        f2 with f1,
20        f3 with 3,
21        s1 with 'X',
22        ztxlfa1 with 0.
23 write: / 'f1=''' no-gap, f1 no-gap, '''',
24        / 'f2=''' no-gap, f2 no-gap, '''',
25        / 'f3=''' no-gap, f3 no-gap, '''',
26        / 's1-f1=''' no-gap, s1-f1 no-gap, '''',
27        / 's1-f2=''' no-gap, s1-f2 no-gap, '''',
28        / 'ztxlfa1-lifnr=''' no-gap, ztxlfa1-lifnr no-gap, '''',
29        / 'ztxlfa1-land1=''' no-gap, ztxlfa1-land1 no-gap, ''''.

The code in Listing 9.5 produces this output:

f1='AB'
f2='  '
f3='    12,345 '
s1-f1='XYZ'
s1-f2='   123,456 '
ztxlfa1-lifnr='          '
ztxlfa1-land1='   '

f1='XX'
f2='XX'
f3='50,529,027 '
s1-f1='XXX'
s1-f2='1482184792 '
ztxlfa1-lifnr='##########'
ztxlfa1-land1='###'

Using the move Statement

To move a value from one field to another, use the move statement. The entire contents or a portion thereof can be moved. Instead of move, you can use the assignment operator =, as shown below. They are both referred to as a move statement.

Syntax for the move Statement

The following is the syntax for the move statement. Operators and operands must be separated by spaces. Multiple assignment occurs from right to left.

move v1 to v2.

or

v2 = v1.

or

v2 = v1 = vm = vn . . ..

or

move v1[+N(L)] to v2[+N(L)].

or

v2[+N(L)] = v1[+N(L)].

where:

These are two examples in Table 9.2 of the right and wrong ways to code assignment statements. Incorrect coding results in a syntax error.

Table 9.2  Right and Wrong Coding of Assignment
Right
Wrong
f1 = f2.f1=f2.
f1 = f2 = f3.f1=f2=f3.

Data Conversions

If two variables have different data types or lengths, the data is converted when it is moved. This is called an automatic adjustment. If the lengths of the sending and receiving variables do not match, an automatic length adjustment is performed. If the data types do not match, an automatic type adjustment is performed.

If the data types of the sending and receiving fields are the same but the lengths differ, a length adjustment is performed as shown in Table 9.3. In this table, the sending field is the "From" field.

Table 9.3  Effect of Length Adjustment Varies with the Data Type
Type
When assigning to a longer field, the 'from' value is: When assigning to a shorter field, the 'from' value is:
c
Right-padded with blanks Right-truncated
x
Right-padded with zeros Right-truncated
n
Left-padded with zeros Left-truncated
p
Left-padded with zeros Assigned if the numeric value will fit in the 'to' field.
 
  If the numeric value is too large for the receiving field, a short dump occurs.

The remaining data types (f, i, d, and t) are all of a fixed length, so the sending and receiving fields will always be the same length if they are of the same data type.

Rules for type adjustments are provided in Table 9.4. The conversion rules for type i are the same as for type p. Included are conversions with unusual behaviors. Points to notice are:

Table 9.4  Rules for Type Adjustments
From Type
To Type
Conversion Rules
c
p
The sending field can only contain numbers, a single decimal point, and an optional sign. The sign can be leading or trailing. Blanks can appear on either side of the value. It is right-justified and padded on the left with zeros. An entirely blank sending field is converted to zero.
c
d
The sending field should contain only a valid date in the format YYYYMMDD. If it does not, an error does not occur; instead, an invalid value is assigned to the receiving field. The results of using this value are undefined.
c
t
The sending field should only have a valid time in the format HHMMSS. If it does not, an error does not occur; instead, an invalid value is assigned to the receiving field. The results of using this value are undefined.
c
n
The sending field is scanned from left to right and only the digits 0-9 are transferred to the receiving field (right-justified) and padded on the left with zeros. All other characters are simply ignored.
c
x
Valid values for the sending field are 0-9 and capital letters A-F. The value is left-justified and padded on the right with zeros or truncated on the right. All characters after the first invalid value in the sending field are ignored.
p
c
The value is right-justified in the receiving field with the right-most byte reserved for a trailing sign. The sign is only displayed if the number is negative; therefore, positive numbers will be right-justified with a single trailing blank. In the event you try to move a positive value that contains as many digits as the receiving field is long, the system will use the entire length of the receiving field to contain the value without reserving the right-most byte for the sign. After considering the above, if the value in the sending field will not fit the receiving field, the number is truncated on the left. If truncation has occurred, the system indicates this by replacing the left-most digit with an asterisk (*). If the value does fit in the receiving field, leading zeros are suppressed. If the sending field is equal to zero, the receiving field receives a single zero.
p
d
The number is interpreted as the number of days since 0001/01/01, converted to a date, and stored internally in YYYYMMDD format.
p
t
The number is interpreted as the number of seconds since midnight, converted to 24-hour clock time, and stored internally in HHMMSS format.
d
p
The date is converted to a number representing the number of days since 0001/01/01.
t
p
The time is converted to a number representing the number of seconds since midnight.

For a complete list of conversion rules, consult the ABAP/4 keyword documentation for the move statement. The procedure for displaying it follows in the next section.

Listing 9.6 contains a demonstration program that performs sample data conversions.


Listing 9.6  Sample Data Conversions

 1 report ztx0906.
 2 constants >(3) value '==>'.      "defines a constant named '>'
 3 data: fc(10)  type c value '-A1B2C3.4',
 4       fn(10)  type n,
 5       fp      type p,
 6       fd      type d,
7       ft      type t,
 8       fx(4)   type x,
 9       fc1(5)  type c value '-1234',
10       fc2(5)  type c value '1234-',
 11       fp1     type p value 123456789,
12       fp2     type p value '123456789-',
13       fp3     type p value 1234567899,
14       fp4     type p value 12345678901,
15       fp5     type p value 12345,
16       fp6     type p value 0.
17
18 fn = fc.       write: / fc, >, fn, 'non-numeric chars are ignored'.
19 fd = 'ABCDE'.  write: / fd, 'date and time fields are invalid'.
20 ft = 'ABCDE'.  write: / ft, '  when you load them with junk'.
21 fp = sy-datum. write: / sy-datum, >, fp, 'd->p: days since 0001/01/01'.
22 fp = sy-uzeit. write: / sy-uzeit, >, fp, 'd->t: secs since midnight'.
23 fx = 'A4 B4'.  write: / 'A4 B4', >, fx, 'ignore all after invalid char'.
24 fp = fc1.      write: / fc1, >, fp, 'allows leading sign'.
25 fp = fc2.      write: / fc2, >, fp, 'also allows trailing sign'.
26 fc = fp1.      write: / fp1, >, fc, 'rightmost byte reserved for sign'.
27 fc = fp2.      write: / fp2, >, fc, 'only negative numbers use it, but'.
28 fc = fp3.      write: / fp3, >, fc, '+ve nums that need it use it too'.
29 fc = fp4.      write: / fp4, >, fc, 'overflow indicated by leading *'.
30 fc = fp5.      write: / fp5, >, fc, 'leading zeros are suppressed'.
31 fc = fp6.      write: / fp6, >, fc, 'zero in = zero out'.
32 fp = ' '.      write: / ' ', >, fp, 'blanks in = zero out'.

The code in Listing 9.6 produces the following output:

-A1B2C3.4  ==> 0000001234 non-numeric chars are ignored
E   ABCD date and time fields are invalid
ABCDE0   when you load them with junk
1998/02/22 ==>         729,443  d->p: days since 0001/01/01
14:57:05 ==>          53,825  d->t: secs since midnight
A4 B4 ==> A4000000 ignore all after invalid char
-1234 ==>           1,234- allows leading sign
1234- ==>           1,234- also allows trailing sign
    123,456,789  ==> 123456789  rightmost byte reserved for sign
    123,456,789- ==> 123456789- only negative numbers use it, but
  1,234,567,899  ==> 1234567899 +ve nums that need it use it too
 12,345,678,901  ==> *345678901 overflow indicated by leading *
         12,345  ==>     12345  leading zeros are suppressed
              0  ==>         0  zero in = zero out
  ==>               0  blanks in = zero out

Start the ScreenCam "How to Display the Conversion Rules in the ABAP/4 Keyword Documentation" now.

To display the conversion rules in the ABAP/4 keyword documentation:

  1. Begin at the ABAP/4 Editor: Initial Screen.
  2. Choose the menu path Utilities->ABAP/4 Key Word doc. The Display Structure: ABAP/4 SAP's 4GL Programming Language screen is displayed.
  3. Press the Find button on the Application toolbar. The Search Titles dialog box is displayed.
  4. In the Find field, type move.
  5. In the Type of Search group box, choose the From Struct. Start radio button.
  6. Press the Continue button. The dialog box disappears and the move line is highlighted.
  7. Double-click on the highlighted line. The Display Hypertext: screen is displayed.
  8. Press the Page Down key twice. The beginning of the conversion table is displayed.

Subfields

The portion of a field referenced by the specification of an offset and/or length is called a subfield.

Syntax for a Subfield
v1[+o][(L)] = v2[+o][(L)].
where: The following points apply: The length, when present, is always surrounded by parentheses.

Listing 9.7 shows a sample program that performs assignments and uses subfields.


Listing 9.7  Moving a Portion of a Field Using a Subfield Assignment

 1 report ztx0907.
 2 data: f1(7),
 3       f2(7).
 4 f1      = 'BOY'.     "same as: move 'BOY' to f1.
 5 f2      = 'BIG'.     "same as: move 'BIG' to f2.
 6 f1+0(1) = 'T'.       "f1 now contains 'TOY    '.

 7 write / f1.
 8 f1(1)   = 'J'.       "same as: f1+0(1) = 'J'.
 9 write / f1.          "f1 now contains 'JOY    '.
10 f1(1)   = f2.        "same as: f1(1) = f2(1).
11 write / f1.          "f1 now contains 'BOY    '.
12 f1+4    = f1.        "same as: f1+4(3) = f1(3).
13 write / f1.          "f1 now contains 'BOY BOY'.
14 f1(3)   = f2(3).     "same as: f1+0(3) = f2+0(3).
15 write / f1.          "f1 now contains 'BIG BOY'.

The code in Listing 9.7 produces this output:
TOY
JOY
BOY
BOY BOY
BIG BOY

Using move with Field Strings

With move, a field string name specified without a component name is treated as if it were a variable of type c. Figure 9.2 and Listing 9.8 illustrate this point.

Figure 9.2 : Using move on a field string without using a component name causes it to be treated as a variable of type c.


Listing 9.8  The MOVE Statement Treats a Field String Name without a Component Name like a Variable of Type C

 1 report ztx0908.
 2 data: f1(4) value 'ABCD',
 3       begin of s1,
 4           c1(1),
 5           c2(2),
 6           c3(1),
 7           end of s1.
 8 s1 = f1.                         "s1 is treated as a char 4 variable
 9 write: / s1,                     "writes ABCD
10        / s1-c1, s1-c2, s1-c3.    "writes A BC D

The code in Listing 9.8 produces this output:

ABCD
A BC D

Field String Moves Involving Numeric Fields
If the sending field is category character (types c, n, d, t, or x) and the target is a field string containing a numeric field (types i, p, or f), no data conversion is performed. The move proceeds as if both were purely character. The reverse is also true. No conversions are performed when moving a numeric to a field string containing a character field. In both cases, the results are invalid and are undefined.
Listing 9.9 shows a sample program that make an invalid conversion of a numeric field to a character field string.


Listing 9.9  Moving a Numeric Field to a Character Field String Is Invalid

 1 report ztx0909.
 2 data: fc(5) type c,
 3       begin of s,
 4            fi type i,
 5            end of s.
 6
 7 fc = '1234'.
 8 s = fc.           "c<-c, no conversion performed
 9 write s-fi.       "writes junk
10
11 s-fi = 1234.      "assign a valid value
12 fc = s.           "c<-c, no conversion performed
13 write / fc.       "writes junk
14
15 s-fi = 1234.      "assign a valid value
16 fc = s-fi.        "c<-i conversion performed
17 write / fc.       "writes 1234

On my machine, the code in Listing 9.9 produces the following output. Your results might vary for the first two lines of output due to the invalid assignments performed.
875770,417
"###
1234

CAUTION
You should not move a type c variable to or from a field string containing a numeric type. The results are machine-dependent and therefore undefined.

Moving from One Field String to Another Using Character Data Types
You can use the move statement on two field strings if both strings contain components of only character data types (c, n, d, t, and x). Listing 9.10 illustrates this concept.


Listing 9.10  Using MOVE with Two Field Strings Composed Entirely of Valid Character Data Types

 1 report ztx0910.
 2 data: begin of s1,
 3           d1     type d value '19980217',   "8 bytes
 4           n1(4)  type n value '1234',       "4 bytes
 5           c1            value 'A',          "1 byte
 6           c2            value 'B',          "1 byte
 7           end of s1,
 8       begin of s2,
 9           y1(4)  type n,                    "4 bytes
10           m1(2)  type c,                    "2 bytes
11           d1(2)  type n,                    "2 bytes
12           n1(2)  type c,                    "2 bytes
13           c1(4)  type c,                    "4 bytes
14           end of s2.
15  s2 = s1.
16  write: / s1,
17         / s2,
18         / s1-d1, s1-n1, s1-c1, s1-c2,
19         / s2-y1, s2-m1, s2-d1, s2-n1, s2-c1.

The code in Listing 9.10 produces this output:
199802171234AB
199802171234AB
19980217 1234 A B
1998 02 17 12 34AB

Moving from One Field String to Another with Numeric Data Types
Most operating systems require the machine address of numeric fields to conform to specific rules. For example, the address of a four-byte integer might be required to be divisible by two. That rule is often stated as "a four-byte integer must be aligned on an even byte boundary." Thus, the rule to which the address of a field conforms is called the alignment.
In order to satisfy alignment requirements, a typical compiler will insert padding bytes before a field that requires alignment. For example, if your four-byte integer begins at offset 0003 from the beginning of a program, a padding byte is necessary to align it on a two-byte boundary. The compiler will place an unused byte at offset 0003 so that the integer begins at offset 0004, causing it to be properly aligned. Padding bytes are invisible to the programmer, but their effects can be seen at times.
If you create a field string having a mixture of character and numeric fields, padding bytes are sometimes inserted by the system to bring numeric fields into alignment. If you attempt to use a move statement on such a field string to move its contents to another, these padding bytes can cause unexpected results.
Therefore, you can only use move if one of the following is true: If both the sending and receiving fields are entirely composed of character fields, no padding bytes will exist and the result of using move is predictable. If there is a mixture of character and numeric types, padding bytes might exist and the result of using move can be unexpected. An example is shown in Listing 9.11.
NOTE
The move-corresponding statement can be used to move field strings that have a mixture of character and numeric data types. It is described in the following section.


Listing 9.11  Padding Bytes Can Cause Unexpected Results When Moving Data Between Field Strings

 1 report ztx0911.
 2 data: begin of s1,
 3           c1 value 'A',             "one byte

 4           c2 type i value 1234,     "four bytes, usually needs padding
 5           c3 value 'B',             "one byte
 6           end of s1,

 7       begin of s2,
 8           c1,                       "one byte
 9           c2(4),                    "four bytes, no padding
10           c3,                       "one byte
11           end of s2,
12       begin of s3,                  "s3 matches s1 exactly:
13           x1,                       "- data types the same
14           x2 type i,                "- number of fields the same
15           x3,                       "- fields in the same order
16           end of s3.                "(names don't have to match)
17 s2 = s1.
18 write: / s2-c1, s2-c2, s2-c3.
19 s3 = s1.
20 write: / s3-x1, s3-x2, s3-x3.

On my system, the code in Listing 9.11 produces the following output. In your system, results might vary for fields with invalid assignments.

A ###" #
A      1,234  B

s1-c1 is only one byte long, so c2 has an uneven offset from the beginning of the field string and requires padding on most systems, which makes s1 longer than s2. When s1 is assigned to s2, c3 does not line up and some of s1-c2 ends up at the beginning of s2-c3. However, s3 matches s1 exactly, so the move on line 14 works perfectly.

This example shows that you can't ignore the effects of having numeric fields within a structure. The fact that each receiving field has the same number of bytes as each sending field is not enough to guarantee that the components will line up.

Alignment rules vary with the operating system, so the number of padding bytes and their positions vary. The results of a move on one operating system might be different on another. Therefore, to ensure that your programs are portable, never rely on padding bytes and don't consider them during moves. Each field string must be composed entirely of character data types or all components of each field string must match exactly (except for the name).

Using the move-corresponding Statement

To perform a move from one field string to another where the data types and/or lengths do not match, use the move-corresponding statement. It generates individual move statements for components with matching names. Components in the receiving field string that do not have a matching name in the sending field string are not changed. Listing 9.12 illustrates.

Syntax for the move-corresponding Statement

The following is the syntax for the move statement. Operators and operands must be separated by spaces. Multiple assignment occurs from right to left.

move-corresponding v1 to v2.

where:


Listing 9.12  The MOVE-CORRESPONDING Statement Generates Individual MOVE Statements and Thus Performs Data Conversion

 1 report ztx0912.
 2 data: begin of s1,
 3           c1    type p decimals 2 value '1234.56',
 4           c2(3)                   value 'ABC',
 5           c3(4)                   value '1234',
 6           end of s1,
 7       begin of s2,
 8           c1(8),
 9           x2(3)                   value 'XYZ',
10           c3    type i,
11           end of s2.
12 write: / 's1                          :', s1-c1, s1-c2, s1-c3.
13 write: / 's2 before move-corresponding:', s2-c1, s2-x2, s2-c3.
14 move-corresponding s1 to s2. "same as coding the following two statements
15 * move s1-c1 to s2-c1.       "performs conversion
16 * move s1-c3 to s2-c3.       "performs conversion
17 write: / 's2 after  move-corresponding:', s2-c1, s2-x2, s2-c3.

The code in Listing 9.12 produces this output:

s1                          :         1,234.56  ABC 1234
s2 before move-corresponding:          XYZ          0
s2 after  move-corresponding: 1234.56  XYZ      1,234

Line 14 generates two move statements; for sake of clarity, they are shown within comments on lines 15 and 16. Normally, you cannot see these move statements; the system generates and executes them automatically "behind the scenes." One move is generated for each component of the receiving field string that has the same name as a component in the sending field string. In this case, c1 and c3 have the same names, so two moves are generated. Data conversions are performed as they would be if you had coded these statements yourself. The contents of c2 are unchanged after the move-corresponding completes.

Performing Calculations

You can perform calculations using the following statements:

Using the compute Statement

Compute is the statement most commonly used to perform calculations.

TIP
If two field strings match exactly, don't use move-corresponding to move the data from one to another. Use move, it's more efficient.

Syntax for the compute Statement
The following is the syntax for the compute statement. Operators and operands must be separated by spaces. More than one operator per statement is permitted.
compute v3 = v1 op v2 [op vn ...].
or
v3 = v2 op v2 [op vn ...].

where: Table 9.5 contains a list of the valid operators.

Table 9.5  Valid Operators for the COMPUTE Statement
Operator
Operation
+
Addition
-
Subtraction
*
Multiplication
/
Division
**
Exponentiation
DIV
Integer division
MOD
Remainder of integer division

There are also built-in functions. For a list, obtain F1 help for the keyword compute.
Operator precedence is as follows: Division by zero results in a short dump unless the operands are both zero. In that case, the result is zero. Values are converted when necessary during computation. The rules for data conversion and the order of data type precedence (described below with the if statement) determine how the conversion is performed.
Mathematical expressions can contain any number of parentheses. Each must be preceded and followed by at least one space. However, there is one exception to this rule. There cannot be a space after a built-in function name; the opening parenthesis must follow it immediately. Table 9.6 shows the right and wrong ways to code mathematical expressions.

Table 9.6  Right and Wrong Ways to Code Mathematical Statements
Right
Wrong
f1 = f2 + f3.f1 = f2+f3.
f1 = ( f2 + f3 ) * f4. f1 = (f2 + f3) * f4.
f1 = sqrt( f2 ).f1 = sqrt ( f2 ).
f1 = sqrt(f2).

The check box Fixed Point Arithmetic in the Program Attributes screen controls how decimal calculations are performed and should always be checked. If it is, intermediate results are calculated to 31 decimal places and then rounded off when assigned to the result variable. If it is not, intermediate results do not have any decimal places, which causes the loss of all decimal precision. For example, if Fixed Point Arithmetic is not checked, the calculation 1 / 3 * 3 will give a result of zero because the intermediate result of 0.333333 is rounded off to zero before being multiplied by 3. When it is checked, the result is 1.

Using the add and add-corresponding Statements

Use the add statement to add one number to another. Field strings with components having the same name can be added together with add-corresponding.

Syntax for the add Statement
Following is the syntax for the add statement. Conversions are performed as necessary in the same way as the compute statement.
add v1 to v2.
where: The syntax for the subtract, multiply, and divide is similar.
Syntax for the add-corresponding Statement
Below is the syntax for the add-corresponding statement.
add-corresponding s1 to s2.
where: An add statement is generated for each pair of components having the same name in s1 and s2. Data conversions are performed in the same way as for the add statement. Subtract-corresponding, multiply-corresponding, and divide-corresponding operate in a similar fashion.
Examples are given in Listing 9.13.


Listing 9.13  Using ADD, SUBTRACT, MULTIPLY, DIVIDE, and CORRESPONDING Statements

 1 report ztx0913.
 2 data: f1 type i value 2,
 3       f2 type i value 3,
 4       begin of s1,
 5           c1 type i value 10,
 6           c2 type i value 20,
 7           c3 type i value 30,
 8           end of s1,
 9       begin of s2,
10           c1 type i value 100,
11           x2 type i value 200,
12           c3 type i value 300,
13           end of s2.
14 add                    f1  to   f2.   write  / f2.   "f1 is unchanged
15 subtract               f1  from f2.   write  / f2.
16 multiply               f2  by   f1.   write  / f2.
17 divide                 f2  by   f1.   write  / f2.
18 add-corresponding      s1  to   s2.   write: / s2-c1, s2-x2, s2-c3.
19 subtract-corresponding s1  from s2.   write: / s2-c1, s2-x2, s2-c3.
20 multiply-corresponding s2  by   s1.   write: / s2-c1, s2-x2, s2-c3.
21 divide-corresponding   s2  by   s1.   write: / s2-c1, s2-x2, s2-c3.

The code in Listing 9.13 produces this output:
         5
         3
         6
         3
       110         200         330
       100         200         300
     1,000         200       9,000
       100         200         300

Date Calculations

A date variable (type d) can be used within mathematical expressions. Assigning the result of a date computation to a packed variable will give the difference in days. An example is given Listing 9.14.


Listing 9.14  Date Calculations Using the Date Variable within a Computation

 1 report ztx0914.
 2 type-pools ztx1.               "contains ztx1_amalgamation_date
 3 data: d1       like sy-datum,
 4       d2       like d1,
 5       num_days type p.
 6 d1 = d2 = sy-datum.
 7
 8 subtract 1 from d1.  write / d1.  "yesterday's date
 9 d2+6 = '01'.         write / d2.  "first day of current month
10 subtract 1 from d2.  write / d2.  "last day of previous month
11
12 num_days = sy-datum - ztx1_amalgamation_date.
13 write / num_days.                "number of days since amalgamation

On February 22, 1998, the code in Listing 9.14 produced this output:

1998/02/21
1998/02/01
1998/01/31
             354

Dynamic Assignment

A field-symbol is a pointer you can dynamically assign to a field. After assignment, you can use the field-symbol anywhere in your program in place of the actual field name. Use the field-symbol statement to define a field-symbol, and use assign to assign a field to it. The field-symbol name must begin and end with angle brackets. Listing 9.15 contains a simple example.


Listing 9.15  A Field-Symbol Is a Reference to Another Field

1  report ztx0915.
2  data f1(3) value 'ABC'.
3  field-symbols <f>.
4  assign f1 to <f>.   "<f> can now be used in place of f1
5  write <f>.          "writes the contents of f1
6  <f> = 'XYZ'.        "assigns a new value to f1
7  write / f1.

The code in Listing 9.15 produces this output:

ABC
XYZ

You can use field-symbols to create very generic programs. Suppose, for example, that you want to create a program that accepts a table name as an input parameter and displays the contents. You could not hard-code the field names on the write statement because the names are different in every table. You could instead use a field-symbol on the write statement to refer to the field of a table.

Summary

DO
DON'T
DO use fields of the same data type when possible to avoid conversions. DON'T move invalid values into fields.
DO use move-corresponding to move fields from one field string to another when the components have the same name but the data types and lengths do not match.  
DO use the clear statement to assign default initial values to a variable or field string.  

Q&A

Q
I can use the clear statement to set a value to blanks or zeros, but is there a statement that can set a variable back to the value I specified using the value addition on the data statement?
A
No, unfortunately there isn't.
Q
Can I use the move statement with field strings of differing lengths?
A
Yes, you can. They will both be treated as variables of type c. The sending value will be truncated or padded on the end with blanks as needed before assignment to the receiving field string.
Q
Why do I need to know about padding bytes? Doesn't the system take care of that if I just follow all the rules?
A
Technically, yes, it will. However, as you code more programs, occasionally you will inadvertently assign a field string incorrectly using move. If you understand padding bytes and how they affect your output, hopefully you will be able to recognize the cause of your problems, and won't resort to a "hack" to make the program work.
Q
It seems strange that I can assign invalid values to variables. What happens if I use one of these variables with an invalid value in it?
A
Anything can happen. I wouldn't write a program that intentionally relies on invalid values. For example, don't be tempted to use a special date value of all x to indicate something special like a missing date. The behavior of your program becomes unpredictable when you go outside the allowable boundaries of the language.
Q
The syntax messages often don't indicate what is truly wrong with my program. Is it me or is the syntax checker way out in left field sometimes?
A
Let's just say...it isn't you. My favorite of all time is the message xxxx is expected. It really means "xxxx is not expected." So when you see that message, insert the word not, and it will be correct.

Workshop

The Workshop provides 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. What is another way to move a value from one variable to another?
  2. What must separate operands and operators in order for the computation to work?

Exercise 1

Using the procedure called "How to Search the Descriptions of a Structure or Table" to find the following:

Two things are wrong with the program in Listing 9.16. What are they?


Listing 9.16  This Code Illustrates the Use of Some Basic System Variables

report zty0916.
tables ztxlfa1.
 parameters land1 like ztxlfa1-land1 obligatory default 'US'.
select * from ztxt005t
    where land1 = land1
    and   spras = sy-langu.
    write: / 'Description:', ztxt005t-landx.
    endselect.
if sy-subrc <> 0.
    write: / 'No descriptions exist for country', land1.
    endif.


© Copyright, Macmillan Computer Publishing. All rights reserved.