How to Add Custom Rows to an AnyLogic Exporter Report

       To add custom rows to an AnyLogic Exporter report, you can use the AdditionalRowExport classes provided by the Petroleum Refining Library. This allows you to extend an AnyLogic Excel export with custom simulation statistics, calculated flows, product-specific results, and aggregated values for refinery objects such as Sources, Process Units, and Tank Farms.
Custom rows allow you to add calculated flows, product-specific results, or aggregated values to the existing report structure.
The workflow is simple: Create a row → register it with Exporter → calculate its value → add the value at each simulation step. This extends the standard AnyLogic XLSX report with custom simulation statistics without changing the Exporter's built-in statistics.

How Custom Rows Work in an AnyLogic Exporter Report

       Custom Exporter rows are based on the AbstractAdditionalRowExport class. It stores the row name, indentation level, associated PRL object, row placement, and values recorded during the simulation. The Petroleum Refining Library provides specialized classes for common cases, such as AdditionalRowExportTotalOutput, AdditionalRowExportTotalInput, and Process Unit line-specific rows. Each class defines where the row appears in the report.
After creating a row, it must be registered with the Exporter using addAdditionalRow(). Its values are then added during the simulation with addStepValue(). Each simulation step must add exactly one value to keep the row synchronized with the simulation results.

How to Create a Custom Row in an AnyLogic Exporter

       The first step is to create an instance of one of the AdditionalRowExport classes provided by the Petroleum Refining Library.
For example, to add a custom output row for a product:
AdditionalRowExportTotalOutput row = new AdditionalRowExportTotalOutput( "Custom Product Output", 4, processUnit, productId );
       The constructor defines the main properties of the row:
  • flowName — the row name displayed in the report;
  • indentLevel — the row indentation;
  • processUnit — the associated PRL object;
  • productId — the ID of the product represented by the row.
The selected AdditionalRowExport class also determines where the row is placed in the report. For example, AdditionalRowExportTotalOutput uses the TOTAL_OUTPUT placement.

Register a Custom Row with the AnyLogic Exporter

       Creating the row object is not enough. The row must also be registered with the Exporter:
main.resultsExporter.addAdditionalRow(row);
       This registers the custom row in the AnyLogic Exporter report and allows the Exporter to include the additional data in the generated XLSX report. In a typical model, the registration can be performed immediately after creating the row:
AdditionalRowExportTotalOutput row = new AdditionalRowExportTotalOutput( "Custom Product Output", 4, processUnit, productId );
main.resultsExporter.addAdditionalRow(row);
       The row object can then be kept in a variable or collection so that its values can be updated during the simulation. In the example implementation, the created row is registered with resultsExporter and then stored in a map for later access.

Store and Retrieve Custom Rows in AnyLogic

       After registering the row with the Exporter, keep a reference to it so that its values can be updated during the simulation.
A convenient approach is to store rows in a Map using a key that identifies the PRL object, product, and output type:
exportRows.put( new ExportKey(prlObject, productId, outputLabel), row );
       The same key can then be used to retrieve the row when its value needs to be updated:
ExportKey key = new ExportKey(processUnit, productId, outputLabel); 
AdditionalRowExportTotalOutput row = exportRows.get(key);
       This separates two tasks: the Exporter manages the row in the report, while the model keeps a reference to the row and controls how its values are calculated. In the example implementation, ExportKey combines the PRL object, product ID, and output label.

Update Custom Row Values During an AnyLogic Simulation

       Once the row has been registered and stored, add its value during each simulation step using addStepValue():
row.addStepValue(value);
The value can come from any calculation or flow measurement available in the model. The important requirement is that exactly one value is added for each simulation step so that the row remains synchronized with the simulation results. For example:
double value = getMass(fluidBlock);
row.addStepValue(value);
In a larger model, the calculation and row lookup can be combined:
ExportKey key = new ExportKey(processUnit, productId, outputLabel); 
AdditionalRowExportTotalOutput row = exportRows.get(key); 
if (row == null) { throw new IllegalStateException("Export row not found"); } row.addStepValue(value);
The resulting sequence of values is stored in the row in simulation-step order and is later used by the Exporter when generating the XLSX report.

Example: Add a Custom Output Row to an AnyLogic Exporter Report

       The following example shows how to add a custom output row to an AnyLogic Exporter XLSX report, from creating and registering the row to updating its value during the simulation.
AdditionalRowExportTotalOutput row = new AdditionalRowExportTotalOutput( "Custom Product Output", 4, processUnit, productId ); 
main.resultsExporter.addAdditionalRow(row); 
ExportKey key = new ExportKey(processUnit, productId, outputLabel); 
exportRows.put(key, row);
During the simulation, calculate the required value and add it to the same row:
AdditionalRowExportTotalOutput row = exportRows.get(key); 
double value = getMass(fluidBlock); 
row.addStepValue(value);
The complete workflow is therefore: Create the row → register it with Exporter → store its reference → calculate the value → add one value per simulation step. This pattern can be used with the different AdditionalRowExport classes provided by the Petroleum Refining Library.

AdditionalRowExport Types for AnyLogic XLSX Reports

       The Petroleum Refining Library provides several AdditionalRowExport classes for different report structures:
For example, AdditionalRowExportTotalInput can be associated with a Process Unit or Tank Farm, while AdditionalRowExportProcessUnitOutputByProduct is associated with a specific Process Unit, production line, and product.
The appropriate class should be selected according to what the row represents and where it should appear in the report.

Control Custom Row Position in an AnyLogic Exporter Report

       Each AdditionalRowExport class defines where the row is placed in the Exporter report. This is controlled by the AdditionalRowPlacement value passed to the base AbstractAdditionalRowExport class. For example, AdditionalRowExportTotalOutput uses the TOTAL_OUTPUT placement, while Process Unit line rows use dedicated positions for input or output data. Report-level rows can also be placed at the beginning or end of the report using AdditionalRowExportReportStart and AdditionalRowExportReportEnd. Choose the AdditionalRowExport class according to the required position and meaning of the row. This ensures that the custom data appears in the appropriate section of the generated XLSX report.

Conclusion

       Learning how to add custom rows to an AnyLogic Exporter report provides a simple way to extend an AnyLogic XLSX report with model-specific simulation data. The workflow is: Create an AdditionalRowExport row → register it with the Exporter → store its reference → calculate the required value → add one value per simulation step. By using the appropriate AdditionalRowExport class, you can add additional input, output, product, and Process Unit line data while keeping the standard XLSX report structure intact.

FAQ

1. Can I add custom rows without changing the standard Exporter statistics?
Yes. Custom AdditionalRowExport rows extend the existing Exporter report and do not replace the standard statistics.

2. Which class should I use for a custom output row?
For a total output row, use AdditionalRowExportTotalOutput. Other AdditionalRowExport classes are available for total input, Process Unit lines, report boundaries, and other positions.

3. Do I need to register the custom row with the Exporter?
Yes. After creating the row, register it using addAdditionalRow(). This registers the row with the Exporter so it can be included in the generated report.

4. How do I add values to a custom row in an AnyLogic Exporter report?
Use the addStepValue() method during the simulation:
row.addStepValue(value); The row should receive exactly one value for each simulation step.

5. Can I calculate the value of a custom row myself?
Yes. The value can be calculated from flow measurements or other model data. The AdditionalRowExport object stores the resulting value sequence for the Exporter.

6. Can I create several custom rows?
Yes. Multiple AdditionalRowExport objects can be created and registered with the Exporter. They can be stored in a collection or map so that the model can update each row during the simulation.

7. How can I control where the custom row appears in the report?
The position is determined by the selected AdditionalRowExport class and its AdditionalRowPlacement. For example, AdditionalRowExportTotalOutput is intended for total output data, while report-start and report-end classes place rows at the corresponding report boundaries.

8. Can custom rows be associated with a Process Unit or another PRL object?
Yes. Depending on the row type, an AdditionalRowExport object can be associated with a supported PRL object, such as a Process Unit, Tank Farm, or Source.

9. What happens if I add more than one value for a simulation step?
Adding more than one value for a simulation step breaks the one-value-per-step alignment required by the custom row.

10. Can I use custom rows to add aggregated refinery flows to an AnyLogic XLSX report?
Yes. Custom rows are particularly useful when several flows need to be aggregated into a single reporting line or when calculated model-specific values need to be added to the XLSX report.