Skip to content
sheetsmith

Complete example

A fictional service company produces a monthly report of the cases handled by its teams, in the corporate style shared by all its reports.

public enum CaseStatus implements Labelled {
OPEN("Open"), WAITING("Waiting for customer"), CLOSED("Closed");
private final String label;
CaseStatus(String label) { this.label = label; }
@Override public String label() { return label; }
}
@ExcelSheet(
title = "Case handling, September 2026",
titleStyle = "corp-title",
preset = TablePreset.LIGHT,
accentColor = "#0B3D5C",
styleSheets = CorporateStyles.class,
autoFilter = true,
header = @HeaderStyles(base = "corp-header"),
body = @BodyStyles(base = "corp-cell", firstColumn = "case-number"))
@ExcelStyle(name = "case-number", bold = Toggle.TRUE)
@ExcelStyle(name = "centered", align = Align.CENTER)
public record CaseRow(
@ExcelColumn(header = "Case", order = 10, width = 14) String number,
@ExcelColumn(header = "Opened on", order = 20, format = "dd/mm/yyyy",
styles = @ColumnStyles(base = "centered")) LocalDate openedOn,
@ExcelColumn(header = "Team", order = 30) String team,
@ExcelColumn(header = "Category", order = 40) String category,
@ExcelColumn(header = "Status", order = 50) CaseStatus status,
@ExcelColumn(header = "Due on", order = 60, format = "dd/mm/yyyy",
styles = @ColumnStyles(base = "centered")) LocalDate dueOn,
@ExcelColumn(header = "Days open", order = 70, format = "0") int daysOpen,
@ExcelColumn(header = "Charged", order = 80, styles = @ColumnStyles(base = "corp-money")) BigDecimal charged,
@ExcelColumn(header = "Notes", order = 90, width = 60) String notes) {
}

Spring configuration:

sheetsmith:
formats:
date: dd/mm/yyyy
document:
author: Example Services Ltd
application: Case Reporting
validation:
packages: com.example.reporting
@Configuration
class ReportingConfiguration {
@Bean
CellConverter<Labelled> labelConverter() {
return (value, context) -> CellValue.text(value.label());
}
}
@Service
class CaseReportService {
private final Sheetsmith sheetsmith;
private final CaseQueries queries;
CaseReportService(Sheetsmith sheetsmith, CaseQueries queries) {
this.sheetsmith = sheetsmith;
this.queries = queries;
}
void writeMonthlyReport(YearMonth month, OutputStream out) {
List<SheetData<?>> sheets = List.of(
SheetData.of("Cases", CaseRow.class, queries.cases(month)),
SheetData.of("By team", TeamSummaryRow.class, queries.summaryByTeam(month)));
sheetsmith.generate(sheets, out);
}
}

What the reader sees: a title in the corporate font; a header with bold text, a dark accent line and wrapped labels; light zebra rows separated by thin lines; bold case numbers; centred dates in dd/mm/yyyy; status labels instead of constant names; amounts right-aligned with two decimals; an auto-filter on every column; the file properties showing “Example Services Ltd” and “Case Reporting”. Styling that depends on the value of a cell, such as overdue cases in red, is not part of version 1.0.0: styles depend on the position of the cell, never on its content.