Call RecordListToExcel (Logic tab → System → ExcelUtils) with your record list to get a Binary Data Excel file, then pass it to the Download action with filename and MimeType 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'. Both actions are built into OutSystems — no Forge component required for basic Excel export.
Excel Export with RecordListToExcel
Exporting data to Excel is one of the most common requests in business applications. OutSystems includes RecordListToExcel as a built-in system action that converts any record list to an .xlsx file in one call. This tutorial covers the complete pattern from clicking Export to downloading the file, including column customization and large dataset considerations.
Prerequisites
- A Reactive Web App with at least one entity (e.g., Employee with FullName, Email, Department)
- Service Studio open with the Logic tab visible
- Basic familiarity with Server Actions and calling them from Client Actions
Step-by-step guide
Create the Export Server Action
Create the Export Server Action
Logic tab → Server Actions → right-click → 'Add Server Action'. Name it 'ExportEmployeesToExcel'. The action needs no input parameters for a full export, or add filter inputs (e.g., DepartmentId, DateFrom) if you want a filtered export. Action flow: Start → GetAllEmployees (Aggregate — fetch the data to export) → RecordListToExcel → Download → End First, set up the Aggregate: drag Aggregate from the Toolbox into the flow. Double-click to configure → drag Employee entity into Sources. Set Max Records to 10000 (or your expected max — see performance notes below). Close the Aggregate editor. Note: RecordListToExcel is in Logic tab → System → ExcelUtils. Drag it into the flow after the Aggregate.
Expected result: ExportEmployeesToExcel Server Action is created with Aggregate and RecordListToExcel nodes.
Configure the RecordListToExcel action
Configure the RecordListToExcel action
Select the RecordListToExcel node in the action flow. In the Properties Panel, set the input parameters: - RecordList: GetAllEmployees.List (your aggregate's output list) That is the only required input. RecordListToExcel automatically: - Uses attribute names as column headers - Includes all attributes in the record list - Generates an .xlsx format file Output parameter: - File: Binary Data (the generated Excel file content) To customize column headers, you need a Structure. Create a Structure in Data tab → Structures → Add Structure with only the attributes you want exported, then fetch into that structure in the Aggregate. Column headers in the Excel file will match the Structure attribute names.
1/* RecordListToExcel parameters */2RecordList: GetAllEmployees.List34/* Output */5File: Binary Data (access as RecordListToExcel.File)67/* For custom columns, create a Structure */8/* Data tab → Structures → Add Structure 'EmployeeExportRow' */9/* Add attributes: FullName (Text), Email (Text), Department (Text) */10/* Fetch into this structure in the aggregate using calculated attributes */Expected result: RecordListToExcel.File contains the Excel binary data after this node executes.
Add the Download action to serve the file
Add the Download action to serve the file
After RecordListToExcel in the action flow, drag the Download action from Logic tab → System into the flow. Set the Download action parameters: - FileContent: RecordListToExcel.File - FileName: 'Employees_' + FormatDate(CurrDate(), 'yyyyMMdd') + '.xlsx' - MimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' The complete action flow: Start → GetAllEmployees (Aggregate) → RecordListToExcel (RecordList=GetAllEmployees.List) → Download (FileContent=RecordListToExcel.File, FileName='Employees.xlsx', MimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet') → End
1/* Download action parameters */2FileContent: RecordListToExcel.File3FileName: "Employees_" + FormatDate(CurrDate(), "yyyyMMdd") + ".xlsx"4MimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"56/* Full flow summary */7Start8 --> Aggregate: GetAllEmployees (Max Records: 10000)9 --> RecordListToExcel: RecordList = GetAllEmployees.List10 --> Download: FileContent = RecordListToExcel.File11 FileName = "Employees_" + FormatDate(CurrDate(), "yyyyMMdd") + ".xlsx"12 MimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"13 --> EndExpected result: The Download action terminates the server response with the Excel file. The browser receives the file and shows a download dialog.
Add an Export button to the screen
Add an Export button to the screen
In the Screen Editor, add a Button widget to the screen. Set its Label to 'Export to Excel'. Right-click → 'Add OnClick Client Action'. In the Client Action flow: Start → ExportEmployeesToExcel (Server Action) → End The Download action inside ExportEmployeesToExcel terminates the response — no additional navigation is needed in the Client Action after the call. For filtered exports, add input parameters to ExportEmployeesToExcel (e.g., DepartmentId) and map the currently selected filter values from the screen when calling the Server Action: Start → ExportEmployeesToExcel (DepartmentId = SelectedDepartmentId) → End
Expected result: Clicking the 'Export to Excel' button downloads an Excel file with all employee records. The file opens in Excel showing rows with attribute names as headers.
Customize columns with a Structure
Customize columns with a Structure
By default RecordListToExcel exports all attributes from the aggregate. To control which columns appear (and in what order), define a Structure with only the desired attributes. Data tab → Structures → right-click → Add Structure. Name it 'EmployeeExportRow'. Add attributes: - FullName: Text - Department: Text - Email: Text - HireDate: Date In the GetAllEmployees Aggregate, add calculated attributes matching the Structure: - Click 'New Attribute' in the Aggregate editor - Name: FullName, Value: Employee.FirstName + ' ' + Employee.LastName - Name: Department, Value: Department.Name (requires joining the Department entity) - etc. Then map the aggregate list to the Structure list before passing to RecordListToExcel. Use a For Each + Assign pattern or use a List Append approach to build the export list.
1/* Structure: EmployeeExportRow2 Attributes: FullName (Text), Department (Text), Email (Text), HireDate (Date) */34/* In Server Action - build export list */5Assign: ExportList = GetAllEmployeesWithDept.List6 /* GetAllEmployeesWithDept aggregate joins Employee + Department */7 /* and has calculated attributes matching EmployeeExportRow */89/* RecordListToExcel reads the structure attribute names as column headers */10RecordListToExcel: RecordList = ExportListExpected result: The exported Excel file shows only the four specified columns in the order defined by the Structure, with clean attribute names as headers.
Complete working example
1/* ============================================================2 SERVER ACTION: ExportEmployeesToExcel3 Input: DepartmentId (Department Identifier) - optional filter4 Output: none (Download action terminates response)5 ============================================================ */6Start7 --> Aggregate: GetEmployeesForExport8 Source: Employee join Department (Only With)9 Filter: If(DepartmentId = NullIdentifier(), True,10 Employee.DepartmentId = DepartmentId)11 Calculated Attributes:12 FullName = Employee.FirstName + " " + Employee.LastName13 Department = Department.Name14 Email = Employee.Email15 HireDate = Employee.HireDate16 Sort: Employee.LastName Ascending17 Max Records: 500001819 --> If: GetEmployeesForExport.List.Empty20 [True] --> Raise UserException: "NoData"21 Message = "No employees match the selected filter."2223 --> RecordListToExcel:24 RecordList: GetEmployeesForExport.List2526 --> Download:27 FileContent: RecordListToExcel.File28 FileName: "Employees_" + FormatDate(CurrDate(), "yyyyMMdd") + ".xlsx"29 MimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"3031 --> End3233Exception Handler (User Exception: NoData)34 --> (bubble up to Client Action for user message)35 --> End3637/* ============================================================38 CLIENT ACTION: ButtonExportOnClick39 ============================================================ */40Start41 --> ExportEmployeesToExcel: DepartmentId = SelectedDepartmentId42 --> End4344Exception Handler (User Exception: NoData)45 --> Message: ExceptionMessage (Warning)46 --> EndCommon mistakes
Why it's a problem: Calling the Export Server Action directly from another Server Action and expecting the download to reach the browser
How to avoid: The Download action must be triggered from a Client Action → Server Action chain that originated from a user interaction. Server-to-server calls that include Download do not reach the browser. Always wire Export to a button OnClick Client Action.
Why it's a problem: Not setting Max Records on the source Aggregate, causing a full table scan
How to avoid: RecordListToExcel loads the entire list into memory. Without Max Records, exporting a 500,000-row table crashes the server with an out-of-memory error. Set a practical Max Records limit (e.g., 50000) and document it. For larger exports, use a scheduled export to file pattern.
Why it's a problem: Using 'application/xls' as the MimeType for .xlsx files
How to avoid: The correct MIME type for modern Excel (.xlsx) files is 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'. Using 'application/xls' causes Excel to show 'The file format does not match the extension' warning on open.
Why it's a problem: Expecting column headers to be human-readable when attribute names are camelCase database identifiers
How to avoid: RecordListToExcel uses attribute names directly as headers. Create a Structure with readable names (FullName not 'empfullnm', HireDate not 'dtehire') to control the header row content.
Best practices
- Always set Max Records on the Aggregate feeding RecordListToExcel — exporting without a limit on a large table can cause out-of-memory errors on the server.
- Raise a User Exception and show a message when the filtered result is empty, rather than downloading a blank Excel file.
- Use a dynamic filename with FormatDate(CurrDate(), 'yyyyMMdd') so users can distinguish multiple exports by date.
- For exports over 50,000 rows, consider generating the file asynchronously with a Timer and providing a download link instead of blocking the HTTP request.
- Join related entities in the Aggregate (Employee + Department) rather than running multiple queries — keep the export logic in a single well-structured Aggregate.
- Always use the correct MIME type for .xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'. Using 'application/xls' or 'application/excel' may cause Excel to show format warnings.
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
Show me how to export data to Excel in OutSystems 11 using RecordListToExcel. I have an Employee entity with FirstName, LastName, Email, DepartmentId. Walk through: (1) creating an ExportEmployeesToExcel Server Action with an Aggregate, (2) calling RecordListToExcel with the aggregate list, (3) calling the Download action with the correct MIME type for .xlsx, (4) wiring a button OnClick Client Action. Include the dynamic filename pattern using FormatDate.
Add an Excel export button to my OutSystems employee list screen. Create ExportEmployeesToExcel Server Action that: fetches employees joined with Department (Max Records: 10000), with optional DepartmentId filter; calls RecordListToExcel with the list; calls Download with FileName = 'Employees_' + FormatDate(CurrDate(), 'yyyyMMdd') + '.xlsx' and the correct xlsx MimeType. Wire a ButtonExport OnClick Client Action to call it.
Frequently asked questions
Can I format cells in the exported Excel file (bold headers, colors)?
RecordListToExcel generates a plain .xlsx file with no cell formatting — just data in rows. For styled exports (bold headers, colored rows, merged cells), use the OutSystems Excel Utilities or OfficeUtils Forge components, or generate the file via a third-party library exposed through an Integration Studio extension (O11) or External Library (ODC).
How do I export multiple sheets in one Excel file?
RecordListToExcel only creates single-sheet files. For multi-sheet exports, use the OfficeUtils Forge component or the XlsxUtils component from the OutSystems Forge marketplace, which provides AddSheet and AddRow actions for building complex workbooks.
Does RecordListToExcel work in ODC?
Yes. RecordListToExcel and the Download action are built-in system actions available in both O11 and ODC. The action signature and MIME type are identical. Access it in ODC Studio via Logic tab → System → ExcelUtils.
How do I export dates in a specific format in the Excel file?
RecordListToExcel exports Date values as Excel date serial numbers, which Excel displays using its own date formatting. To control the format, convert the Date to Text using FormatDate() in a calculated attribute of your Aggregate (e.g., HireDateFormatted = FormatDate(Employee.HireDate, 'dd/MM/yyyy')). The column then exports as Text with your format, which prevents Excel from auto-reformatting it.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation