Skip to content
sheetsmith

Sheet classes and columns

This section explains the mental model of the library. The precise reference of every element follows in sections 4 to 11.

A sheet class is a Java class or record annotated with @ExcelSheet. It describes one table: its optional title, its columns, its styles and its layout options.

A column is a field of the sheet class annotated with @ExcelColumn. Each column has a header text and an order. Fields without @ExcelColumn are ignored: export is opt-in, so adding a field to a class never adds a column by accident.

The data of a sheet is a list of instances of the sheet class (or of its subclasses). Each element becomes one data row, in list order. The first element is data row 1.

The pairing of a sheet name, a sheet class and a data list is a SheetData. A workbook is generated from an ordered list of SheetData.

List<SheetData<?>> workbook
├── SheetData("Customers", CustomerRow.class, customers) → sheet 1
└── SheetData("Orders", OrderRow.class, orders) → sheet 2
row 0 ┌──────────────────────────────────────────────┐
│ Title (optional, merged across all columns) │ title: no role, never framed
row 1 ├──────────┬──────────┬──────────┬─────────────┤
│ Header 1 │ Header 2 │ Header 3 │ Header 4 │ header row
row 2 ├──────────┼──────────┼──────────┼─────────────┤
│ data row 1 (odd, first row) │
row 3 │ data row 2 (even) │
row 4 │ data row 3 (odd) │
row 5 │ data row 4 (even, last row) │
└──────────┴──────────┴──────────┴─────────────┘
first column last column

Without a title, the header is row 0 of the sheet and the data starts on row 1. The title, when present, occupies exactly one row.

Every column declares an integer order. Columns appear from left to right in ascending order. Values must be unique within the sheet class, inherited columns included, but need not be consecutive. Numbering in steps of 10 (10, 20, 30) leaves room to insert columns later without renumbering. The order is mandatory because the Java reflection API does not guarantee the declaration order of fields.

Both records and ordinary classes can be sheet classes.

  • Records. @ExcelColumn is written on the record component. It applies to the component field, and the value is read through the component accessor.
  • Classes. @ExcelColumn is written on the field. The value is read through a public getter when a suitable one exists, otherwise directly from the field, even when the field is private. The exact rules are in section 4.2.1.
  • Inheritance. Annotated fields of superclasses are columns too. They are collected from the topmost superclass down to the sheet class and then sorted by order. @ExcelSheet is not inherited: every class passed to a SheetData carries its own @ExcelSheet. A superclass that only contributes columns does not need it. Named styles (@ExcelStyle) are not inherited either: they are read from the sheet class only.
  • Subclass instances. A SheetData of a sheet class accepts instances of its subclasses. The columns are always those of the sheet class passed as type.
  • A null field value produces an empty cell that keeps its resolved style, so fills and borders remain continuous along the row and the column. The converter is not called.
  • A null element in the data list is an error: it is reported as a SheetsmithGenerationException naming the sheet and the data row.