---
url: >-
  /statelake/scripting-reference/functions-and-procedures/what-is-a-procedure/defining-or-declaring-a-procedure.md
---

# Defining Or Declaring A Procedure

**Procedures** are set-up (declared in script) using the keyword **Procedure** as the prefix. And just like a function, you can write your own user‑defined procedures.

But just writing and naming a user-defined procedure does not actually allow it to run. All procedures (and functions for that matter) need to be enveloped in a *script wrapper* or envelope, within a special procedure name that is recognised by **Statelake**.

For a procedure to be run within a custom script this wrapper is called **ScriptEvent**. When the **Statelake** core system comes to this **ScriptEvent** procedure in its processing, it pauses at that point whatever processing is taking place and runs the code contained within the **ScriptEvent** wrapper.

There are other procedures of course that run outside of this custom **ScriptEvent** wrapper – but these procedures have their own system generated wrapper. These other wrappers are found within the **Statelake Map**, and are **BeforeMap**, **OnStartMap**, **OnEndMap**, **LinkedData**, **AfterMap**, **AfterDetailMap**, and **OnMap**.

The wrappers will always be in the same format. The wrapper code will occupy the first line with the unnamed variables within parentheses (i.e. OnMapEvent(var Value:variant);).

The following lines contain the code that will be run, with the final line as the wrapper closing instruction end;. The final character on both of these top and bottom wrapper lines is a semi-colon (;).

The following example shows a simple basic procedure to send a text string to the script log using the pre-defined function **LogInfo**, enveloped by the **ScriptEvent** wrapper.

```pascal
procedure ScriptEvent(var Value:variant);
begin
  LogInfo('Hello there.  Welcome to our system!');
end;
```

This custom script **ScriptEvent** procedure uses the two variables **CustName** and **HomeNum** to supply the information necessary to generate the function result as a string.

```pascal
procedure ScriptEvent(var Value:variant);
  ContactFunc(CustName:string;HomeNum:integer):string;
begin
  Result := 'Please contact '+CustName+' on '+IntToStr(HomeNum);
end;
```

**Procedures** can be as complicated as they need to be.

This following procedure is called by the script wrapper **OnMapEvent** within the **Statelake Map**, and tests for the presence of multiple address fields with an **IF** statement, to build an address string with no blank or redundant data.

The square brackets \[ ] signify that the contents within the brackets is a field name.

```pascal
procedure OnMapEvent(var Value:variant);         //ADDRESS
begin
    Value := '';
 If (CR_ACCS['ADDRESS3'].AsString <> '') then
       Value := CR_ACCS['ADDRESS1'].AsString+', '+CR_ACCS['ADDRESS2'].AsString+', '+CR_ACCS['ADDRESS3'].AsString;
 else if (CR_ACCS['ADDRESS2'].AsString <> '') then
      Value := CR_ACCS['ADDRESS1'].AsString+', '+CR_ACCS['ADDRESS2'].AsString;
 else
      Value := CR_ACCS['ADDRESS1'].AsString;
end;
```

Within a procedure wrapper you can have any combination of instructions, including other procedure calls.

The procedure **LogInfo** will write an entry into the action **Log** file for the configuration in which it runs.

In this one‑line procedure declaration, the input parameters are contained within the parentheses ( ), with the name of the parameter and data type separated by a colon. This procedure only requires a single string parameter called **MyMessage**. If **MyMessage** contains the string “**All the records have now been written**.” then when the procedure executes, and the exact line of text will be written into the log file.

```pascal
procedure LogInfo(MyMessage:string);
```

As with functions, multiple parameters of the same data type can be entered in the shorthand version, with a comma between the parameters such as the following example using the **Delete** procedure.

This example deletes **HowMany** characters from **Message** starting at position **WhereFrom** – where the starting position in a string is number **1**.

```pascal
procedure Delete(Message:string;WhereFrom,HowMany:integer);
```

Some procedures will use the keyword **var** to modify the parameters that are passed in, effectively returning one or more results.

This following example of the procedure **Delete** has three input variables - **MyMesssage**, which is a string, and two others called **Index** and **Count** which are both integers. **Index** specifies how many characters into the string **MyMessage** the procedure is to start at, and **Count** specifies the number of characters to be deleted.

However, since **MyMessage** is prefixed by the keyword **var**, this value of this variable will be modified and updated with the string value after the given number of characters specified in the remaining parameters have been deleted. Any further use of this variable after completion of the procedure will be using the updated value.

```pascal
procedure Delete(var MyMessage:string;Index,Count:integer);
```

This user-defined procedure called **RemoveNonKeyboardChars** can be called from a custom script to remove any characters from a string before any further processing – such as where you need to remove any non-keyboard characters. But this procedure could easily be amended to remove other characters such as apostrophe’s, double spaces, dashes or line breaks.

```pascal
procedure RemoveNonKeyboardChars(var MyString:string);
var
  OutStr : string;
  C : integer;
begin
  OutStr := '';
 For C := 1 to length(MyString) do
 begin
 If ((Ord(MyString[c]) >= 32) and (Ord(MyString[c]) <= 126)) then
      OutStr := OutStr + MyString[c];
 //Else character is not a keyboard character, therefore SKIP
 end;
  MyString := OutStr;       //Return the amended string
end;
```

The following procedure called **DumpDataview** loops through a Dataview and displays the record number and contents of the **INVNO** field to the **Log** - from the **FIrst** record until **EOF** is reached. \<DatasetName> is a placeholder for the actual **Dataview** name.

```pascal
procedure DumpDataview;
var
  RecNum : integer;
begin
  RecNum := 0;
  <DatasetName>.First;
 While not <DatasetName>.EOF do
 begin
    RecNum := RecNum + 1;
    LogInfo('RecNum = '+IntToStr(RecNum)+' '+<DatasetName>['INVNO'].AsString);
    <DatasetName>.Next;
 end;
end;
```
