Class StreamWorkbook

java.lang.Object
io.keikai.axyra.sheets.io.StreamWorkbook
All Implemented Interfaces:
AutoCloseable

public final class StreamWorkbook extends Object implements AutoCloseable
Writes an XLSX file row by row, in memory that does not grow with the row count.

Use this when authoring a large export. The ordinary Workbook path builds the whole workbook in memory before writing a byte, which is the right trade when you need to read, edit, recalculate or lay out — and the wrong one when you are pouring a result set into a file. Each row here is serialized and deflated as it arrives; the engine holds one row at a time. Writing 1,000,000 rows of five columns costs the same memory as writing ten.

What you give up, in exchange:

  • Rows go out in ascending order and never come back. Committing row 5 after row 9 throws AxyraIoException: a streaming writer cannot rewind the file.
  • Values only — cell values, number formats, bold / italic. No charts, images, merges, conditional formats, comments or validation; those need the whole-workbook model. Reach for Workbook when you need them.
  • No recalculation. Formulas are written verbatim; supply the cached value with StreamRow.setFormula(int, String, double, int) if the consumer must see a number before opening in Excel.
  • Text is stored inline rather than in a shared string table, so heavily repeating text yields a larger file than the modeled writer produces. The table is what a streaming writer cannot afford: it must stay resident until the last sheet closes.

The file is complete only after close() (or finish()); a writer that is never closed leaves a partial file behind. Use try-with-resources:


 try (StreamWorkbook wb = StreamWorkbook.create(Path.of("report.xlsx"))) {
     int header = wb.addStyle(StreamStyle.defaults().withBold());
     int money  = wb.addStyle(StreamStyle.defaults().withNumberFormat("#,##0.00"));
     wb.startSheet("Sales");
     wb.row(0).addText("Customer", header).addText("Amount", header).commit();
     int r = 1;
     for (Order o : orders) {
         wb.row(r++).addText(o.customer()).addNumber(o.amount(), money).commit();
     }
 }
 

Not thread-safe: rows are ordered, so one writer belongs to one thread.

  • Method Details

    • create

      public static StreamWorkbook create(Path file)
      Opens a streaming writer on file, replacing it if it exists.

      Under license enforcement this counts as a file operation and the output is stamped as evaluation material, exactly as an ordinary save is.

      Parameters:
      file - the XLSX file to write
      Returns:
      the writer; close it to complete the file
      Throws:
      AxyraIoException - if the file cannot be created
    • addStyle

      public int addStyle(StreamStyle style)
      Registers a style and returns the index that cells pass as their style argument. Equal styles return the same index, so calling this per row costs a map lookup.
      Parameters:
      style - the style
      Returns:
      the style index; 0 is the default style
      Throws:
      IllegalStateException - if the writer is closed
      NullPointerException - if style is null
    • startSheet

      public void startSheet(String name)
      Closes any open sheet and starts a new one. Row order restarts, so the new sheet may begin at row 0. Sheet names follow Excel's rules (at most 31 characters, none of []:*?/\), but the engine writes what it is given and does not check them. Duplicate names are not checked either.
      Parameters:
      name - the sheet name
      Throws:
      IllegalArgumentException - if name is null or empty
      IllegalStateException - if the writer is closed
    • row

      public StreamRow row(int index)
      Begins row index of the current sheet and returns the shared row builder. The builder is reused across rows: fill it and call StreamRow.commit() before you ask for the next row. Cells of a row that was not committed are discarded.

      Rows must be strictly ascending within a sheet. Committing a row at or below the previous one, or at row 1,048,576 or above, makes StreamRow.commit() throw AxyraIoException.

      Parameters:
      index - the 0-based row index
      Returns:
      the shared row builder
      Throws:
      IllegalStateException - if no sheet was started or the writer is closed
      IllegalArgumentException - if index is negative
    • finish

      public void finish()
      Completes the package and closes the file. close() calls it, so call it directly only to surface a write failure at a chosen point.
      Throws:
      AxyraIoException - if no sheet was started or the file cannot be written
      IllegalStateException - if the writer is already finished or closed
    • close

      public void close()
      Finishes the workbook if it has not been finished already, so a normal try-with-resources exit produces a complete file.

      close can itself throw, for instance when no sheet was ever started; see finish(). A second call does nothing. The native writer is released in either case, so no handle leaks.

      Specified by:
      close in interface AutoCloseable
    • isFinished

      public boolean isFinished()
      Whether the package has been completed by finish() or close().