Jasperreports 中的嵌套子报表

Nested subreports in Jasperreports

我想生成一个包含嵌套子报表的报表,例如:

MainReport --- whose dataSource refers to ---> List<MainSkillCategory>
|
|--- contains ---> SubReport_1 --- whose dataSource refers to ---> List<SubSkillCategory>
                      |
                      |--- contains ---> SubReport_2 --- whose dataSource refers to ---> List<Skill>

MainSkillCategory.java class :

public class MainSkillCategory {
    String nameMainSkillCat;
    List<SubSkillCategory> subSkillCategories;

    public MainSkillCategory(String nameMainSkillCat){
        this.nameMainSkillCat = nameMainSkillCat;
        this.subSkillCategories = new ArrayList<SubSkillCategory>();        
    }

    public String getNameMainSkillCat() {
        return nameMainSkillCat;
    }


    public void setNameMainSkillCat(String nameMainSkillCat) {
        this.nameMainSkillCat = nameMainSkillCat;
    }

    public List<SubSkillCategory> getSubSkillCategories() {
        return subSkillCategories;
    }

    public void setSubSkillCategories(List<SubSkillCategory> subSkillCategories) {
        this.subSkillCategories = subSkillCategories;
    }

    public void addSubSkillCategory(SubSkillCategory subSkillCat){
        subSkillCategories.add(subSkillCat);
    }

}

SubSkillCategory.java class :

public class SubSkillCategory {
    String nameSubSkillCat;
    List<Skill> skills;

    public SubSkillCategory(String nameSubSkillCat){
        this.nameSubSkillCat = nameSubSkillCat;
        this.skills = new ArrayList<Skill>();       
    }

    public String getNameSubSkillCat() {
        return nameSubSkillCat;
    }

    public void setNameSubSkillCat(String nameSubSkillCat) {
        this.nameSubSkillCat = nameSubSkillCat;
    }

    public List<Skill> getSkills() {
        return skills;
    }

    public void setSkills(List<Skill> skills) {
        this.skills = skills;
    }

    public void addSkill(Skill skill){
        skills.add(skill);
    }
}

Skill.java Class :

public class Skill {
    String nameSkill;

    public Skill(String nameSkill){
        this.nameSkill=nameSkill;
    }

    public String getNameSkill() {
        return nameSkill;
    }

    public void setNameSkill(String nameSkill) {
        this.nameSkill = nameSkill;
    }

}

我的 MainReport.jrxml :

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="profile_report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="40a9d14e-f38a-4588-b1d3-216588ae5e9a">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>
    <style name="mainSkillCategory" hAlign="Left" vAlign="Middle" fontSize="12" isBold="true"/>
    <parameter name="datasource_mainSkillCategories" isForPrompting="false" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
    <parameter name="subreport_subCat_parameter" class="net.sf.jasperreports.engine.JasperReport"/>
    <parameter name="subreport_skill_parameter" class="net.sf.jasperreports.engine.JasperReport"/>  
    <field name = "nameMainSkillCat" class = "java.lang.String"/>       
    <detail>
        <band height="108">
            <textField isStretchWithOverflow = "true">
                <reportElement style="mainSkillCategory" x="0" y="33" width="555" height="25" uuid="1e50be4f-2743-470c-a8ad-1fd91d99f786"/>
                <textElement>
                    <font fontName="Calibri" size="12" isBold="true" pdfFontName="Calibri" isPdfEmbedded="true"/>
                    <paragraph spacingBefore="-15" tabStopWidth="24"/>
                </textElement>
                <textFieldExpression class = "java.lang.String">
                    <![CDATA[$F{nameMainSkillCat}]]>
                </textFieldExpression>
            </textField>

            <subreport>
                <reportElement positionType = "Float" x = "0" y = "10" width = "555" height = "10" isRemoveLineWhenBlank = "true" backcolor = "#99ccff"/>               
                <subreportParameter name="subreport_skill_parameter">
                    <subreportParameterExpression><![CDATA[$P{subreport_skill_parameter}]]></subreportParameterExpression>
                </subreportParameter>
                <subreportParameter name="datasource_skills">
                    <subreportParameterExpression><![CDATA[$P{subreport_skill_parameter}]]></subreportParameterExpression>
                </subreportParameter>
                <dataSourceExpression><![CDATA[$P{datasource_mainSkillCategories}]]></dataSourceExpression>
                <subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{subreport_subCat_parameter}]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

我的 SubSkillCategory.jrxml :

<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="profile_report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="40a9d14e-f38a-4588-b1d3-216588ae5e9a">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>  
    <style name="subSkillCategory" hAlign="Left" vAlign="Middle" fontSize="12" isBold="true"/>      
    <parameter name="datasource_skills" isForPrompting="false" class="net.sf.jasperreports.engine.data.JRBeanCollectionDataSource"/>
    <parameter name="subreport_skill_parameter" class="net.sf.jasperreports.engine.JasperReport"/>
    <field name = "nameSubSkillCat" class = "java.lang.String"/>    
    <detail>
        <band height="100">         
            <textField isStretchWithOverflow = "true">
                <reportElement style="subSkillCategory" x="0" y="0" width="555" height="9" uuid="e0c7832a-2099-4185-abcd-ad85dc935a86"/>
                <textElement>
                    <font fontName="Calibri" size="12" isBold="true" pdfFontName="Calibri" isPdfEmbedded="true"/>
                    <paragraph spacingBefore="-15" tabStopWidth="30"/>
                </textElement>
                <textFieldExpression class = "java.lang.String">
                    <![CDATA[$F{nameSubSkillCat}]]>
                </textFieldExpression>
            </textField>

            <subreport>
                <reportElement positionType = "Float" x = "0" y = "10" width = "555" height = "10" isRemoveLineWhenBlank = "true" backcolor = "#99ccff"/>
                <dataSourceExpression><![CDATA[$P{datasource_skills}]]></dataSourceExpression>
                <subreportExpression class="net.sf.jasperreports.engine.JasperReport"><![CDATA[$P{subreport_skill_parameter}]]></subreportExpression>
            </subreport>
        </band>
    </detail>
</jasperReport>

我的 Main.java :

public static void main(String[] args) {
        try {
                JasperReport jasperReportSKill = JasperCompileManager.compileReport("resources/subReport_skill.jrxml");
                JasperReport jasperReportSubCat = JasperCompileManager.compileReport("resources/subReport_subCat.jrxml");
                JasperReport jasperReportMainCat = JasperCompileManager.compileReport("resources/subReport_mainCat.jrxml");

                JRBeanCollectionDataSource dataSource = new JRBeanCollectionDataSource(getMainSkillCategoryList());

                Map<String, Object> parameters = new HashMap<String, Object>();
                parameters.put("subreport_skill_parameter", jasperReportSKill);
                parameters.put("subreport_subCat_parameter", jasperReportSubCat);       
                parameters.put("datasource_mainSkillCategories", dataSource);

                JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReportMainCat, parameters, new JREmptyDataSource());

//...
}

也就是说,当我尝试生成 MainReport 时,我得到了这个错误:java.lang.NoSuchMethodException: Unknown property 'nameSubSkillCat' on class 'class jasperReports.helloWorld.MainSkillCategory' 我认为这是合乎逻辑的,因为我正在传递给 SubReport_1(即 SubSkillCategory 报告)的数据源MainSkillCategory 报告。

现在我的问题是如何在 MainSkillCategory.jrxml 的子报表块中指定对当前 MainSkillCategory bean 的引用,以便我可以获得 "this.getSubSkillCategories()" 并将其作为我的 dataSourceExpression 传递给 SubReport_1.

抱歉,文字太长了,但我想提供源代码,这样任何人都可以知道问题到底是什么。预先感谢您的帮助。

我找到了问题的解决方案:我应该将现在的 List<SubSkillCategory> 定义为 MainSkillCategory.jrxml 中的一个字段。感谢 Ranjit 回答 @http://community.jaspersoft.com/questions/533552/solved-problem-passing-datasource-subreport.