druvu-lib-excel
Describe the sheet once, get a file that opens in Excel looking finished. Rows in, and for each column a header and the value to show. Bold header that stays in view, filters, fitted column widths, dates that are dates, money that is money.
It writes. It does not read Excel files.
Try it
Save this as Report.java and run jbang Report.java. JBang fetches Java 25 and the library by itself.
///usr/bin/env jbang "$0" "$@" ; exit $?
//JAVA 25
//DEPS com.druvu:druvu-lib-excel:1.0.0
import com.druvu.excel.Excel;
import com.druvu.excel.Fill;
import com.druvu.excel.Style;
import java.math.BigDecimal;
import java.nio.file.Path;
import java.time.LocalDate;
import java.util.List;
public class Report {
record Invoice(String number, String customer, LocalDate due, BigDecimal amount, boolean paid) {}
public static void main(String[] args) throws Exception {
List<Invoice> invoices = List.of(
new Invoice("2026-041", "Familie Keller", LocalDate.of(2026, 9, 30), new BigDecimal("1840.50"), true),
new Invoice("2026-042", "Atelier Nord", LocalDate.of(2026, 10, 15), new BigDecimal("620.00"), false),
new Invoice("2026-043", "Praxis Weber", LocalDate.of(2026, 10, 31), new BigDecimal("2315.75"), false));
Excel.sheet("Invoices", invoices)
.column("Number", Invoice::number)
.column("Customer", Invoice::customer)
.column("Due", Invoice::due)
.column("Amount", invoice -> invoice.paid() ? Style.MONEY : Style.MONEY.withFill(Fill.ORANGE), Invoice::amount)
.column("Paid", Invoice::paid)
.save(Path.of("invoices.xlsx"));
System.out.println("invoices.xlsx written - open it in Excel.");
}
}
Everything public is in one package, com.druvu.excel: Excel, Sheet, Workbook, Style, Fill, Align.
What you get without asking
- a bold header row that stays in view while you scroll
- a filter on every column
- each column as wide as what it holds
- dates shown as dates, money as money, an empty cell where a value is missing
- a style per column, or chosen row by row:
Style.MONEY,.withBold(),.withFill(Fill.ORANGE), any Excel number format - several sheets in one file; a totals row is just one more row, styled bold
- rows are streamed, so a sheet can be far larger than the heap
With druvu-acc, a few lines turn a GnuCash book into a spreadsheet. Watch it done, start to finish.
What it refuses
Rather than write a file that is quietly wrong, it throws, and the message names the column or the sheet:
- a number Excel would round — more than 15 significant digits. Round it, or pass an identifier as text.
- a value with no Excel cell type — an
Instant, aList, an object of your own. Convert it in the value function. - a sheet without columns, two sheets with one name, or a sheet name Excel itself would reject.
Nothing is written until save. A refused write leaves no file behind, and a file already there is left untouched.
Install
On Maven Central. One runtime dependency, fastexcel. Java 25 or newer.
<dependency>
<groupId>com.druvu</groupId>
<artifactId>druvu-lib-excel</artifactId>
<version>1.0.0</version>
</dependency>
//DEPS com.druvu:druvu-lib-excel:1.0.0 (JBang script)
implementation("com.druvu:druvu-lib-excel:1.0.0") (Gradle)
With the Java module system: requires com.druvu.excel;
The full reference — every value type, every style, the totals-row recipe — is the README.
Something it almost does?
Open an issue, or write to me. If it is small and useful to more than you, I will often just build it.
Apache License 2.0.