Understanding the PeopleCode Language

This chapter discusses:

Click to jump to parent topicPeopleCode Language Structure

This chapter assumes that you are familiar with a programming language, such as C, Visual Basic, or Java.

In its fundamentals, PeopleCode syntax resembles other programming languages. Some aspects of the PeopleCode language, however, are specifically related to the PeopleTools environment. Definition name references, for example, enable you to refer to PeopleTools definitions, such as record definitions or pages, without using hard-coded string literals. Other language features, such as PeopleCode data types and metastrings, reflect the close interaction of PeopleTools and SQL. Dot notation, classes, and methods in PeopleCode are similar to other object-oriented languages, like Java.

Click to jump to parent topicData Types

Conventional data types include number, date, string. Use them for basic computing. Object data types instantiate objects from PeopleTools classes. The appropriate use of each data type is demonstrated where the documentation discusses PeopleCode that uses that data type.

Declare variables before you use them.

This section discusses:

See Also

Variables

Click to jump to top of pageClick to jump to parent topicConventional Data Types

PeopleCode includes these conventional data types:

Considerations for Float, Integer, and Number Types

The Integer type is a number represented as a 32-bit signed twos complement number, so it has a range of -2,147,483,648 to 2,147,483,647.

The Float type is a number represented using the machine floating binary point (double precision) representation. This floating binary point representation is not appropriate for exact calculations involving decimal fractions; in particular, calculations involving money. For example, because a tenth (1/10 or .1) cannot be exactly represented in floating binary point, a floating binary point sum of .10 + .10 is not be equal to .20.

The Number type has a size limit of 34 digits, not including the decimal point, with a maximum of 32 digits to the right of the decimal point. Since the Number type is a floating decimal point representation, it is the appropriate data type for calculations involving money.

Operations (other than division) are done using integer arithmetic if the operands are both integers and the destination is an integer, even if the variable is declared as the Number type. The destination is considered to be an integer if one of the following is True:

Division (the / operator) is never performed using integer arithmetic. It is always performed using the floating-decimal-point arithmetic, even if the result variable is declared as an Integer type.

Follow these recommendations for assigning types to numbers:

Click to jump to top of pageClick to jump to parent topicObject Data Types

For most classes in PeopleTools, you need a corresponding data type to instantiate objects from that class.

See Understanding Objects and Classes in PeopleCode.

PeopleCode includes these data buffer access types:

PeopleCode includes these display data types:

PeopleCode includes these internet script data types:

PeopleCode includes these miscellaneous data types:

API Object Types

Use this data type for any ApiObject, such as a session object, a tree object, a component interface, a portal registry, and so on.

The following ApiObject data type objects can be declared as type Global:

All other ApiObject data type objects (such as all the PortalRegistry classes) must be declared as Local.

Click to jump to parent topicComments

Use comments to explain, preferably in language comprehensible to anyone reading your program, what your code does. Comments also enable you to differentiate between PeopleCode delivered with the product and PeopleCode that you add or change. This differentiation helps in your analysis for debugging and upgrades.

Note. Use comments to place a unique identifier marking any changes or enhancements that you have made to a PeopleSoft application. This marker makes it possible for you to search for all the changes you have made, which is particularly helpful when you are upgrading a database.

You insert comments into PeopleCode in these ways:

Warning! In application classes, you will see the use of /+ +/ style comments. Do not use these in your PeopleCode. These annotations are generated by the compiler. If you use them, they are removed by the system the next time you validate, compile, or save your PeopleCode. They are used to provide signature information on application class methods and properties, and they are regenerated each time the compiler compiles your application class PeopleCode. Instead, use the standard commenting mechanisms listed above.

Note. Commented text cannot exceed a maximum of 16383 characters.

The following code sample shows comment formatting:

<* this program is no longer valid commenting out entire thing REM This is an example of commenting PeopleCode; /* ----- Logic for Compensation Change ----- */ /* Recalculate compensation change for next row. Next row is based on prior value of EFFDT. */ calc_next_compchg(&OLDDT, EFFSEQ, 0); /* Recalculate compensation change for current row and next row. Next row is based on new value of EFFDT. */ calc_comp_change(EFFDT, EFFSEQ, COMP_FREQUENCY, COMPRATE, CHANGE_AMT, CHANGE_PCT); calc_next_compchg(EFFDT, EFFSEQ, 0); *>

Note. All text between the <* and *> comment markers is scanned. If you have mismatched quotation marks, invalid assignments, and so on, you may receive an error when using this type of comment.

Click to jump to parent topicStatements

A statement can be a declaration, an assignment, a program construct (such as a Break statement or a conditional loop), or a subroutine call.

This section discusses:

Click to jump to top of pageClick to jump to parent topicSeparators

PeopleCode statements are generally terminated with a semicolon. The PeopleCode language accepts semicolons even if they are not required, such as after the last statement completed within an If statement. This functionality enables you to consistently add semicolons after each statement.

Extra spaces are ignored. They are removed by the PeopleCode Editor when you save the code.

Click to jump to top of pageClick to jump to parent topicAssignment Statements

The assignment statement is the most basic type of statement in PeopleCode. It consists of an equal sign with a variable name on the left and an expression on the right:

variableName = expression;

The expression on the right is evaluated, and the result is placed in the variable named on the left. Depending on the data types involved, the assignment is passed either by value or by reference.

Assignment by Value

In most types of assignments, the result of the right-hand expression is assigned to the variable as a newly created value, in the variable's own allocated memory area. Subsequent changes to the value of that variable have no effect on any other data.

Assignment by Reference

When both sides of an assignment statement are object variables, the result of the assignment is not to create a copy of the object in a unique memory location and assign it to the variable. Instead, the variable points to the object's memory location. Additional variables can point to the same object location.

For example, both &AN and &AN2 are arrays of type Number. Assigning &AN2 to &AN does not assign a copy of &AN2 to &AN. Both array objects point to the same information in memory.

Local array of number &AN, &AN2; Local number &NUM; &AN = CreateArray(100, 200, 300); ​&AN2 = &AN; ​&NUM = &AN[1];

In the code example, &AN2 and &AN point to the same object: an array of three numbers. If you were to change the value of &AN[2] to 500 and then reference the value of &AN2[2], you would get 500, not 300. On the other hand, assigning &NUM to the first element in &AN (100) is not an object assignment. It is an assignment by value. If you changed &AN[1] to 500, then &NUM remains 200.

Note. In PeopleCode, the equal sign can function as either an assignment operator or a comparison operator, depending on context.

Click to jump to top of pageClick to jump to parent topicLanguage Constructs

PeopleCode language constructs include:

Functions as Subroutines

PeopleCode, like C, does not have subroutines as we generally refer to them. PeopleCode subroutines are the subset of PeopleCode functions only that are defined to return no value or to return a value optionally. Calling a subroutine is the same as calling a function with no return value:

function_name([param_list]);

See Also

Branching Statements

Functions

Function

Declare Function

CreateException

Try

Click to jump to top of pageClick to jump to parent topicBranching Statements

Branching statements control program flow based on evaluation of conditional expressions.

If, Then, and Else statements

The syntax of If, Then, and Else statements is:

IfconditionThen [statement_list_1] [Else [statement_list_2]] End-if;

This statement evaluates the Boolean expression condition. If condition is True, then the If statement executes the statements in statement_list_1. If condition is False, then the program executes the statements in the Else clause; if there is no Else clause, the program continues to the next statement.

Evaluate Statement

Use the Evaluate statement to check multiple conditions. Its syntax is:

Evaluateleft_termWhen [relop_1] ​right_term_1 ​[statement_list] . . . When [relop_n] ​right_term_n ​[statement_list][When-other [statement_list]] ​End-evaluate;

The Evaluate statement takes an expression, left_term, and compares it to compatible expressions (right_term) using the relational operators (relop) in a sequence of When clauses. If relop is omitted, then the equal sign is assumed. If the result of the comparison is True, the program executes the statements in the When clause, and then moves on to evaluate the comparison in the following When clause. The program executes the statements in all of the When clauses for which the comparison evaluates to True. If none of the When comparisons evaluates to True, the program executes the statement in the When-other clause, if one is provided. For example, the following Evaluate statement executes only the first When clause. &USE_FREQUENCY in the following example can only have one of three string values:

evaluate &USE_FREQUENCY when = "never" PROD_USE_FREQ = 0; when = "sometimes" PROD_USE_FREQ = 1; when = "frequently" PROD_USE_FREQ = 2; when-other Error "Unexpected value assigned to &USE_FREQUENCY." end-evaluate;

To end the Evaluate statement after the execution of a When clause, you can add a Break statement at the end of the clause, as in the following example:

evaluate &USE_FREQUENCY when = "never" PROD_USE_FREQ = 0; Break; when = "sometimes" PROD_USE_FREQ = 1; Break; when = "frequently" PROD_USE_FREQ = 2; Break; when-other Error "Unexpected value assigned to &USE_FREQUENCY." end-evaluate;

In rare cases, you may want to make it possible for more than one When clause to execute, as shown in the following example:

evaluate &PURCHASE_AMT when >= 100000 BASE_DISCOUNT = "Y"; when >= 250000 SPECIAL_SERVICES = "Y"; when >= 1000000 MUST_GROVEL = "Y"; end-evaluate;

For Statement

The For statement repeats a sequence of statements a specified number of times. Its syntax is:

Forcount=expression1toexpression2 [Stepi]; ​statement_listEnd-for;

The For statement initializes the value of count to expression1, and then increments count by i each time after it executes the statements in statement_list. The program continues in this loop until count is equal to expression2. If the Step clause is omitted, then i equals one. To count backwards from a higher value to a lower value, use a negative value for i. You can exit a For loop using a Break statement.

The following example demonstrates the For statement:

&MAX = 10; for &COUNT = 1 to &MAX; WinMessage("Executing statement list, count = " | &COUNT); end-for;

See Also

If

Evaluate

For

Click to jump to top of pageClick to jump to parent topicConditional Loops

Conditional loops, Repeat and While, repeat a sequence of statements, evaluating a conditional expression each time through the loop. The loop terminates when the condition evaluates to True. You can exit from a conditional loop using a Break statement. If the Break statement is in a loop embedded in another loop, the break applies only to the inside loop.

Repeat Statement

The syntax of the Repeat statement is:

Repeatstatement_listUntillogical_expression;

The Repeat statement executes the statements in statement_list once, and then evaluates logical_expression. If logical_expression is False, the sequence of statements is repeated until logical_expression is True.

While Statement

The syntax of the While statement is:

While ​logical_expressionstatement_listEnd-while;

The While statement evaluates logical_expression before executing the statements in statement_list. It continues to repeat the sequence of statements until logical_expression evaluates to False.

See Also

Repeat

While

Click to jump to parent topicFunctions

This section discusses:

See Also

Understanding Objects and Classes in PeopleCode

PeopleCode Built-in Functions

Function

Declare Function

Click to jump to top of pageClick to jump to parent topicSupported Functions

PeopleCode supports the following types of functions:

Note. PeopleSoft Analytic Calculation Engine provides its own set of built-in functions.

See Using Built-in Functions in Analytic Models.

In addition, PeopleCode supports methods. The main differences between a built-in function and a method are:

Click to jump to top of pageClick to jump to parent topicFunction Definitions

PeopleCode functions can be defined in any PeopleCode program. Function definitions must be placed at the top of the program, along with any variable and external function declarations.

By convention, PeopleCode programs are stored in records whose names begin in FUNCLIB_, and they are always attached to the FieldFormula event.

Note. Application classes can provide an alternative, and sometimes cleaner, mechanism for separating functionality than the functions stored in FUNCLIBs.

See Also

Function

Application Classes

Click to jump to top of pageClick to jump to parent topicFunction Declarations

If you call an external function from a PeopleCode program, you must declare the function at the top of the program. The syntax of the function declaration varies, depending on whether the external function is written in PeopleCode or compiled in a dynamic link library.

The following is an example of a function declaration of a function that is in another FUNCLIB record definition:

Declare Function UpdatePSLOCK PeopleCode FUNCLIB_NODES.MSGNODENAME FieldFormula;

See Also

Declare Function

Click to jump to top of pageClick to jump to parent topicFunction Calls

Functions are called with this syntax:

function_name([param_list])

The parameter list (param_list)is a list of expressions, separated by commas, that the function expects you to supply. Items in the parameter list can be optional or required.

You can check the values of parameters that get passed to functions at runtime in the Parameter window of the PeopleCode debugger.

If the return value is required, then the function must be called as an expression, for example:

&RESULT = Product(&RAISE_PERCENT, .01, EMPL_SALARY);

If the function has an optional return value, it can be called as a subroutine. If the function has no return value, it must be called as a subroutine:

WinMessage(64, "I can't do that, " | &OPER_NICKNAME | ".");

Parameters are always passed to internal and external PeopleCode functions by reference. If the function is supposed to change the data the caller passes, you must also pass in a variable.

Built-in function parameters can be passed by reference or by value, depending on the function. External C function parameters can be passed by value or by reference, depending on the declaration and type.

See Also

Debugging Your Application

Variables and Functions

Click to jump to top of pageClick to jump to parent topicFunction Return Values

Functions can return values of any supported data type; some functions do not return any value.

Optional return values occur only in built-in functions. You cannot define a function that optionally returns a value. Optional return values are typical in functions that return a Boolean value indicating whether execution was successful. For example, the following call to DeleteRow ignores the Boolean return value and deletes a row:

DeleteRow(RECORD.BUS_EXPENSE_PER, &L1_ROW, RECORD.BUS_EXPENSE_DTL, &L2_ROW);

The following example checks the return value and returns a message saying whether it succeeded:

if DeleteRow(RECORD.BUS_EXPENSE_PER, &L1_ROW, RECORD.BUS_EXPENSE_DTL, &L2_ROW) then WinMessage("Row deleted."); else WinMessage("Sorry -- couldn't delete that row."); end-if;

Click to jump to top of pageClick to jump to parent topicFunction Naming Conflicts

If you define a function with the same name as a built-in function, the function that you defined takes precedence over the built-in function.

Anytime you compile the PeopleCode in the PeopleCode Editor, a warning message appears in the Validate tab, indicating that a user-defined function has the same name as an existing built-in function.

In addition, if you select Compile All PeopleCode, an error message is generated in the log file for every user-defined function that has the same name as a built-in function.

The following is an example error message: User-defined function IsNumber is overriding the built-in function of the same name. (2,98)

If you notice that you named a function the same as a built-in function, and that the built-in function does what you're trying to achieve, replace your function with a reference to the built-in function. The built-in function is probably more efficient. In addition, using the built-in function reduces confusion for people who maintain your code, because if they miss the warning message in the Validate tab, they might assume the built-in function is being called when it is not.

Click to jump to parent topicExpressions

This section discusses:

See Also

Variables

Click to jump to top of pageClick to jump to parent topicExpression Fundamentals

Expressions evaluate to values of PeopleCode data types. A simple PeopleCode expression can consist of a constant, a temporary variable, a system variable, a record field reference, or a function call. Simple expressions can be modified by unary operators (such as a negative sign or logical NOT), or combined into compound expressions using binary operators (such a plus sign or logical AND).

Definition name references evaluate to strings equal to the name of a PeopleTools definition, such as a record or page. They enable you to refer to definitions without using string literals, which are difficult to maintain.

Metastrings (also called meta-SQL) are special expressions used within SQL string literals. At runtime, the metastrings expand into the appropriate SQL for the current database platform.

Click to jump to top of pageClick to jump to parent topicConstants

PeopleCode supports numeric, string, and Boolean constants, as well as user-defined constants. It also supports the constant Null, which indicates an object reference that does not refer to a valid object.

Note. You can express Date, DateTime, and Time values by converting from String and Number constants using the Date, Date3, DateTime6, DateTimeValue, DateValue, Time3, TimePart, and the TimeValue functions. You can also format a DateTime value as text using FormatDateTime.

Numeric Constants

Numeric constants can be any decimal number. Some examples are:

String Constants

String constants can be delimited by using either single (') or double (") quotation marks. If a quotation mark occurs as part of a string, the string can be surrounded by the other delimiter type. As an alternative, you can include the delimiter twice. Some examples are:

Use the following code to include a literal quotation mark as part of your string:

&cDblQuote = '"'; /* singlequote doublequote singlequote */

The following also produces a string with two double quotation marks in it:

&cDblQuote = """"; /* dquote dquote dquote dquote */

You can also directly embed the doubled double quotation mark in strings, such as:

&sImage = Char(10) | '<IMG SRC="%IMAGE(' | &pImageName | ')"';

Strings must be contained on a single line. If you need to create a multi-line string, you must use concatenation to connect the lines to be a single sting.

Boolean Constants

Boolean constants represent a truth value. The two possible values are True and False.

Null Constant

Null constants represent an object reference value that does not refer to a valid object. This means that calling a method on the object or trying to get or set a property of it fails. The Null constant is just the keyword Null.

User-Defined Constants

You can define constants at the start of a PeopleCode program. Then you can use the declared constant anywhere that the corresponding value would be allowed. Constants can be defined as numbers, strings, or Boolean values.

User-defined constants can only be declared as Local.

The following is an example of user-defined constant declarations:

Constant &Start_New_Instance = True; Constant &Display_Mode = 0; Constant &AddMode = "A": Local Field &Start_Date; . . . MyFunction(&Start_New_Instance, &Display_Mode, &Add_Mode);

See Also

PeopleCode Built-in Functions

Click to jump to top of pageClick to jump to parent topicFunctions as Expressions

You can use any function that returns a value as an expression. The function can be used on the right side of an assignment statement, passed as a parameter to another function, or combined with other expressions to form a compound expression.

See Also

Functions

Click to jump to top of pageClick to jump to parent topicSystem Variables

System variables are preceded by a percent (%) symbol whenever they appear in a program. Use these variables to get the current date and time, or to get information about the user, the current language, the current record, page, or component, and more.

See Also

System Variables

Click to jump to top of pageClick to jump to parent topicMetastrings

Metastrings are special SQL expressions. The metastrings, also called meta-SQL, are preceded with a percent (%) symbol, and can be included directly in string literals. They expand at runtime into an appropriate substring for the current database platform. Metastrings are used in or with:

See Also

SQLExec

ScrollSelect

Meta-SQL

Click to jump to top of pageClick to jump to parent topicRecord Field References

Use record field references to retrieve the value stored in a record field or to assign a value to a record field.

Record Field Reference Syntax

References to record fields have the following form:

[recordname.]fieldname

You must supply the recordname only if the record field and your PeopleCode program are in different record definitions.

For example, suppose that in a database for veterinarians you have two records, PET_OWNER and PET. A program in the record definition PET_OWNER must refer to the PET_BREED record field in the PET record definition as PET.PET_BREED.

However, a program in the PET record definition can refer to this same record field more directly as PET_BREED.

If the program is in the PET_BREED record field itself, it can refer to this record field using the caret (^) symbol.

The PeopleCode Editor replaces the caret symbol with the actual record field name.

You can also use object dot notation to refer to record fields, for example:

&FIELD = GetRecord(RECORD.PET_OWNER).GetField(FIELD.PET_BREED);

See Referencing Data in the Component Buffer.

Legal Record Field Names

A record field name consists of two parts, the record name and the field name, separated by a period.

The field names used in PeopleCode are consistent with the field names allowed in the field definition. Case is ignored, although the PeopleCode Editor for the sake of convention, automatically formats field names in uppercase. A field name can be 1 to 18 characters, consisting of alphanumeric characters determined by your current language setting in Microsoft Windows, and characters #, @, $, and _.

A record name can be 1 to 15 characters, consisting of alphanumeric letters determined by your current language setting in Microsoft Windows, and characters #, @, $, and _.

Click to jump to top of pageClick to jump to parent topicDefinition Name References

Definition name references are special expressions that reference the name of a PeopleTools definition, such as a record, page, component, business interlink, and so on. Syntactically, a definition name reference consists of a reserved word indicating the type of definition, followed by a period, then the name of the PeopleTools definition. For example, the definition name reference RECORD.BUS_EXPENSE_PER refers to the definition name BUS_EXPENSE_PER.

Generally, definition name references are passed as parameters to functions. If you attempt to pass a string literal instead of a definition name reference to such a function, you receive a syntax error.

You also use definition name references outside function parameter lists, for example, in comparisons:

If (%Page = PAGE.SOMEPAGE) Then /* do stuff specific to SOMEPAGE */ End-If;

In these cases, the definition name reference evaluates to a string literal. Using the definition name reference instead of a string literal enables PeopleTools to maintain the code if the definition name changes.

If you use the definition name reference, and the name of the definition changes, the change automatically ripples through the code, so you do not have to change it or maintain it.

In the PeopleCode Editor, if you place your cursor over any definition name reference and right-click, you can select View Definition to open the definition.

In addition, for most definitions, if you specify a definition that was not created in PeopleSoft Application Designer, you receive an error message when you try to save your program.

Legal and Illegal Definition Names

Legal definition names, as far as definition name references are concerned, consist of alphanumeric letters determined by your current language setting in Microsoft Windows, and the characters #, @, $, and _.

In some cases, however, the definition supports the use of other characters. You can, for example, have a menu item named A&M stored in the menu definition even though & is an illegal character in the definition name reference. The illegal character results in an error when you validate the syntax or attempt to save the PeopleCode.

You can avoid this problem in two ways:

The second solution is a commonly used workaround in cases where the definition name contains illegal characters. If you use this notation, the definition name reference is not treated as a string literal: PeopleTools maintains the reference the same way as it does other definition name references.

Note. If your definition name begins with a number, you must enclose the name in quotation marks when you use it in a definition name reference. For example, CompIntfc."1_DISCPLIN_ACTN".

Click to jump to top of pageClick to jump to parent topicReserved Word Summary Table

The following table summarizes the reserved words used in definition name references:

Reserved Word

Common Usage

BARNAME

Used with transfers and modal transfers.

BUSACTIVITY

Used with TriggerBusinessEvent.

BUSEVENT

Used with TriggerBusinessEvent.

BUSPROCESS

Used with TriggerBusinessEvent.

COMPINTFC

Used with Component Interface Classes.

COMPONENT

Used with transfers and modal transfers, as well as for generating URLs.

FIELD

Used with methods and functions to designate a field.

FILELAYOUT

Used with the SetFileLayout File class method.

HTML

Used with the GetHTMLText function.

IMAGE

Used in with functions and methods to designate an image.

INTERLINK

Used with the GetInterlink function.

ITEMNAME

Used with transfers and modal transfers.

MENUNAME

Used with transfers and modal transfers.

MESSAGE

Used with Messaging functions and methods.

MOBILEPAGE

Used to identify a mobile page (used with transfers.)

NODE

Used with transfers and modal transfers, as well as generating URLs.

PAGE

Used with transfers and modal transfers to pass the page item name (instead of the page name), and with controls and other functions to pass the page name.

PORTAL

Used with transfers and modal transfers, as well as generating URLs.

RECORD

Used in functions and methods to designate a record.

SCROLL

The name of the scroll area in the page. This name is always equal to the primary record of the scroll.

SQL

Used with SQL definitions.

STYLESHEET

Used with style sheets.

See Also

TriggerBusinessEvent

GetHTMLText

GetInterlink

Component Interface Classes

Message Classes

SetFileLayout

SQL Class

Click to jump to parent topicVariables

This section discusses.

See Also

System Variables

Click to jump to top of pageClick to jump to parent topicSupported Variable Types

PeopleCode supports these types of variables:

User-defined variables

These variable names are preceded by an & character wherever they appear in a program. Variable names can be 1 to 1000 characters, consisting of letters A through Z and a through z, digits 0 through 9, and characters #, @, $, and _.

System variables

System variables provide access to system information. System variables have a prefix of the % character rather than the & character. Use these variables wherever you can use a constant, passing them as parameters to functions or assigning their values to fields or to temporary variables.

Click to jump to top of pageClick to jump to parent topicUser-Defined Variables

A user-defined variable can hold the contents of a record field for program code clarity. For example, you may give a variable a more descriptive name than a record field, based on the context of the program. If the record field is from another record, you may assign it to a temporary variable rather than always using the record field reference. This makes it easier to enter the program, and can also make the program easier to read.

Also, if you find yourself calling the same function repeatedly to get a value, you may be able to avoid some processing by calling the function once and placing the result in a variable.

Click to jump to top of pageClick to jump to parent topicUser-Defined Variable Declaration and Scope

The difference between the variable declarations concerns their life spans:

You can declare variables using the Global, Local, or Component statements, or you can use local variables without declaring them. Here are some examples:

Local Number &AGE; Global String &OPER_NICKNAME; Component Rowset &MY_ROWSET; Local Any &SOME_FIELD; Local ApiObject &MYTREE; Local Boolean &Compare = True;

Variable declarations are usually placed above the main body of a PeopleCode program (along with function declarations and definitions). The exception is the Local declaration, which you can use within a function or the main section of a program. You can declare variables as any of the PeopleCode data types. If a variable is declared as an Any data type, or if a variable is not declared, PeopleTools uses an appropriate data type based on context.

Note. Declare a variable as an explicit data type unless the variable will hold a value of an unknown data type.

Global variables can be accessed from different components and applications, including an Application Engine program. A global variable must be declared, however, in each PeopleCode program where it’s used. Use global variables rarely, because they are difficult to maintain.

Global variables are not available to a portal or applications on separate databases.

Component variables remain defined and keep their values while any page in the component in which they are defined remains active. Similar to a global variable, a component variable must be declared in each PeopleCode program where it is used.

Component variables act the same as global variables when an Application Engine program is called from a page (using CallAppEngine).

Component variables remain defined after a TransferPage, DoModal, or DoModalComponent function. However, variables declared as Component do not remain defined after using the Transfer function, whether you are transferring within the same component or not.

Local variables declared at the top of a PeopleCode program (or within the main, that is, non-function, part of a program) remain in scope for the life of that PeopleCode program. Local variables declared within a function are valid to the end of the function and not beyond.

You can check the values of Local, Global, and Component variables at runtime in the different variable windows of the PeopleCode debugger. Local variables declared within a function appear in the Function Parameters window.

Click to jump to top of pageClick to jump to parent topicVariable Declaration

Declare variables before you use them. If you do not declare a variable, it is automatically declared with the scope Local and the data type Any. You receive a warning message in the Validation tab of the PeopleSoft Application Designer output window for every variable that is not declared when you save the PeopleCode program, as shown in the following example:

Validation tab with auto-declared variables

If you declared all the variables, you can use these values to ensure you do not have misspellings. For example, if you declared a variable as &END_DATE and then accidentally spell it as &EDN_DATE, the “new variable” appears on the Validate tab when you save the program.

Another reason to declare variables is for the design-time checking. If you declare a variable of one data type and then assign to it a value of a different type, the PeopleCode Editor catches that assignment as a design-time error when you try to save the program. With an undeclared variable, the assignment error does not appear until runtime.

The following example produces a design-time error when you try to save the program:

Local Field &DATE; &DATE = GetRecord(RECORD.DERIVED_HR);

In addition, if you declare variables, the Find Object Reference feature finds embedded definitions. For example, suppose you wanted to find all occurrences of the field DEPT_ID. If you have not declared &MyRecord as a record, Find Object References does not find the following reference of the field DEPT_ID:

&MyRecord.DEPT_ID.Visible = False;

Click to jump to top of pageClick to jump to parent topicUser-Defined Variable Initialization

To declare and initialize variables in one step, use the following format:

Local String &MyString = "New"; Local Date &MyDate = %Date;

This method is available only for variables with the scope of Local.

Though you can declare more than one variable on a single line, you can only initialize one variable on a line. The following code creates a syntax error when you try to save the program:

Local Number &N1, &N2 = 5;

You cannot declare a variable, then initialize it in a second declaration statement. The following produces a duplicate declaration error when you try to save the program:

Global Number &N1; ... Local String &N1 = "Str"; /* Duplicate definition. */

If you do not initialize variables, either when you declare them or before you use them, strings are initialized as Null strings, dates and times as Null, and numbers as zero.

Click to jump to top of pageClick to jump to parent topicRestrictions on Variable Use

The following data types can only be declared as Local:

The following ApiObject data type objects can be declared as Global:

All other ApiObject data type objects (such as all the PortalRegistry classes) must be declared as Local.

Click to jump to top of pageClick to jump to parent topicScope of Local Variables

The two types of local variables are: program-local and function-local.

See Recursive Functions.

A program-local variable can be affected by statements anywhere in the program. For example, suppose RECORD_A.FIELD_A.FieldFormula has two functions, FUNC_1 and FUNC_2, and both modify a local variable named &TEMP. They could affect each other, as they both use the same variable name in the same PeopleCode program.

If, however, FUNC_3 is defined in RECORD_B_FIELD_B.FieldFormula and makes reference to &TEMP, it is not the same &TEMP as in RECORD_A.FIELD_A.FieldFormula. This difference becomes important when FUNC_1 calls FUNC_3. Technically, both functions exist at the same time, one inside the other, but &TEMP is a different variable for each of them. However, if FUNC_1 calls FUNC_2, then &TEMP is the same variable for both.

Click to jump to top of pageClick to jump to parent topicDuration of Local Variables

A local variable is valid for the duration of the PeopleCode program or function in which it is defined. A PeopleCode program is defined as what the PeopleCode Editor in Application Designer presents in a single window: a chunk of PeopleCode text associated with a single item (a record field event, a component record event, and so on.)

When the system evaluates a PeopleCode program and calls a function in the same PeopleCode program, a new program evaluation is not started.

However, when a function from a different PeopleCode program is called (that is, some PeopleCode text associated with a different item), the current PeopleCode program is suspended, and the Component Processor starts evaluating the new program. This means that any local variables in the calling program (called A) are no longer available. Those in the called program (called B) are available.

Even if the local variables in the A program have the same name as those in the B program, they are different variables and are stored separately.

If the called program (B) in turn calls a function in program A, a new set of program A's variables are allocated, and the called function in A uses these new variables. Thus, this second use of program A gets another lifetime, until execution returns to program B.

The following is an example of pseudocode to show how this might work. (This is non-compiled, non-working code. To use this example, you'd have to enter a similar program without the external declaration of the function in the other, not yet compiled, one.)

Program A (Rec.Field.FieldChange): local number &temp; declare function B1 PeopleCode Rec.Field FieldFormula; /* Uncomment this declaration and comment above to compile this the first time. function B1 end-function; */ function A1 WinMessage("A1: &temp is " | &temp); &temp = &temp + 1; A2(); B1(); A2(); end-function; function A2 WinMessage("A2: &temp is " | &temp); &temp = &temp + 1; end-function; A1(); Program B (Rec.Field.FieldFormula): local number &temp; declare function A2 PeopleCode Rec.Field FieldChange; function B1 WinMessage("B1: &temp is " | &temp); &temp = &temp + 1; A2(); end-function;

When this is compiled and run, it produces the following output:

A1: &temp is 0 A2: &temp is 1 B1: &temp is 0 A2: &temp is 0 A2: &temp is 2

Click to jump to top of pageClick to jump to parent topicVariables and Functions

PeopleCode variables are always passed to functions by reference. This means, among other things, that a function can change the value of a variable passed to it so that the variable has the new value on return to the calling routine.

For example, the Amortize built-in function expects you to pass it variables into which it places the amount of a loan payment applied towards interest (&PYMNT_INTRST), the amount of the payment applied towards principal (&PYMNT_PRIN), and the remaining balance (&BAL). It calculates these values based on information that the calling routine supplies in other parameters:

&INTRST_RT=12; &PRSNT_BAL=100; &PYMNT_AMNT=50; &PYMNT_NBR=1; Amortize(&INTRST_RT, &PRSNT_BAL, &PYMNT_AMNT, &PYMNT_NBR, &PYMNT_INTRST, &PYMNT_PRIN, &BAL); &RESULT = "Int=" | String(&PYMNT_INTRST) | " Prin=" | String(&PYMNT_PRIN) | " Bal=" | String(&BAL);

Click to jump to top of pageClick to jump to parent topicRecursive Functions

PeopleCode supports True recursive functions. A function can call itself, and each possibly recursive call of the function has its own independent copy of the parameters and function-local variables.

When writing recursive functions, be careful about passing variables as parameters, because PeopleCode implements such calls by reference. This means that if you call a function such as:

Function Func(&n as Number) &n = 3; End-Function; local &x = 5; Func(&x);

After the call to Func(&x), &x has the value 3, not 5. If the call was Func(Value(&x)), after the call &x is still 5.

Click to jump to top of pageClick to jump to parent topicState of Shared Objects Using PeopleSoft Pure Internet Architecture

Consider the following scenario:

In general, the global state of the object is restored. If the object has not been destroyed from the global state, the global state of the object is used for local references; otherwise, the local state is used for local references.

Here is an example:

Global array of number &Global_Array; Local array of number &Local_Array: &Global_Array = CreateArray(1, 2, 3); &Local_Array = &Global_Array DoModal(Page.PAGENAME, "", -1, -1, 1, Record.SHAREDREC, 1); /* return to here */ &Local_Array[1] = -1; &Global_Array[2] = -2; WinMessage(&Local_Array is " | &Local_Array.Join()); WinMessage(&Global_Array is " | &Global_Array.Join());

The following program, program 2, is located on the modal page the user is transferred to:

Global array of number &Global_Array; &Global_Array[3] = -3;

The following program, program 3, is also located on the modal page:

Global array of number &Global_Array; &Global_Array = CreateArray(1, 2, -3);

If program 2 is run, the output is the following:

&Local_Array is -1, -2, -3

&Global_Array is -1, -2, -3

However, if program 3 is run, thereby destroying the original global state, the output is the following:

&Local_Array is -1, 2, 3

&Global_Array is 1, -2, -3

See Also

System Variables

Debugging Your Application

Click to jump to parent topicOperators

PeopleCode expressions can be modified and combined using math, string, comparison, and Boolean operators.

This section discusses:

Click to jump to top of pageClick to jump to parent topicMath Operators

PeopleCode uses standard mathematical operators:

Exponentiation occurs before multiplication and division; multiplication and division occur before addition and subtraction. Otherwise, math expressions are evaluated from left to right. You can use parentheses to force the order of operator precedence.

The minus sign can also, of course, be used as a negation operator, as in the following expressions:

-10 - &NUM - Product(&PERCENT_CUT, .01, SALARY)

Click to jump to top of pageClick to jump to parent topicOperations on Dates and Times

You can add or subtract two date values or two time values, which provides a Number result. In the case of dates, the number represents the difference between the two dates in days. In the case of time, the number represents the difference in seconds. You can also add and subtract numbers to or from a time or date, which results in another date or time. Again, in the case of days, the number represents days, and in the case of time, the number represents seconds.

The following table summarizes these operations:

Operation

Result Type

Result Represents

Time + number of seconds

Time

Resulting time

Date + number of days

Date

Resulting date

Date - date

Number

Difference in days

Time - time

Number

Difference in seconds

Date + time

DateTime

Date and time combined

Click to jump to top of pageClick to jump to parent topicString Concatenation

The string concatenation operator ( | ) is used to combine strings. For example, assuming &OPER_NICKNAME is “Dave”, the following statement sets &RETORT to “I can’t do that, Dave.”

&RETORT = "I can't do that, " | &OPER_NICKNAME | "."

The concatenation operator automatically converts its operands to strings. This conversion makes it easy to write statements that display mixed data types. For example:

&DAYS_LEFT = &CHRISTMAS - %Date; WinMessage("Today is " | %Date | ". Only " | &DAYS_LEFT | " shopping days left!");

Click to jump to top of pageClick to jump to parent topic@ Operator

The @ operator converts a string storing a definition reference into the definition. This is useful, for example, if you want to store definition references in the database as strings and retrieve them for use in PeopleCode; or if you want to obtain a definition reference in the form of a string from the operator using the Prompt function.

To take a simple example, if the record field EMPLID is currently equal to 8001, the following expression evaluates to 8001:

@"EMPLID"

The following example uses the @ operator to convert strings storing a record reference and a record field reference:

&STR1 = "RECORD.BUS_EXPENSE_PER"; &STR2 = "BUS_EXPENSE_DTL.EMPLID"; &STR3 = FetchValue(@(&STR1), CurrentRowNumber(1), @(&STR2), 1); WinMessage(&STR3, 64);

Note. String literals that reference definitions are not maintained by PeopleTools. If you store definition references as strings, then convert them with the @ operator in the code, this creates maintenance problems whenever definition names change.

The following function takes a rowset and a record, passed in from another program, and performs some processing. The GetRecord method does not take a variable for the record, however, you can dereference the record name using the @ symbol. Because the record name is never hard-coded as a string, if the record name changes, this code does not have to change.

Function Get_My_Row(&PASSED_ROWSET, &PASSED_RECORD) For &ROWSET_ROW = 1 To &PASSED_ROWSET.RowCount &UNDERLYINGREC = "RECORD." | &PASSED_ROWSET.DBRecordName; &ROW_RECORD = &PASSED_ROWSET.GetRow(&ROWSET_ROW).GetRecord(@&UNDERLYINGREC); /* Do other processing */ End-For; End-Function;

Click to jump to top of pageClick to jump to parent topicComparison Operators

Comparison operators compare two expressions of the same data type. The result of the comparison is a Boolean value. The following table summarizes these operators:

Operator

Meaning

=

Equal

!=

Not equal

<>

Not equal

<

Less than

<=

Less than or equal to

>

Greater than

>=

Greater than or equal to

You can precede any of the comparison operators with the word Not, for example:

Expressions formed with comparison operators form logical terms that can be combined using Boolean operators.

String comparisons are case-sensitive. You can use the Upper or Lower built-in functions to do a case-insensitive comparison.

See Also

Lower

Upper

Click to jump to top of pageClick to jump to parent topicBoolean Operators

The logical operators AND, OR, and NOT are used to combine Boolean expressions. The following table shows the results of combining two Boolean expressions with AND and OR operators:

Expression 1

Operator

Expression 2

Result

False

AND

False

False

False

AND

True

False

True

AND

True

True

False

OR

False

False

False

OR

True

True

True

OR

True

True

The NOT operator negates Boolean expressions, changing a True value to False and a False value to True.

In complex logical expressions using the operations AND, OR, and NOT, NOT takes the highest precedence, AND is next, and OR is lowest. Use parentheses to override precedence. (Generally, it is a good idea to use parentheses in logical expressions anyway, because it makes them easier to decipher.) If used on the right side of an assignment statement, Boolean expressions must be enclosed in parentheses.

The following are examples of statements containing Boolean expressions:

&FLAG = (Not (&FLAG)); /* toggles a Boolean */ if ((&HAS_FLEAS or &HAS_TICKS) and SOAP_QTY <= MIN_SOAP_QTY) then SOAP_QTY = SOAP_QTY + OrderFleaSoap(SOAP_ORDER_QTY); end-if;