Creating Programs
Before a program can appear in the Run Programs list for end users to execute, someone must create it. This chapter walks you through the full process of writing a program in the ToolBox editor, saving it, configuring its properties, and sharing it with other users. It also covers best practices for writing programs that are intended for non-developer audiences.
The Program Creation Workflow
Creating a program for Run Programs follows a natural progression from development to deployment:
- Write the AL script in the ToolBox editor.
- Test the script interactively to verify it works correctly.
- Save the script as a named program.
- Configure the program properties (sharing, Excel, permissions).
- Share the program with the users who need it.
Each of these steps is covered in detail below.
Step 1: Writing the Program
You begin by opening the ToolBox editor in Business Central. This is the interactive coding environment where you write AL code, execute it with F9, and see results in the console output pane.
When writing a program that will be used through Run Programs, keep in mind that the end user will not see your source code. They will only see the console output and any Excel data that the program produces. This means your code should be written with the end user's experience in mind from the start.
A typical program structure looks like this:
var
Cust : Record Customer;
Counter : Integer;
begin
message('--- Customer Balance Report ---');
message('');
Cust.SetFilter("Balance (LCY)", '>%1', 0);
if Cust.FindSet() then
repeat
message('%1: %2 (%3)', Cust."No.", Cust.Name, Cust."Balance (LCY)");
Counter += 1;
until Cust.Next() = 0;
message('');
message('Total customers with balance: %1', Counter);
end;
This script produces clear, structured output that any user can understand without knowing what the code does internally.
Step 2: Testing the Program
Before saving your program, you should test it thoroughly in the ToolBox editor. Press F9 to execute the script and review the console output. Verify that:
- The output is clear and informative.
- The script handles edge cases (for example, what happens when no records match the filter).
- Error conditions are handled gracefully rather than producing cryptic error messages.
- The script completes within a reasonable time for the expected data volume.
- Any Excel operations read from and write to the correct cells and sheets.
Run the script multiple times with different data scenarios to ensure it behaves correctly in all cases. If the program modifies data, test it in a sandbox or test environment first to avoid unintended changes to production data.
Step 3: Saving the Program
Once your script is tested and working, you save it as a named program using the Save or Save As actions in the ToolBox editor.
Save
The Save action updates the currently loaded program with your latest code changes. If you opened an existing program and modified it, Save writes your changes back to the same program record.
Save As
The Save As action creates a new program record with a name you specify. Use Save As when you want to preserve the original program and create a separate copy, or when you are saving a new script for the first time.
When you save a program, the following happens:
- The AL source code is stored in the CodeBlob field of the Program table.
- The program name and description are recorded.
- Any associated Excel data is stored in the ExcelSheet blob field if applicable.
- The program becomes available for configuration and sharing.
Choose a descriptive name for your program that clearly communicates what it does. End users will see this name in the Run Programs list, so names like "Customer Balance Report" or "Monthly Data Cleanup" are far more helpful than "Script1" or "Test Program."
Step 4: Configuring Program Properties
After saving your program, you can configure its properties to control how it behaves and who can access it. The program properties are stored in the Program table and can be managed from the Programs page.
Name and Description
The program name is the primary identifier that users see in the Run Programs list. The description provides additional context about what the program does. Both should be written in plain language that your end users will understand.
CodeBlob
The CodeBlob field contains the AL source code of your program. This field is populated automatically when you save the program from the ToolBox editor. You do not typically edit this field directly; instead, you open the program in the editor, make changes, and save it again.
Shared
The Shared property is a boolean field that controls whether the program is visible to other users in the Run Programs list. When you first save a program, you should decide whether it is ready to be shared:
- Set Shared to true when the program is fully tested and ready for other users to execute.
- Keep Shared as false while the program is still in development or is intended only for your personal use.
Changing the Shared property does not affect the program's code or behavior -- it only controls visibility in the Run Programs list.
Default
The Default property is a boolean field that marks a program as the default. When you open the ToolBox editor, the default program loads automatically. Only one program should be marked as Default at a time.
This property is useful if you have a standard starting script that you work with regularly. It does not affect how the program appears in Run Programs.
WithExcelSheet
The WithExcelSheet property indicates that the program has an associated Excel file. When this property is enabled, the ExcelSheet blob field stores the Excel data.
Programs that use Excel typically fall into two categories:
- Input programs: The Excel file contains input data that the program reads during execution using
exgetfunctions. For example, a program that imports customer updates from an Excel template. - Output programs: The program writes results to the Excel file during execution using
exsetfunctions. For example, a program that generates a formatted data export.
Some programs use Excel for both input and output, reading data from certain cells and writing results to others.
To attach an Excel file to your program, use the Excel functionality in the ToolBox editor before saving the program. The Excel data is saved alongside the code when you save the program.
Public Sharing Permissions (Fields 300-302)
Fields 300 through 302 in the Program table provide granular control over how the program is shared publicly. These fields allow you to define specific sharing permissions beyond the basic Shared boolean.
Use these fields when you need fine-grained control over who can see and execute the program. The exact configuration depends on your organization's security requirements and how many users need access to each program.
Step 5: Sharing Programs with Users
Once your program is saved and configured, you need to make it available to the users who will run it. There are several approaches to sharing:
Basic Sharing with the Shared Property
The simplest approach is to set the Shared property to true. This makes the program visible in the Run Programs list for all users who have the appropriate permissions (either the SUPER role or the Run Programs permission set).
Targeted Sharing with Public Permissions
For more selective sharing, use the public sharing permission fields (300-302) to control exactly which users or groups can see and execute the program. This is useful when a program is relevant only to a specific department or role within your organization.
Program Storage Sync
Erik's ToolBox can synchronize your shared programs to an external backend — either Azure Blob Storage or a GitHub repository. This enables two important sharing scenarios:
- Backup: Your shared programs are backed up outside Business Central, protecting them against accidental deletion or environment issues. With the GitHub backend, every save is committed as a versioned
.alfile, so you also get full change history. - Cross-environment sharing: Programs synced to the backend can be pulled by other Business Central environments that point at the same Azure Storage account or GitHub repository. This is valuable when you have multiple environments (development, staging, production) and want a consistent set of shared programs across all of them.
To use program sync, first choose a backend under Program Storage in the ToolBox Setup page and give the environment a distinct NickName. Once configured, shared programs are pushed when you save and pulled when the ToolBox opens. See Program Storage for the configuration details.
The Programs Page
The Programs page provides a management view of all programs in the system. From this page, you can:
- Browse all programs with their names, sharing status, and other properties.
- Open a program in the ToolBox editor for editing by selecting it and choosing the appropriate action.
- Toggle sharing by changing the Shared property directly on the list.
- Delete programs that are no longer needed.
- Review properties to see which programs have Excel attachments, which are marked as Default, and which have specific sharing permissions configured.
The Programs is your primary tool for managing the library of programs available in your environment. You should review it periodically to ensure that shared programs are still relevant, remove outdated programs, and verify that sharing settings are correct.
Editing Existing Programs
To modify an existing program:
- Open the Programs page or navigate to the program through the ToolBox editor.
- Load the program into the ToolBox editor.
- Make your code changes.
- Test the modified script by pressing F9.
- Save the program using the Save action to update the existing record.
When you edit a shared program, be aware that your changes take effect immediately for all users the next time they run the program. If you need to make significant changes, consider using Save As to create a copy, testing the copy thoroughly, and then updating the original only when you are confident the changes are correct.
Best Practices for User-Facing Programs
Programs in Run Programs are executed by users who may not understand AL code or the internal workings of Business Central. Following these best practices ensures that your programs provide a good experience for end users.
Use Clear Message Output
Your program's message() calls are the only communication channel with the end user. Make them count:
// Good: Clear, informative output
message('Processing vendor invoices for %1...', WorkDate());
message('Found %1 invoices to process.', InvoiceCount);
message('Successfully processed %1 of %1 invoices.', SuccessCount, InvoiceCount);
// Bad: Cryptic or missing output
message('%1', Rec.Count);
Structure your output with headers, separators, and summaries so the user can quickly understand what happened. Use blank message('') calls to add visual spacing between sections.
Add Confirm Dialogs for Destructive Operations
If your program modifies or deletes data, use confirm() to give the user a chance to cancel before the operation proceeds:
if not confirm('This will delete %1 archived records. Continue?', false, ArchiveCount) then
error('Operation cancelled by user.');
This is especially important for programs that affect production data. The confirm dialog acts as a safety net, giving the user one final opportunity to verify that they want to proceed.
Note that confirm() dialogs do not work in Job Queue mode. If your program may be scheduled, include conditional logic that skips confirmation when running unattended. See Job Queue for details.
Handle Errors Gracefully
Instead of allowing the program to fail with a generic Business Central error, catch foreseeable problems and report them clearly:
if not Cust.Get(CustomerNo) then begin
message('Error: Customer %1 not found. Please verify the customer number.', CustomerNo);
error('');
end;
When an error occurs, provide enough context for the user to understand what went wrong and what they should do about it. Avoid technical jargon in error messages -- write them for the person who will be reading them.
Use Excel for Data Input and Output
When your program needs to process a list of items, import data, or generate a structured report, Excel is the ideal medium. Users are comfortable working with Excel, and the ToolBox's exget and exset functions make it straightforward to read from and write to Excel data:
var
Row : Integer;
ItemNo : Text;
begin
Row := 2; // Start after header row
while exget(Row, 1) <> '' do begin
ItemNo := exget(Row, 1);
// Process each item...
Row += 1;
end;
message('Processed %1 items from Excel.', Row - 2);
end;
Attach the Excel template to the program using the WithExcelSheet property so that end users always have the correct input format available.
Document What the Program Does
Include comments at the top of your program source code that explain its purpose, expected inputs, and behavior. While end users will not see these comments, other developers and administrators who maintain the program in the future will benefit from the documentation:
// Customer Balance Report
// Generates a summary of all customers with outstanding balances.
// Output: Console listing of customer number, name, and balance.
// No data modifications are made by this program.
// Last updated: 2025-01-15
Test Before Sharing
Always test your program thoroughly before setting the Shared property to true. Run it in a sandbox environment if possible, and verify that it handles all expected scenarios correctly. Once a program is shared, users may rely on it for their daily work, and unexpected failures can erode trust in the tools you provide.
Keep Programs Focused
Each program should do one thing well. If you find yourself creating a program that handles multiple unrelated tasks, consider splitting it into separate programs. This makes the Run Programs list easier to navigate and reduces the risk of unintended side effects.
Example: Creating a Complete Program
Here is a complete example of creating a program from start to finish.
Goal: Create a program that lists all items with inventory below their reorder point.
Step 1: Write the code in the ToolBox editor.
var
Item : Record Item;
Counter : Integer;
begin
message('=== Low Inventory Report ===');
message('Generated: %1', CurrentDateTime());
message('');
Item.SetFilter(Inventory, '<%1', Item."Reorder Point");
Item.SetFilter("Reorder Point", '>%1', 0);
if Item.FindSet() then begin
message('No.|Description|Inventory|Reorder Point');
message('---|-----------|---------|-------------');
repeat
message('%1|%2|%3|%4',
Item."No.",
Item.Description,
Item.Inventory,
Item."Reorder Point");
Counter += 1;
until Item.Next() = 0;
end;
message('');
if Counter = 0 then
message('All items are above their reorder points.')
else
message('Total items below reorder point: %1', Counter);
end;
Step 2: Test by pressing F9 and reviewing the output.
Step 3: Save the program as "Low Inventory Report" using Save As.
Step 4: Open the Programs, find "Low Inventory Report," and set Shared to true.
Step 5: Verify that end users with the Run Programs permission can see and execute the program.