You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DynamicJasper:如何用数组/列表替代预定义对象作为数据源?

Working with Dynamic Array Data in DynamicJasper

Great question! The JRBeanCollectionDataSource is built for JavaBean collections (where each row maps to an object with defined getters/setters), but you absolutely can handle dynamic array-based data in DynamicJasper. Here are two straightforward solutions tailored to your scenario:

Option 1: Use JRMapCollectionDataSource (Simplest Approach)

Instead of wrapping your arrays into predefined objects, convert each array row into a Map<String, Object> where the keys match your report column names, and values are the corresponding array elements (strings, integers, dates, etc.). DynamicJasper works seamlessly with JRMapCollectionDataSource, which is designed for map-based data.

Example Code:

import net.sf.jasperreports.engine.data.JRMapCollectionDataSource;
// ... other imports

// Step 1: Prepare your dynamic data as a list of maps
List<Map<String, Object>> dynamicData = new ArrayList<>();

// Row 1: Map keys match the column names we'll define later
Map<String, Object> row1 = new HashMap<>();
row1.put("Region", "West");
row1.put("Sales", 45000);
row1.put("SaleDate", new Date());
dynamicData.add(row1);

// Row 2
Map<String, Object> row2 = new HashMap<>();
row2.put("Region", "East");
row2.put("Sales", 62000);
row2.put("SaleDate", new Date());
dynamicData.add(row2);

// Step 2: Build your dynamic report with columns mapped to map keys
FastReportBuilder drb = new FastReportBuilder();
DynamicReport dr = drb.addColumn("Region", "Region", String.class.getName(), 40)
    .addColumn("Sales Amount", "Sales", Integer.class.getName(), 70, true)
    .addColumn("Transaction Date", "SaleDate", Date.class.getName(), 80)
    .setTitle("Dynamic Sales Report")
    .setUseFullPageWidth(true)
    .build();

// Step 3: Use JRMapCollectionDataSource instead of JRBeanCollectionDataSource
JRDataSource ds = new JRMapCollectionDataSource(dynamicData);
JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds);
JasperViewer.viewReport(jp);

If your raw data is in Object[] format, just loop through your arrays and populate the maps using your column names as keys (e.g., for an array rowArray and column list columnNames, do rowMap.put(columnNames[i], rowArray[i]) for each index i).

Option 2: Create a Custom JRDataSource (For Raw Array Data)

If you want to work directly with Object[] arrays without converting to maps, you can implement a custom JRDataSource that handles array indexing. This gives you full control over how fields are fetched from your arrays.

Example Custom Data Source:

import net.sf.jasperreports.engine.JRDataSource;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRField;
import java.util.List;
import java.util.Map;
import java.util.HashMap;

public class ArrayDataSource implements JRDataSource {
    private final List<Object[]> dataRows;
    private final Map<String, Integer> columnIndexMap;
    private int currentRowIndex = -1;

    // Constructor: takes your array data and a list of column names (to map names to array indices)
    public ArrayDataSource(List<Object[]> dataRows, List<String> columnNames) {
        this.dataRows = dataRows;
        this.columnIndexMap = new HashMap<>();
        for (int i = 0; i < columnNames.size(); i++) {
            columnIndexMap.put(columnNames.get(i), i);
        }
    }

    @Override
    public boolean next() throws JRException {
        currentRowIndex++;
        return currentRowIndex < dataRows.size();
    }

    @Override
    public Object getFieldValue(JRField field) throws JRException {
        String fieldName = field.getName();
        Integer columnIndex = columnIndexMap.get(fieldName);
        if (columnIndex == null || columnIndex >= dataRows.get(currentRowIndex).length) {
            return null; // Handle missing fields gracefully
        }
        return dataRows.get(currentRowIndex)[columnIndex];
    }
}

Usage Example:

// Step 1: Prepare your raw array data
List<Object[]> arrayData = new ArrayList<>();
arrayData.add(new Object[]{"West", 45000, new Date()});
arrayData.add(new Object[]{"East", 62000, new Date()});

// Step 2: Define your column names (order matches array indices)
List<String> columnNames = List.of("Region", "Sales", "SaleDate");

// Step 3: Build the report (column property names match the names in columnNames)
FastReportBuilder drb = new FastReportBuilder();
DynamicReport dr = drb.addColumn("Region", "Region", String.class.getName(), 40)
    .addColumn("Sales Amount", "Sales", Integer.class.getName(), 70, true)
    .addColumn("Transaction Date", "SaleDate", Date.class.getName(), 80)
    .setTitle("Raw Array Sales Report")
    .setUseFullPageWidth(true)
    .build();

// Step 4: Use your custom data source
JRDataSource ds = new ArrayDataSource(arrayData, columnNames);
JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds);
JasperViewer.viewReport(jp);

Which Option Should You Choose?

  • Go with Option 1 if you want minimal code and don’t mind converting arrays to maps—it’s the quickest and most maintainable approach for dynamic columns.
  • Use Option 2 if you need to work directly with raw arrays (e.g., performance constraints or existing array-based data pipelines).

内容的提问来源于stack exchange,提问作者SlimenTN

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 08:40:32