Basic Delphi Syntax
Comments
As a starting point you should know how to make comments. A comment is text that is ignored by Exo Clarity and is simply for making a note about the code. This can be to explain how a complex piece of code works or perhaps give a reason for doing something unusual in the code. This helps both you and others after you who may come back to the code long after it was written to fix or modify it.
Don't make comments too long-winded - you don't have to explain every single step, just potentially confusing ones. It's also a good idea to add the date of the change and name or initials to the comment if you are making modifications to an existing report.
You can enclose a comment in curly braces - { }. It is best to put comments at the end of a line of code, or on a line on their own. For example:
Value := 1; {This is a comment here, after a
line of code}
{This
is a comment on its own line}
Variables
Variables need to be declared before they can be used. Use the var keyword to declare variables. The format is:
var variableName : type;
where "type" is one of the defined data types.
Semicolon and Layout
The semicolon is a statement separator. Every clause must end in a semicolon, with a few exceptions which are noted below. While you could put all your code on one line (the semicolons help Exo Clarity know where one statement stops and the next one starts), it is not very practical to do so. Don't be afraid to give your code plenty of space, lay it out neatly, and indent properly. This helps with readability.
Delphi uses begin and end to create code blocks. A code block is a logical sequence of commands that occur one after the other. You must use the begin and end with all major structures in Delphi when you need to do more than one command. A code block always ends in a semicolon, and each clause within the block (including embedded blocks) must end in a semicolon.
A procedure block (same for functions):
procedure MyProcedure(var inputvar: string);
var
a,b,c : integer;
begin
{Do something with a,b,c and inputvar
here}
end;
Notice that the variable declaration occurs before the procedure code block. In the code examples in this document, the procedure header, begin and end keywords are mostly omitted.
Operators
Operators are the symbols in your code that enable you to manipulate all types of data. The various types of operators that are most commonly used are explained below. Note the use of comments in this document is to explain the concepts, and commenting as verbosely is not usually necessary.
Assignment Operators
To assign a value to a variable use the := operator.
Example:
Variable1.Value := 5; {assigning
value of 5 to a variable component}
Dbtext2.text := Master['Name']; {assigning a value of a database
field to a dbtext component}
Comparison Operators
Comparison operators consist of = (equals), < (less than), > (greater than), <= (less than or equal to), >= (greater than or equal to), <> (not equal to). These are most often used in "if" statements.
Example:
if dr_trans['transtype'] = 1 then {Comparison
used}
Variable2.value :=
'Invoice'; {Assignment used}
Note: The := operator is used to assign a value to a variable. The = operator compares the values of two operands.
Logical Operators
AND and OR logical operators are most commonly used as a part of an “if” statement or loop as demonstrated in the following examples:
if (a = 2) AND (b < 3) then
{ ... Do something
... }
if (a = 2) OR (b = 2) then
{ ... Do something
... }
Note: If you have an “if” statement that makes multiple comparisons, make sure that you enclose each set of comparisons in parentheses, as shown above, or it may not work correctly.
Arithmetic Operators
These are standard mathematical operators used in the same way you would on a calculator.
|
Operator |
Addition |
+ |
Subtraction |
- |
Multiplication |
* |
Division |
/ |
Modulus |
Mod |
Because of Delphi's operator precedence, the order in which arithmetic operations are calculated is not necessarily the same as the order you type them, just like on a scientific calculator. You can use parentheses to group operations, and the parenthesised operations will happen first. While operator precedence is outside the scope of this document, two examples are used below to illustrate:
A := 1 + 2 * 3; {A is 7 after this statement}
A := (1 + 2) * 3; {A is 9 after this statement}
String Concatenation Operator
Strings also have an operator, the concatenation operator, which is the same as arithmetic addition:
Text := 'Dear ' + Dr_Contacts['Firstname'] + ' ' + Dr_Contacts['Lastname'];
If you need extra text or more than one data field in a line, this is the best way to do it. It makes the report look a lot tidier than it would if you just dumped the fields next to each other.
Testing Conditions
Testing conditions allow you to give your code some “flow control”:
If Statements
An IF statement enables you to determine whether certain conditions are met before executing some code. If statements don't need semicolons, but the statements after them (or blocks of statements) do.
Example:
if x = 4 then {no semicolon here}
y := x; {there's a
semicolon here because it ends the if statement}
Use the begin and end keywords to execute multiple lines of text when a given condition is true. This is called a “code block”.
Example:
if x = 6 then
begin
DoSomething; {semicolons
after each of these lines in the block}
DoSomethingElse;
DoAnotherThing;
end; {semicolon
after the end keyword}
You can combine multiple conditions using the IF … ELSE construct:
if x = 100 then
Somefunction {no
semicolon here for a single line of code}
else if x = 200 then begin
Someotherfunction1;
Someotherfunction2;
end else begin
Somethingelse1;
Somethingelse2;
end; {End
of the if statements, so there's a semicolon here}
Case Statements
A case statement provides a means for choosing one condition among many possibilities without needing lots of embedded “if…else” constructs. Case statements only work with numeric values though, not strings of text.
Example:
case Cr_Trans['Transtype'] of {Depending
on this value, one of these 4 lines are run}
1: Text := 'Invoice';
4: Text := 'Payment';
5: Text := 'Adjustment';
else Text := '';
end;
The TStringList (1-dimensional String Array)
This is the only type of "array", as it is known to programmers, that is available for use in the Clarity Calc tab. It is a data type you can use anywhere in your code to hold a list of string values that can be referenced by index in the list. You add a new item to the list as follows:
var MyStringList : TStringList;
begin
MyStringList.Add('This is the first item in my
list');
MyStringList.Add('This is the second item in my
list');
...
You can then access any item in the list like this:
...
ShowMessage(MyStringList[0]); { This displays the
first item }
ShowMessage(MyStringList[1]); { This displays the
second item }
end;
Notice the square brackets after MyStringList – you must use square brackets for this. If the entry you request from the string list does not exist you will get an error (for example, if you were to have another line referencing MyStringList[2] you would get an error). TStringLists use a "zero-based" index, because the first item is always zero.
For example, four TStringLists are used in the DashTopCustbyMargin.CLR standard dashboard report. These are global variables; they are defined in the Definitions section of the Calc tab's tree view, empty records are created in the list (before they are needed) in the GlobalOnCreate event handler, then they are populated in the DetailAfterGenerate event handler as the data is retrieved. A description of each is below:
- gslAccNos – this is used to store the account numbers (ACCNO field) of each account that is shown in the list, so that when one of the bars on the chart is clicked the ValueIndex of the clicked bar corresponds to an entry in the list that holds the clicked account's AccNo which is then applied to the filter for the drill-down data pipeline, then the pipeline can be refreshed to show the data for that account.
- gslHeadAccNos – this is used for the special case where an account in the list has a HEADACCNO field set – i.e. it is a sub-account of another account. It will not be discussed here.
- gslAccNames – this is used to store the account name so that it can be used to set the chart heading of the "drill-down" chart showing the customer sales history. It is easier to store it with the other values than pick it up when the database is re-queried.
- gslAlphaCode – similar to the account name, this is used to store the alpha code of the account for use in the history chart heading.