Class StreamingXlsxFormatter

java.lang.Object
io.jmix.reports.yarg.formatters.impl.AbstractFormatter
io.jmix.reports.yarg.formatters.impl.StreamingXlsxFormatter
All Implemented Interfaces:
ReportFormatter, StreamingReportFormatter
Direct Known Subclasses:
JmixStreamingXlsxFormatter

public class StreamingXlsxFormatter extends AbstractFormatter implements StreamingReportFormatter
Streaming XLSX report formatter built on Apache POI SXSSF. Writes the sheet strictly top-to-bottom; all post-processing is computed at row-write time because flushed rows cannot be revisited. The template is read with XSSF (templates are small); result rows are created through SXSSFWorkbook and flushed to disk outside the sliding window, so the heap footprint of the output document stays bounded regardless of the row count. The engine is selected for reports that mark a band as streaming (see ReportBand#getStreaming()); the non-streaming XlsxFormatter remains the default.

Supported (everything computable at the moment a row is written):

  • ${alias} fields with value typing and formats matching the non-streaming engine (strings, numbers, booleans, dates, times, format strings, multi-alias text), with one documented exception for very large integers noted below;
  • horizontal bands, multi-row band blocks, nested bands, sibling bands, empty bands;
  • merged cells: those inside a band are replicated and shifted per instance, those on static rows outside any band are carried over (shifted to the row's output position);
  • in-row formulas (e.g. =B2*C2), references shifted per instance;
  • trailing aggregate formulas below the data (SUM(A1:A1) grows over all rendered rows; an aggregate over an empty band renders the same error text as the non-streaming engine); single references below the data re-base onto the band's last rendered instance, references to static rows onto the row's final position; sheet-qualified references are never rewritten;
  • row grouping (outline levels), conditional formatting, sheet-name and header substitution;
  • hint_style_<param> dynamic named cell styles and hint_rowAutoHeight;
  • template freeze panes, page/print setup, user-defined names, the print area (re-based onto the rendered rows), data validations, and column widths, hidden state and column-level styles (copied to the result workbook).

Not supported (fundamental to forward-only writing — the non-streaming engine must be used instead):

  • formulas referencing forward (a total above the data): a reference to a band laid out below the formula is rejected with an error; sideways references across bands;
  • an aggregate below a band whose rendered rows are interleaved with a child band's rows (a master-detail layout) when the aggregate sums a column shared by both bands: the grown range is one contiguous span from the first to the last rendered master row, so it also covers the detail rows in between. This is harmless when master and detail occupy different columns (the extra cells are empty), but over-counts when they share the summed column;
  • pre-evaluation of formula values: when converting to PDF/CSV/HTML the formula cells stay unevaluated until the file is opened in Excel (the workbook carries <calcPr fullCalcOnLoad="1"/>);
  • vertical and cross bands, side-by-side blocks and nested band rectangles (all rejected with an error), complex master-detail layouts;
  • multi-sheet templates (rejected with an error; only single-sheet templates are supported);
  • content inliners (${bitmap:WxH}, ${image:WxH}, ${html}) — rejected with an error;
  • hyperlinks (SXSSF does not carry them over from the template);
  • theme-palette colors: a template that paints cells with Office theme colors (the top row of Excel's colour picker) loses them — the streamed result workbook has no theme part, so Excel falls back to the default Office palette. Use explicit RGB or indexed colors in the template, or the non-streaming engine, to preserve brand theme colors (RGB and indexed colors are unaffected);
  • charts and pivot tables.

Known behavioral differences from the non-streaming engine: hint_rowAutoHeight sets a fixed measured height (SXSSF cannot emit customHeight="false", so Excel does not re-measure on open); parent/child band nesting is derived from the template row order, so a child band's named range must be laid out below its parent's and a sibling band laid out between a parent and its child is rejected with an error rather than silently reordered; an integer value beyond a double's exact range (2^53) is written as a rounded double, because POI sets a numeric cell only through a double, whereas the non-streaming engine keeps the exact digits in the raw file (give the field a format or select the value as a string to keep it exact); and data-validation regions, which are copied verbatim, keep their template positions — they are not re-based as bands expand.

Data feeding: when the report's streaming band is backed by a sql or jpql dataset, its rows are pulled from a live database cursor inside an open transaction (see StreamingBandFeed and StreamingReportDataLoader); the band must be horizontal, single-dataset and childless, other loader types (groovy, json) are rejected. Conditional formatting over the fed band is applied as one contiguous range covering the whole rendered span. A hint_rowAutoHeight range over a fed band measures every streamed row's text with an AWT layout pass: this stays O(1) in memory but costs CPU per row, so a large fed export with auto-height is measurably slower.

Output types: xlsx is written directly to the output stream. csv is derived from the streamed workbook by a single SAX pass over a temp file (StreamingXlsxToCsvWriter), so it stays O(1) in memory at any size. pdf/html go through the office DocumentConverter and load the whole workbook bytes, so they are practically limited by what the office process can handle; formula cells stay unevaluated in all converted outputs.

  • Field Details

    • HINT_NAME_PREFIX

      protected static final String HINT_NAME_PREFIX
      See Also:
    • STYLE_HINT_PREFIX

      protected static final String STYLE_HINT_PREFIX
      See Also:
    • ROW_AUTO_HEIGHT_HINT

      protected static final String ROW_AUTO_HEIGHT_HINT
      See Also:
    • BUILT_IN_NAME_PREFIX

      protected static final String BUILT_IN_NAME_PREFIX
      Prefix of Excel built-in defined names: Print_Area, _FilterDatabase, Print_Titles, ...
      See Also:
    • RESERVED_NAMES

      protected static final Set<String> RESERVED_NAMES
      Reserved built-in name labels POI may expose without the _xlnm prefix; never copied as user names.
    • SPREADSHEET_ML_NS

      protected static final String SPREADSHEET_ML_NS
      See Also:
    • NANOS_PER_DAY

      protected static final double NANOS_PER_DAY
      See Also:
    • MAX_ROW_HEIGHT

      protected static final double MAX_ROW_HEIGHT
      Max row height in Excel, in points (mirrors the non-streaming RowAutoHeightXlsxHint).
      See Also:
    • DEFAULT_FONT_SIZE

      protected static final int DEFAULT_FONT_SIZE
      See Also:
    • rowAccessWindowSize

      protected int rowAccessWindowSize
      SXSSF sliding window; large enough to cover a single band's multi-row block.
    • maxResultRows

      protected int maxResultRows
      Hard row cap of the .xlsx format; exceeding it is rejected with a clear error, not a raw POI throw.
    • templateWorkbook

      protected org.apache.poi.xssf.usermodel.XSSFWorkbook templateWorkbook
    • resultWorkbook

      protected org.apache.poi.xssf.streaming.SXSSFWorkbook resultWorkbook
    • templateBands

      protected Map<String,TemplateBand> templateBands
    • templateMerges

      protected List<org.apache.poi.ss.util.CellRangeAddress> templateMerges
    • styleCache

      protected StreamingStyleCache styleCache
    • renderedBandRows

      protected Map<String,int[]> renderedBandRows
      Band name -> [first, last] output row (0-based) actually rendered for the band, across all instances.
    • lastInstanceStarts

      protected Map<String,Integer> lastInstanceStarts
      Band name -> output row where the band's LAST rendered instance starts.
    • staticRowOutputs

      protected Map<Integer,Integer> staticRowOutputs
      Template row (static, outside bands) -> output row it was written to.
    • evaluationWorkbook

      protected org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook evaluationWorkbook
      Parse/render context for formula tokens; sheet index 0 (single-sheet templates only).
    • styleHints

      protected List<StreamingXlsxFormatter.HintRange> styleHints
      hint_style_<param> template ranges: cells whose style name comes from band data.
    • rowAutoHeightHints

      protected List<StreamingXlsxFormatter.HintRange> rowAutoHeightHints
      hint_rowAutoHeight template ranges: rows whose height is measured from the written text.
    • fontRenderContext

      protected FontRenderContext fontRenderContext
    • streamingBandFeed

      protected @Nullable StreamingBandFeed streamingBandFeed
      Optional supply of the hot band's rows from a live cursor; see StreamingBandFeed.
    • reportBandNames

      protected @Nullable Set<String> reportBandNames
      All band names of the report definition; when null, names are derived from the band data tree.
    • documentConverter

      protected @Nullable DocumentConverter documentConverter
      Office converter for pdf/html output; when absent those output types fail with a clear error.
    • templateConditionalFormattings

      protected List<org.openxmlformats.schemas.spreadsheetml.x2006.main.CTConditionalFormatting> templateConditionalFormattings
      Template conditional formattings, re-targeted onto rendered ranges after the walk.
    • cfTrackedBands

      protected Set<String> cfTrackedBands
      Bands referenced by conditional formatting; only these track per-instance start rows.
    • bandInstanceStarts

      protected Map<String,List<Integer>> bandInstanceStarts
      Band name -> first output row of each rendered instance (only for cfTrackedBands).
    • bandLayouts

      Band name -> precomputed render plan of the band's template rectangle.
    • childBandNames

      protected Map<String,Set<String>> childBandNames
      Band name -> names of its direct child bands, derived from the band data tree.
    • namedStyleXfIds

      protected Map<String,Integer> namedStyleXfIds
      Template named cell style name -> index into cellStyleXfs.
    • namedResultStyles

      protected Map<String,org.apache.poi.ss.usermodel.CellStyle> namedResultStyles
      Template named cell style name -> materialized result-workbook style.
  • Constructor Details

  • Method Details

    • setDocumentConverter

      public void setDocumentConverter(@Nullable DocumentConverter documentConverter)
    • setRowAccessWindowSize

      public void setRowAccessWindowSize(int rowAccessWindowSize)
      Must be set before consumeData(); the window is fixed once the result workbook exists.
    • setMaxResultRows

      public void setMaxResultRows(int maxResultRows)
    • setStreamingBandFeed

      public void setStreamingBandFeed(@Nullable StreamingBandFeed streamingBandFeed)
      Description copied from interface: StreamingReportFormatter
      Injects the feed that supplies the streaming band's rows. Must be set before StreamingReportFormatter.consumeData().
      Specified by:
      setStreamingBandFeed in interface StreamingReportFormatter
    • setReportBandNames

      public void setReportBandNames(@Nullable Set<String> reportBandNames)
      Description copied from interface: StreamingReportFormatter
      Supplies the full set of band names of the report definition, so the template parser can distinguish band named ranges from service/user defined names even for bands that produced no data. Optional — implementations may fall back to names derivable from the band data tree, hence the no-op default.
      Specified by:
      setReportBandNames in interface StreamingReportFormatter
    • renderDocument

      public void renderDocument()
      Description copied from interface: ReportFormatter
      Creates document and serializes it to predefined stream (or something like this)
      Specified by:
      renderDocument in interface ReportFormatter
    • consumeData

      public void consumeData()
      Description copied from interface: StreamingReportFormatter
      First phase: consumes band data (including the streaming feed) and builds the result document. Must be called inside the streaming loader's callback, while the feed's cursor is alive.
      Specified by:
      consumeData in interface StreamingReportFormatter
    • discard

      public void discard()
      Description copied from interface: StreamingReportFormatter
      Releases the partially built result (e.g. SXSSF spool files) without writing it. Safe to call at any phase and more than once; used by the engine when the streaming loader fails after the render callback succeeded, so temp files do not outlive the report run. Implementations that hold no intermediate resources may make this a no-op, but must still implement it so the release contract is explicit.
      Specified by:
      discard in interface StreamingReportFormatter
    • disposeResultWorkbook

      protected void disposeResultWorkbook()
      Disposes the result workbook (deleting its spool files) exactly once; null-safe and idempotent.
    • closeTemplateWorkbook

      protected void closeTemplateWorkbook()
      Releases the template workbook (and its backing OPCPackage). Best-effort and idempotent.
    • completeRendering

      public void completeRendering()
      Description copied from interface: StreamingReportFormatter
      Second phase: writes or converts the built document to the output stream and releases resources. Runs after the loader callback returns, so it must not touch the feed.
      Specified by:
      completeRendering in interface StreamingReportFormatter
    • convertStreamedWorkbook

      protected void convertStreamedWorkbook() throws IOException
      Non-xlsx output: the workbook is always streamed to a temp file first (formula values stay unevaluated), then converted. CSV is derived with a single SAX pass (O(1) memory); PDF/HTML go through the office DocumentConverter and are practically limited by what the office process can chew.
      Throws:
      IOException
    • validateBandTree

      protected void validateBandTree()
      The streaming engine writes strictly top-to-bottom, so structures that require revisiting flushed rows are rejected up front with a clear error instead of producing a corrupt document.
    • rejectUnsupportedBandOrientations

      protected void rejectUnsupportedBandOrientations(BandData band)
    • rejectOverlappingBands

      protected void rejectOverlappingBands()
      Two bands whose template rows overlap cannot both be rendered forward-only: the top-to-bottom walk emits each template row once, so a band sharing another band's rows (side-by-side blocks, or one band rectangle nested inside another) would be silently dropped or double-counted. Reject such a layout up front. Parent/child bands never overlap — a child's range sits below its parent's.
    • rejectMisplacedChildBands

      protected void rejectMisplacedChildBands()
      A child band renders attached to its parent instance, so its template rows must sit below the parent's. A child laid out above its parent cannot be rendered forward-only (its rows would have to be written before the parent) and rejectOverlappingBands() does not catch it when the two ranges do not overlap — it would otherwise be silently dropped. Reject it up front instead.
    • finalizeWorkbook

      protected void finalizeWorkbook()
      Formula values are not pre-evaluated by the streaming engine, so the workbook asks Excel to run a full recalculation on open. POI does not emit the optional <calcPr/> element by itself.
    • normalizeTemplateRows

      protected byte[] normalizeTemplateRows(byte[] xlsxBytes)
      Merges duplicate <row> elements (same r) in each worksheet part into one row. The report wizard's docx4j engine emits every cell in its own <row r="N"> element; POI keeps only the last such element when reading, dropping all columns but the one it carries. Normalizing the template bytes before POI reads them restores the full row. A well-formed template (one <row> per index) is returned unchanged, so it pays only a scan.
    • mergeDuplicateRows

      protected @org.jspecify.annotations.Nullable byte[] mergeDuplicateRows(byte[] sheetXml)
      Collapses duplicate <row> elements in one worksheet part, appending the cells of each duplicate to the first row with that index. Returns the rewritten XML, or null when the sheet has no duplicate rows (nothing to change).
    • init

      protected void init()
    • parseConditionalFormattings

      protected void parseConditionalFormattings()
    • bandContainingRows

      protected @Nullable TemplateBand bandContainingRows(org.apache.poi.ss.util.CellRangeAddress range)
      The band whose template rows fully cover the range's rows, or null when the range sits on static rows. Only rows matter for conditional-formatting re-targeting: a rule may legitimately be one or more columns wider than the band's named range, and its columns are kept as authored.
    • parseTemplateBands

      protected void parseTemplateBands()
      Bands are defined in the template as workbook named ranges whose name equals the band name. Defined names prefixed with hint_ carry per-cell processing hints, not bands. Excel service names (_xlnm.Print_Area, _xlnm._FilterDatabase, _xlnm.Print_Titles) and names that do not match any report band (e.g. named constants) are ignored — treating them as bands would silently skip template rows or fail on multi-area references.
    • styleHintParamName

      protected String styleHintParamName(String definedName)
      The style parameter from a hint_style_<param> defined name: the first underscore-separated segment after the prefix. A trailing _<n> that only makes the defined name unique (Excel forbids duplicate names, e.g. hint_style_col_2) is not part of the parameter. Mirrors the non-streaming CustomCellStyleXlsxHint, which splits on _ and takes the first segment.
    • toHintRange

      protected StreamingXlsxFormatter.HintRange toHintRange(org.apache.poi.ss.usermodel.Name name, String param)
    • resolveBandNames

      protected Set<String> resolveBandNames()
      Band names the template walk recognizes: the report definition names supplied by the engine (covers bands that produced no data), plus everything derivable from the band data tree and the streaming feed for direct formatter usage.
    • collectBandDataNames

      protected void collectBandDataNames(BandData band, Set<String> names)
    • parseNamedStyles

      protected void parseNamedStyles()
      Reads the template's named cell styles (cellStyles in xl/styles.xml). The typed CTCellStyle classes are absent from poi-ooxml-lite, so the mapping is extracted with an XmlBeans cursor over the stylesheet document.
    • writeWorkbook

      protected void writeWorkbook()
    • applyConditionalFormattings

      protected void applyConditionalFormattings()
      Re-targets template conditional formattings onto the rendered rows: a rule range fully inside a band rectangle is replicated per rendered band instance (mirrors the non-streaming sqref re-mapping); ranges outside any band are kept as is. Conditional formatting lives in the sheet part, not in the streamed row window, so adding it after the walk is safe.
    • applyStaticMerges

      protected void applyStaticMerges(org.apache.poi.xssf.streaming.SXSSFSheet resultSheet)
      Adds template merged regions that lie entirely on static rows outside any band (e.g. a merged title or footer). A region overlapping a band is skipped here: one fully inside a band is replicated per instance while the band renders, and one that partially overlaps a band has no well-defined extent once the band expands. Static rows may have shifted down as bands above them grew, so each endpoint is re-based onto the row's actual output position.
    • overlapsAnyBand

      protected boolean overlapsAnyBand(org.apache.poi.ss.util.CellRangeAddress range)
      Whether any template row the range covers belongs to a band (a full or partial band overlap).
    • lastTemplateRowToWalk

      protected int lastTemplateRowToWalk(org.apache.poi.xssf.usermodel.XSSFSheet templateSheet)
      The last template row the top-to-bottom walk must visit. A merged region may extend below the last row that holds a cell (its lower cells are empty and have no Row object), so it is included here: otherwise those rows get no staticRowOutputs entry and applyStaticMerges(org.apache.poi.xssf.streaming.SXSSFSheet) would shift one merge endpoint while leaving the other on its template row (an inverted or collapsed box).
    • bandStartingAt

      protected @Nullable TemplateBand bandStartingAt(int templateRow)
    • copyColumnWidths

      protected void copyColumnWidths(org.apache.poi.xssf.usermodel.XSSFSheet from, org.apache.poi.xssf.streaming.SXSSFSheet to)
    • copyColumnStyles

      protected void copyColumnStyles(org.apache.poi.xssf.usermodel.XSSFSheet from, org.apache.poi.xssf.streaming.SXSSFSheet to)
      Copies column-level default styles (e.g. a whole-column number format) declared in the template's <cols> definitions. Only columns that explicitly set a style are copied — the usermodel getColumnStyle returns the workbook default for unstyled columns, which must not be propagated. CTCol min/max are 1-based.
    • copyTemplateSettings

      protected void copyTemplateSettings(org.apache.poi.xssf.usermodel.XSSFSheet templateSheet, org.apache.poi.xssf.streaming.SXSSFSheet resultSheet)
      Carries over sheet- and workbook-level template settings that the fresh result workbook would otherwise lose (the non-streaming engine renders on a template copy and keeps them for free): freeze panes, page/print setup and user-defined names. The print area is carried over once the rows are written, see copyPrintArea(). Other coordinate-based settings are copied with their template positions; they are not re-based as bands expand (a documented limitation).
    • copyDataValidations

      protected void copyDataValidations(org.apache.poi.xssf.usermodel.XSSFSheet from, org.apache.poi.xssf.streaming.SXSSFSheet to)
      Copies the template's data validations (e.g. drop-down lists) onto the result sheet. The validation regions keep their template coordinates and are not re-based as bands expand.
    • copyFreezePane

      protected void copyFreezePane(org.apache.poi.xssf.usermodel.XSSFSheet from, org.apache.poi.xssf.streaming.SXSSFSheet to)
    • copyPrintSetup

      protected void copyPrintSetup(org.apache.poi.xssf.usermodel.XSSFSheet from, org.apache.poi.xssf.streaming.SXSSFSheet to)
    • insertPrintText

      protected @Nullable String insertPrintText(@Nullable String text)
      Substitutes ${...} aliases in a page header/footer segment, tolerating a null/empty segment.
    • copyDefinedNames

      protected void copyDefinedNames()
      Copies user-defined names into the result workbook. Hint names, band ranges and Excel built-ins (print area/titles, filter database) are skipped: the first two are structural, the built-ins are re-created by copyPrintArea() or reserved. Copying user names keeps formulas that reference a workbook name resolving instead of rendering #NAME?.
    • copyPrintArea

      protected void copyPrintArea()
      Copies the template print area re-based onto the written rows, see XlsxUtils.rebasePrintArea(io.jmix.reports.yarg.formatters.impl.xlsx.Range, io.jmix.reports.yarg.formatters.impl.xlsx.RangeDependencies, io.jmix.reports.yarg.formatters.impl.xlsx.RangeDependencies, org.apache.poi.ss.SpreadsheetVersion): static rows are mapped to the rows they are written to, bands to all their instances with their child bands. A print area that is not re-based, e.g. whole columns, is copied as authored; one that is not one area of cell references, e.g. several areas or a formula, is not copied.
    • getWrittenBlocks

      protected RangeDependencies getWrittenBlocks(String sheetName, org.apache.poi.ss.SpreadsheetVersion version)
      Returns the template ranges of the rendered bands and of the static rows mapped to the rows written for them: all the instances of a band with their child bands, the output row of a static row.
    • getRenderedBlockRows

      protected @org.jspecify.annotations.Nullable int[] getRenderedBlockRows(TemplateBand band)
      Returns the first and the last output row (0-based) of all the rendered instances of the band with their child bands, or null if the band rendered nothing.
    • createResultRow

      protected org.apache.poi.xssf.streaming.SXSSFRow createResultRow(org.apache.poi.xssf.streaming.SXSSFSheet resultSheet, int outRowIdx)
      Creates the next result row, rejecting the .xlsx hard row limit with a clear error instead of the raw IllegalArgumentException POI would throw mid-render after minutes of streaming.
    • childBands

      protected List<BandData> childBands(BandData parent, String name)
    • writeHorizontalBand

      protected void writeHorizontalBand(TemplateBand band, org.apache.poi.xssf.usermodel.XSSFSheet templateSheet, org.apache.poi.xssf.streaming.SXSSFSheet resultSheet, StreamingXlsxFormatter.WriteCursor cursor, List<BandData> instances)
      Renders a horizontal band: the band's template rows are emitted once per BandData instance, top to bottom. Everything derivable from the template alone (cell classification, parsed formulas, merges, hint membership, auto-height metrics) is precomputed once per band in StreamingXlsxFormatter.BandLayout; the per-instance loop only looks up values and writes cells.
    • writeHorizontalBand

      protected void writeHorizontalBand(TemplateBand band, org.apache.poi.xssf.usermodel.XSSFSheet templateSheet, org.apache.poi.xssf.streaming.SXSSFSheet resultSheet, StreamingXlsxFormatter.WriteCursor cursor, Iterator<BandData> instances, boolean fed)
    • rejectContentBetween

      protected void rejectContentBetween(TemplateBand parent, TemplateBand child, org.apache.poi.xssf.usermodel.XSSFSheet templateSheet)
      A child band renders attached to its parent instance, so anything physically located between the parent's rows and the child's rows would be written out of order (after the child). Reject such a layout up front instead of producing a silently reordered document: a static row, or another band that is not a child of the same parent (an unrelated sibling), both break the ordering.
    • bandLayout

      protected StreamingXlsxFormatter.BandLayout bandLayout(TemplateBand band, org.apache.poi.xssf.usermodel.XSSFSheet templateSheet)
    • prepareBandLayout

      protected StreamingXlsxFormatter.BandLayout prepareBandLayout(TemplateBand band, org.apache.poi.xssf.usermodel.XSSFSheet templateSheet)
    • prepareCell

      protected StreamingXlsxFormatter.PreparedCell prepareCell(TemplateBand band, org.apache.poi.xssf.usermodel.XSSFCell templateCell, int templateRow, int col)
    • prepareStringCell

      protected void prepareStringCell(TemplateBand band, StreamingXlsxFormatter.PreparedCell prepared, String text)
      Classifies a string template cell: a lone ${alias} becomes a typed value lookup, text with aliases is split into literal/alias segments once (so no regex runs per row), plain text becomes a constant. Content inliner formats are rejected here, before any row is written.
    • prepareFormula

      protected StreamingXlsxFormatter.PreparedFormula prepareFormula(String formula, TemplateBand band)
      Parses an in-row formula once and records which reference tokens point inside the band's template rows; per instance only those rows are re-assigned (base + shift) before rendering the tokens back. String literals, function names, defined names and sheet-qualified references are never touched.
    • inBand

      protected boolean inBand(int row, TemplateBand band)
    • instanceShift

      protected boolean instanceShift(int row, boolean rowRelative, TemplateBand band)
      A row endpoint tracks the band instance only when it is a relative reference inside the band. An absolute ($) row is anchored by definition, and a row outside the band belongs to a static row (or a not-yet-written forward row) — neither follows the instance.
    • rejectSingleRefBelowBand

      protected void rejectSingleRefBelowBand(org.apache.poi.ss.formula.ptg.RefPtgBase ref, TemplateBand band, String formula)
      Rejects an in-band single-cell reference pointing to a row below the band. That row is written after the band, so its output position is unknown while the band renders and cannot be resolved forward-only — mirrors the rejection of an area whose relative end lies below the band. A reference inside the band shifts per instance; one above the band re-bases onto the already-written row, so neither is rejected.
    • renderPreparedFormula

      protected String renderPreparedFormula(StreamingXlsxFormatter.PreparedFormula formula, int rowShift)
    • renderPreparedCell

      protected void renderPreparedCell(StreamingXlsxFormatter.PreparedCell prepared, org.apache.poi.ss.usermodel.Cell out, BandData instance, int rowShift, TemplateBand band)
    • renderCellFormula

      protected String renderCellFormula(StreamingXlsxFormatter.PreparedCell prepared, TemplateBand band, BandData instance, int rowShift)
      Renders an in-band formula for one instance. Formulas without aliases are parsed once (cached in the band layout) and only shifted; a formula carrying ${alias} is substituted and re-parsed per instance, because its aliases resolve to per-instance values.
    • renderSingleAlias

      protected void renderSingleAlias(StreamingXlsxFormatter.PreparedCell prepared, org.apache.poi.ss.usermodel.Cell out, BandData instance)
      Writes a lone-alias cell value replicating the non-streaming engine's typing rules: the raw value's Excel type (numeric, boolean, date serial) unless an explicit format string turns it into text.
    • writeNumericValue

      protected void writeNumericValue(org.apache.poi.ss.usermodel.Cell out, Number number)
      Writes a numeric value as a numeric cell (Number -> numeric). POI can set a numeric cell only through a double, so an integer whose magnitude exceeds a double's exact range (2^53) — a BIGINT or snowflake id — loses its low digits here. This differs from the non-streaming engine, which writes the exact decimal string into the numeric cell (Excel still rounds it to a double when the file is opened, but the raw file keeps the exact digits). To keep such a value exact in the streamed file, author an explicit field format so it is emitted as text, or select it as a string in the query.
    • renderSegments

      protected void renderSegments(StreamingXlsxFormatter.PreparedCell prepared, org.apache.poi.ss.usermodel.Cell out, BandData instance)
    • parseFormula

      protected org.apache.poi.ss.formula.ptg.Ptg[] parseFormula(String formula)
    • renderFormula

      protected String renderFormula(org.apache.poi.ss.formula.ptg.Ptg[] ptgs)
    • styleHintParamAt

      protected @Nullable String styleHintParamAt(int templateRow, int templateCol)
    • applyPreparedStyleHint

      protected void applyPreparedStyleHint(StreamingXlsxFormatter.PreparedCell prepared, org.apache.poi.ss.usermodel.Cell out, BandData instance)
      hint_style_<param>: if the template cell lies in a style-hint range, the band supplies the name of a template named cell style to apply. Unknown names or missing values keep the base style.
    • resolveNamedStyle

      protected @Nullable org.apache.poi.ss.usermodel.CellStyle resolveNamedStyle(String styleName, org.apache.poi.xssf.usermodel.XSSFCell templateCell)
      Materializes a template named cell style in the result workbook. Mirrors the non-streaming CustomCellStyleXlsxHint: the named style's attributes are combined with the template cell's border, registered as a regular cell style, and cloned into the result workbook once.
    • applyCellBorder

      protected void applyCellBorder(org.apache.poi.xssf.usermodel.XSSFCellStyle result, @Nullable org.apache.poi.xssf.usermodel.XSSFCellStyle source)
      Overlays the template cell's own border (styles and colors) onto a named-style result cell.
    • prepareAutoHeight

      protected void prepareAutoHeight(StreamingXlsxFormatter.PreparedCell prepared, org.apache.poi.xssf.usermodel.XSSFCell templateCell, int templateRow, int templateCol)
      Precomputes the hint_rowAutoHeight metrics of a template cell: hint membership, the (merge-aware) column width, the indent width and the font. Cells inside multi-row merges are excluded up front.
    • applyPreparedAutoHeight

      protected void applyPreparedAutoHeight(StreamingXlsxFormatter.PreparedCell prepared, org.apache.poi.ss.usermodel.Cell outCell, org.apache.poi.xssf.streaming.SXSSFRow outRow)
      hint_rowAutoHeight: measures the written text against the precomputed column width and font, and raises the row height so wrapped text stays visible. Mirrors the non-streaming RowAutoHeightXlsxHint; the height is capped at MAX_ROW_HEIGHT.
    • templateMergeAt

      protected @Nullable org.apache.poi.ss.util.CellRangeAddress templateMergeAt(int row, int col)
    • mergedOrColumnWidthInPixels

      protected int mergedOrColumnWidthInPixels(org.apache.poi.xssf.usermodel.XSSFSheet templateSheet, int col, @Nullable org.apache.poi.ss.util.CellRangeAddress merge)
    • calculateCellHeight

      protected double calculateCellHeight(org.apache.poi.xssf.usermodel.XSSFFont font, String cellValue, int cellWidthInPixels)
      Measures wrapped text height: fontSize * 1.3 * lineCount, ceiled to the nearest 0.25pt.
    • getIndentInPixels

      protected int getIndentInPixels(int indent)
      One indent "point" equals three whitespaces in the default font.
    • createAttributedString

      protected AttributedString createAttributedString(org.apache.poi.xssf.usermodel.XSSFFont font, String value)
    • copyRowOutlineLevel

      protected void copyRowOutlineLevel(org.apache.poi.xssf.usermodel.XSSFRow templateRow, org.apache.poi.xssf.streaming.SXSSFSheet resultSheet, int outRowIdx)
      Row grouping: replicates the template row's outline level onto the rendered row.
    • customRowHeight

      protected short customRowHeight(org.apache.poi.xssf.usermodel.XSSFRow templateRow, org.apache.poi.xssf.usermodel.XSSFSheet templateSheet)
      Custom height of a template row in twips, or -1 when it uses the sheet default.
    • applyRowHeightAndHidden

      protected void applyRowHeightAndHidden(short heightTwips, boolean zeroHeight, org.apache.poi.ss.usermodel.Row outRow)
      Carries a row's custom height and hidden flag onto the rendered row. Without this a tall header row would collapse to the sheet default and a hidden template row would become visible (the non-streaming engine keeps them because it renders on a template copy). heightTwips < 0 keeps the default.
    • childTemplateBandsOf

      protected List<TemplateBand> childTemplateBandsOf(TemplateBand parent)
      The template bands that are actual child bands of the given one, in row order. Children are decided by the BandData tree (not by mere row position), so an unrelated sibling band laid out below the parent is not pulled into the parent's render — it is emitted by the main template walk in its template position instead.
    • copyStaticRow

      protected void copyStaticRow(org.apache.poi.xssf.usermodel.XSSFSheet templateSheet, org.apache.poi.xssf.streaming.SXSSFSheet resultSheet, int templateRowIdx, StreamingXlsxFormatter.WriteCursor cursor)
      Copies a template row that lies outside every band range. Aliases are resolved through band paths (${Band.child.param}); aliases that resolve to no band are left untouched.
    • writeStaticCellValue

      protected void writeStaticCellValue(org.apache.poi.xssf.usermodel.XSSFCell templateCell, org.apache.poi.ss.usermodel.Cell out)
    • writeOuterFormula

      protected void writeOuterFormula(org.apache.poi.xssf.usermodel.XSSFCell templateCell, org.apache.poi.ss.usermodel.Cell out)
      Writes a formula placed outside band ranges (typically a total row below the data). Range references pointing into a band's template rectangle are grown to cover all rows the band actually rendered; a reference to a band that rendered nothing turns the cell into an error text, matching the non-streaming engine.
    • rejectForwardReference

      protected void rejectForwardReference(String formula, int formulaTemplateRow)
      A formula outside band ranges may reference a band or a static row ABOVE it (a running total below the data), but a reference to a band OR a static row laid out BELOW the formula cannot be resolved forward-only: those rows are written after the formula, so the reference would otherwise be handled wrongly (a below-formula band silently renders the empty-range error text; a below-formula static row is silently kept as the template row and ends up pointing into the band data). Reject both up front with a clear message instead.
    • rejectIfReferencedRowBelow

      protected void rejectIfReferencedRowBelow(int referencedRow, int formulaTemplateRow, String formula)
      Rejects an endpoint that lands below the formula on a row whose output position cannot be resolved forward-only: either inside a band positioned below the formula (where growOuterFormula(java.lang.String) would grow the reference onto rows the band has not written yet and emit the misleading empty-range error), or on a static template row below the formula (which resolveOuterAreaRow(int, boolean) would silently keep at its template number, pointing into the shifted band data). A wide or whole-column reference (e.g. SUM(A:A)) is left as authored: its far endpoint is not a real template row, so it does not match either case; it needs no growth and Excel computes it on open.
    • growOuterFormula

      protected @Nullable String growOuterFormula(String formula)
      Rewrites a formula placed outside band ranges: area references into a band grow over all rows the band rendered; single references into a band re-base onto the same offset within the band's LAST rendered instance (the "totals below the data" convention); references to static template rows re-base onto the row's actual output position. A forward reference to a band laid out below the formula is rejected up front (see rejectForwardReference(String, int)); a forward reference to a static row not written yet is kept as in the template. Returns null when a referenced band produced no rows.
    • resolveOuterAreaRow

      protected @Nullable Integer resolveOuterAreaRow(int templateRow, boolean firstEndpoint)
      Maps one endpoint of an outer area reference to its rendered row, classifying each endpoint on its own so an area straddling a band and static rows is handled correctly. An endpoint inside a band preserves its offset within the band block: the first endpoint re-bases onto the first rendered instance (its start plus the offset), the last endpoint onto the last rendered instance, so a range covering only part of a multi-row band is not silently widened to the whole band. An endpoint on a static row re-bases onto that row's output position, or keeps its template row when the row has not been written yet (forward reference). Returns null when the endpoint points into a band that produced no rows.
    • bandContainingTemplateRow

      protected @Nullable TemplateBand bandContainingTemplateRow(int templateRow)
    • recordRenderedRows

      protected void recordRenderedRows(String bandName, int firstOutputRow, int lastOutputRow)
    • insertBandDataToStringByPath

      protected String insertBandDataToStringByPath(String resultStr)
      Resolves ${Band.path.param} aliases against the band tree (mirrors the non-streaming engine's sheet-name/header substitution). Aliases whose band path cannot be resolved are kept as is.