Data Export
File Starter supports three export modes:
- Export by template fields
- builds candidate fields from current model metadata
- defaults selected fields to the currently visible table columns
- lets the user change fields, file name, and sheet name
- generates
.xlsxworkbooks for front-end initiated exports
-
Export by file template
- uses an uploaded Excel template file with
{{ field }}placeholders - extracts variables from the template to determine which fields to query
- generates
.xlsxworkbooks by rendering the template with data
- uses an uploaded Excel template file with
-
Dynamic export
- exports without a template by providing fields and filters directly in the request
Built-in export supports three scopes:
Selected Rowsuses the current toolbar bulk selection idsCurrent Pageuses the current page id snapshot, notpageNumber/pageSizereplayAll Filtered Datareuses currentfilters/orders/groupBy/aggFunctions/effectiveDate
Front-end export is limited to 100000 records for a single request; over-limit scopes are disabled instead of truncated.
ExportTemplate Configuration Table
| Field | Type | Default | Description |
|---|---|---|---|
fileName | String | null | Export file name |
sheetName | String | null | Sheet name |
modelName | String | null | Model name to export |
customFileTemplate | Boolean | null | If true, use file template export mode; otherwise use field template mode |
fileId | Long | null | Template file id (required when customFileTemplate = true) |
filters | Filters | null | Default filters |
orders | Orders | null | Default orders |
customHandler | String | null | Spring bean name for CustomExportHandler |
enableTranspose | Boolean | null | Whether to transpose output (not implemented in starter) |
ExportTemplateField Configuration Table
| Field | Type | Default | Description |
|---|---|---|---|
templateId | Long | null | ExportTemplate id |
fieldName | String | null | Model field name (supports cascaded fields like deptId.name) |
customHeader | String | null | Custom column header |
sequence | Integer | null | Field order in export |
ignored | Boolean | null | Whether to ignore the field in output |
Cascaded Field Export
All three export modes support cascaded field references using dotted-path syntax (e.g. deptId.name, deptId.companyId.code).
This allows exporting fields from related models through ManyToOne/OneToOne associations.
Syntax: {field1}.{field2} or {field1}.{field2}.{field3} (up to 4 levels of cascade)
How it works:
- The ORM layer creates dynamic virtual fields for dotted-path references (via
MetaField.createDynamicField). - The field is split into 2 parts: the root ManyToOne/OneToOne field and the remaining path.
- The related model is queried with the remaining path as expand fields.
- For 3+ levels, the process recurses:
deptId.companyId.code→ queryDeptwith fieldcompanyId.code→ queryCompanywith fieldcode. - The resolved value is stored in the row map with the full dotted key (e.g.
deptId.companyId.code). - The column header defaults to the last field’s label (e.g. the label of
code), unlesscustomHeaderis set.
Rules:
- Maximum cascade depth: 4 levels (
BaseConstant.CASCADE_LEVEL = 4). - Each intermediate field must be ManyToOne or OneToOne type.
- The last field must be a stored field (not dynamic/computed).
ConvertType.DISPLAYis used, so option fields showitemNameand relation fields showdisplayName.
Example — Template export with cascaded fields:
ExportTemplateField configuration:
fieldName: "name" customHeader: null sequence: 1
fieldName: "deptId.name" customHeader: "Department" sequence: 2
fieldName: "deptId.managerId.name" customHeader: "Dept Manager" sequence: 3Example — Dynamic export with cascaded fields:
curl -X POST 'http://localhost:8080/export/dynamicExport?modelName=Employee' \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"fields": ["name", "deptId.name", "deptId.managerId.name"],
"filters": ["status", "=", "ACTIVE"],
"orders": ["name", "ASC"]
}
JSONResult Excel columns: Name | Department | Dept Manager
1. Export By Template Fields
- Configure ExportTemplate and ExportTemplateField
ExportTemplate key fields:
fileName,sheetName,modelNamefilters,orders,customHandler
ExportTemplateField key fields:
fieldName,customHeader,sequence,ignored
- Export by template
Endpoint:
POST /export/exportByTemplate?exportTemplateId={id}
Request body:
ExportParams(fields, filters, orders, agg, groupBy, limit, effectiveDate)
Example:
curl -X POST http://localhost:8080/export/exportByTemplate?exportTemplateId=2001 \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"fields": ["id", "name", "code", "status"],
"filters": ["status", "=", "ACTIVE"],
"orders": ["createdTime", "DESC"],
"limit": 200,
"groupBy": [],
"effectiveDate": "2026-03-03"
}
JSON2. Export By File Template (Upload Template File)
This mode uses an uploaded Excel template file with placeholders like {{ field }} or {{ object.field }}.
The system extracts variables from the template to decide which fields to query.
To use this mode, set customFileTemplate = true and fileId to the uploaded template file in ExportTemplate.
The same exportByTemplate endpoint is used; the system dispatches to file-template mode automatically based on the customFileTemplate flag.
Endpoint:
POST /export/exportByTemplate?exportTemplateId={id}
Example:
curl -X POST http://localhost:8080/export/exportByTemplate?exportTemplateId=2002 \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"filters": ["status", "=", "ACTIVE"],
"orders": ["createdTime", "DESC"],
"limit": 200
}
JSONFile template placeholder syntax:
{{ fieldName }}— replaced with the field value of each row{{ deptId.name }}— cascaded field reference (resolved by the ORM layer)- The
{{ }}syntax is normalized to underlying Fesod{}syntax before rendering
3. Dynamic Export
Export without a template by providing fields and filters directly.
Endpoint:
POST /export/dynamicExport?modelName={model}&fileName={fileName}&sheetName={sheetName}
Example:
curl -X POST 'http://localhost:8080/export/dynamicExport?modelName=Product&fileName=Products&sheetName=Sheet1' \
-H 'Content-Type: application/json' \
-d @- <<'JSON'
{
"fields": ["id", "name", "code", "status"],
"filters": ["status", "=", "ACTIVE"],
"orders": ["createdTime", "DESC"],
"limit": 200,
"groupBy": [],
"effectiveDate": "2026-03-03"
}
JSON4. Custom Export Handler
You can register a Spring bean implementing CustomExportHandler and reference it by name in
ExportTemplate.customHandler.
import io.softa.starter.file.excel.export.support.CustomExportHandler;
@Component("productExportHandler")
public class ProductExportHandler implements CustomExportHandler {
@Override
public void handleExportData(List<Map<String, Object>> rows) {
// custom post-processing
}
}Contract:
- You may update row values in place.
- You should not replace row map objects.