Как передать основной источник данных отчета в подотчет (JasperReports)? - PullRequest
31 голосов
/ 13 декабря 2011

Я использую JasperReports и заполняю JRDataSource для отчета. Теперь я хочу передать основной REPORT_DATA_SOURCE в подотчет. Как я могу это сделать?

Насколько я знаю, REPORT_DATA_SOURCE - это расходный объект, поэтому его можно использовать только один раз, верно? Могу ли я скопировать этот источник данных и передать его?

Кстати: я использую iReport для создания макета.

Ответы [ 6 ]

37 голосов
/ 14 декабря 2011

Вы можете передать источник данных через встроенный параметр REPORT_DATA_SOURCE.

Пример:

<subreport>
    <reportElement x="261" y="25" width="200" height="100"/>
    <dataSourceExpression><![CDATA[$P{REPORT_DATA_SOURCE}]]></dataSourceExpression>
    <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "subreport.jasper"]]></subreportExpression>
</subreport>

Вы можете создать новый экземпляр источника данных на основе переменной, параметра или поля.

Пример:

<variable name="HeadingsCollection" class="java.util.Collection" calculation="System">
    <initialValueExpression><![CDATA[new java.util.ArrayList()]]></initialValueExpression>
</variable>
...
<subreport>
    <reportElement x="0" y="0" width="515" height="20"/>
    <subreportParameter name="ReportTitle">
        <subreportParameterExpression><![CDATA[$P{ReportTitle}]]></subreportParameterExpression>
    </subreportParameter>
    <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($V{HeadingsCollection})]]></dataSourceExpression>
    <subreportExpression class="java.lang.String"><![CDATA["HeadingsReport.jasper"]]></subreportExpression>
</subreport>

Другой пример:

<field name="cast" class="java.util.Collection"/>
...
<subreport>
    <reportElement positionType="Float" x="15" y="25" width="245" height="20" isRemoveLineWhenBlank="true" backcolor="#99CCFF"/>
    <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{cast})]]></dataSourceExpression>
    <subreportExpression class="java.lang.String"><![CDATA["JRMDbCastSubreport.jasper"]]></subreportExpression>
</subreport>

Или вы можете передать источник данных через параметр:

<parameter name="SubreportDataSource" class="net.sf.jasperreports.engine.JRDataSource"/>
...
<subreport>
    <reportElement positionType="Float" x="15" y="25" width="245" height="20" isRemoveLineWhenBlank="true"/>
    <dataSourceExpression>$P{SubreportDataSource}</dataSourceExpression>
    <subreportExpression class="java.lang.String"><![CDATA["Subreport.jasper"]]></subreportExpression>
</subreport>

Примечание: Использование того же (с основным отчетом) источник данных в подотчете может вызвать эффект потери первой строки в подотчете .Вы можете прочитать Почему в моем подотчете отсутствует первая запись? Пост, чтобы понять, как избежать этой проблемы.

1 голос
/ 13 декабря 2011

Да, вы должны быть осторожны с передачей источника данных. С соединением SQL вы можете просто передать выражение соединения, например $P{REPORT_CONNECTION}. Тогда подотчет имеет свой собственный запрос SQL.

В вашем случае вы хотите передать фактические данные. В зависимости от деталей, это может быть так же просто, как просто определить выражение карты параметров, например $P{REPORT_PARAMETERS_MAP}. Он находится на другой вкладке в том же окне, где вы устанавливаете соединение подотчета в iReport. Часто этого достаточно для передачи источника данных.

Но вам может понадобиться небольшой код для обработки вещей. Рассмотрим этот пример с источником данных CSV, повторно используемым в подотчетах. Причина, по которой вы не можете просто использовать объект JRParameter.REPORT_DATA_SOURCE, заключается в том, что указатель строки индекса никогда не сбрасывается, поэтому передача этого исходного объекта в подотчет приведет к преждевременному закрытию набора записей. Мы решили это с помощью минимального вспомогательного класса:

package com.jaspersoft.untested_unsupported; 

import java.io.File; 
import java.io.FileNotFoundException; 
import net.sf.jasperreports.engine.JRDataSource; 
import net.sf.jasperreports.engine.data.JRCsvDataSource; 

public class CsvDataSourceFactory { 
    public static JRDataSource getDataSource(String fileName, boolean firstRowHeaders) throws FileNotFoundException { 
        JRCsvDataSource csvDs = new JRCsvDataSource(new File(fileName)); 
        csvDs.setUseFirstRowAsHeader(firstRowHeaders); 
        return csvDs; 
    } 
}
0 голосов
/ 29 октября 2018

У меня была ситуация, когда у меня был стол в подотчете.Подотчет содержит только полосу заголовка и сводную полосу с таблицей в сводке.Я хотел также использовать источник данных подотчета для таблицы, но не смог получить ни один из подходов в принятом ответе на работу.Итак, вот альтернативный подход, который отлично работает в версии 6.6.0:

В основном отчете:

        <subreport>
            <reportElement x="0" y="0" width="468" height="0" uuid="c057b890-3889-43dd-8634-bbf2e857cc0d"/>
            <subreportParameter name="partsList">
                <subreportParameterExpression><![CDATA[$F{drawingRevision}.getPartsList()]]></subreportParameterExpression>
            </subreportParameter>
            <subreportExpression><![CDATA["static/engineering/drawings/subreports/DrawingPartsList.jasper"]]></subreportExpression>
        </subreport>

Ключ здесь в том, что List передается какпараметр и NOT в качестве источника данных, например:

<dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{drawingRevision}.getPartsList())]]></dataSourceExpression>

В этом подотчете указывается:

...
<parameter name="partsList" class="java.util.List" isForPrompting="false"/>
...
<summary>
    <band height="60" splitType="Stretch">
        <componentElement>
            <reportElement key="table" style="table" x="0" y="0" width="468" height="60" uuid="09499b35-b122-4fe4-a2b3-d91d6a19b2ab"/>
            <jr:table xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" whenNoDataType="AllSectionsNoDetail">
                <datasetRun subDataset="PartList" uuid="87fcbcc9-f0f0-4397-87f2-237201fc1857">
                    <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($P{partsList})]]></dataSourceExpression>
                </datasetRun>
...

Обратите внимание, что в подотчете также необходимо включить свойство whenNoDataType="AllSectionsNoDetail" или что-то в этом роде, в противном случае подотчет будет пустым, поскольку в нем нет данных.

0 голосов
/ 10 марта 2017

Это старый вопрос, на который уже дан ответ, но я передаю неподходящий компонент в подотчет, избегая потери первой записи или передавая все записи в подотчет.Преимущество этого решения заключается в том, что подотчет можно использовать в качестве основного отчета, и он «просто» передает фактическую запись в качестве источника данных подотчета (используя groovy в качестве языка отчета):

<subreport>
    <reportElement x="261" y="25" width="200" height="100"/>
    <dataSourceExpression><![CDATA[new JRBeanCollectionDataSource(
       $P{REPORT_DATA_SOURCE}.data.toList().subList($V{REPORT_COUNT}-1,$V{REPORT_COUNT})]]></dataSourceExpression>
    <subreportExpression><![CDATA[$P{SUBREPORT_DIR} + "subreport.jasper"]]></subreportExpression>
</subreport>
0 голосов
/ 07 ноября 2013

«REPORT_DATA_SOURCE» является расходуемым объектом. Вы можете использовать столько времени, сколько пожелаете.

Я протестировал источник данных как XML-файл dataSource и не будет отображаться, как сказал ALEX.

"это не приведет к потере первой строки в подотчете."

Я думаю, возможно, я использую xpath для выбора, поэтому каждый раз не будет записей потерь.

Есливы используете базу данных JDBC в качестве источника данных, pealse передает sql в качестве параметра для подотчета.

Если вы используете ResultSet в качестве параметра, возможно, будет потеряна одна запись при определении подотчета в подробных диапазонах.

0 голосов
/ 10 мая 2012

мы предполагаем, что параметром источника данных является «dataSourceParam», а значением источника данных (список) является «dataSourceList» в классе Java мы ставим:

final Map<String, Object> params = new HashMap<String, Object>();
JRDataSource dataSource = new ListOfArrayDataSource( dataSourceList, 
                          new String[] {"date", "age", "adress", "email"});
params.put("dataSourceParam",dataSourceList);**

в основном шаблоне отчета мы помещаем в декларацию параметров:

<parameter name="dataSourceParam" class="net.sf.jasperreports.engine.JRDataSource"/>

затем в теге подотчета мы помещаем:

<subreport isUsingCache="true">
    <reportElement key="subreport-1" stretchType="RelativeToTallestObject" isPrintRepeatedValues="false" x="112" y="45" width="338" height="29"/>
    <subreportParameter name="otherParameter">
        <subreportParameterExpression><![CDATA[$P{sumM1}]]></subreportParameterExpression>
    </subreportParameter>
    <dataSourceExpression><![CDATA[$P{dataSourceParam}]]></dataSourceExpression>
    <subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{subReportFile}]]></subreportExpression>
</subreport>
...