Render to PDF and Images
Axyra Sheets includes a full rendering pipeline that lays out pages much like a spreadsheet application, honoring page setup, print areas, scaling, fonts, borders, charts, and images, and exports the result to PDF or image formats.
A PDF in one line
try (Workbook wb = Workbook.open(Path.of("report.xlsx"))) {
wb.renderPdf(Path.of("report.pdf"));
}
Controlling the output
PdfOptions is a builder. Everything is optional.
import io.keikai.axyra.sheets.io.PdfOptions;
PdfOptions options = PdfOptions.builder()
.title("Q3 Report")
.author("Finance")
.sheetNames("Summary", "Detail") // only these sheets
.pageRange("1-4") // only these pages
.watermark("CONFIDENTIAL")
.bookmarks(true) // one outline entry per sheet
.build();
wb.renderPdf(Path.of("report.pdf"), options);
To render into memory instead of onto disk:
byte[] pdf = wb.renderPdf(options);
Encryption and permissions
PdfOptions locked = PdfOptions.builder()
.userPassword("open-me") // required to open the document
.ownerPassword("owner") // required to change permissions
.allowPrint(true)
.allowCopy(false)
.allowModify(false)
.build();
Archival output
.pdfA(true) produces PDF/A output — fonts fully embedded, no encryption, no
transparency. It cannot be combined with the password options above.
Fonts
Rendering needs the fonts the workbook asks for. Point the engine at your font directories when the defaults are not enough:
PdfOptions.builder().fontDirs(List.of("/usr/share/fonts", "/opt/corp-fonts")).build();
The renderer scans the usual macOS and Linux font directories, but not
C:\Windows\Fonts; on Windows, pass that folder (or your application’s font
folder) in fontDirs. Metric-compatible substitutes are bundled for Calibri
(Carlito), Cambria (Caladea), and Arial (Liberation Sans). Other missing fonts
fall back to a different font, which changes line breaks, and CJK text needs
CJK fonts (such as Noto) installed. If output must be pixel-stable across
machines, ship the fonts.
Images
Per sheet, to any of six raster or vector formats:
import io.keikai.axyra.sheets.io.ImageOptions;
import io.keikai.axyra.sheets.io.Renderer;
ImageOptions image = ImageOptions.builder()
.scale(2.0) // 2× the nominal size
.gridLines(true) // draw grid lines even if the sheet hides them
.page(1) // one page of a multi-page sheet
.build();
int summary = wb.sheet("Summary").index(); // look the sheet up by name
byte[] png = wb.renderSheetPng(summary, image);
byte[] svg = wb.renderSheetSvg(summary, image);
// The Renderer facade covers the rest
byte[] jpg = Renderer.toJpeg(wb, summary, image);
byte[] tiff = Renderer.toTiff(wb, summary, image);
The methods take a sheet index. Resolve it from the sheet name: a file saved in
Evaluation Mode starts with an extra Axyra Evaluation Copy sheet, so index
0 is not necessarily your first sheet.
Use scale(...) for a multiple of the nominal size, or targetWidthPx(...) to
pin the output to an exact pixel width and let the engine derive the scale.
Page count
Useful for progress reporting, or for splitting a large render into chunks:
int pages = wb.sheetPageCount(wb.sheet("Summary").index());
HTML
Not a render, strictly — HTML export reproduces the sheet as a styled table rather than as paginated output. It is the right choice for previewing a sheet in a browser.
import io.keikai.axyra.sheets.io.HtmlOptions;
// The package shape Excel's "Save as Web Page" writes — report.html plus a
// report_files/ sidecar holding each sheet, the stylesheet and the images.
wb.saveHtml(Path.of("report.html"), HtmlOptions.create());
// Or one self-contained file: every sheet in it, every image inlined.
wb.saveHtml(Path.of("report.html"), HtmlOptions.create().singleFile(true));
The package is the default for a path, and the shape a multi-sheet workbook needs for its sheet tabs to work. Pick the single document when the file has to travel on its own.
Next
- Rendering — the full options reference, page-layout rules, and font resolution
- Developer Reference