12

I am creating a simple reporting program using java and iReport (from jasper), which is supposed to create a report in pdf showing PCs with their IP address, their location, whether it's idle or not at the moment (handled by another system), and a list of projects it is currently attached to (managed elsewhere, too).

I'm using iReport for this matter, and have created a dummy collection generating class as follows:

public class PCReports {

    public static java.util.Collection PC_collection;
    public static java.util.Collection generateCollection() {

        PC_collection = new ArrayList<PCLineDTO>();
        PCLineDTO line = new PCLineDTO();
        line.setIP("192.168.1.1");
        line.setLab("location");
        line.setActive(true);
        line.addProjectName("project1");
        line.addProjectName("project2");
        line.addProjectName("project3");
        PC_collection.add(line);

        line = new PCLineDTO();
        line.setIp("192.168.1.2");
        line.setLab("location2");
        line.setActive(false);
        line.addProjectName("project1");
        line.addProjectName("project2");
        PC_collection.add(line);

        return PC_collection;
    }
}

The entity class in this case being:

public class PCLineDTO {
    private String ip;
    private String lab;
    private Boolean active;
    private ArrayList<String> projects;
}

After some searching around the Internet, I found a way to do something similar, using subreports.

The thing is, I don't know how to print a collection of strings passed as a dataSource to this subreport.

In the examples I found on the Internet, for each item in the master collection, the subreports were passed a collection of objects -with their own getter methods for each attribute- instead of a collection of strings as is the case here. In those cases, they accessed the values they needed to use via the iReport syntax, which I was not able to use, for example:

$F{project}

Since iReport looks for a getProject method contained within the objects it receives, but in this case it's a simple String object (without a getProject method, as it were).

Kenji Kina
  • 2,402
  • 3
  • 22
  • 39

4 Answers4

20

Use a subreport or a subdataset.

Pass the subreport a collection datasource

JRBeanCollectionDataSource($F{Projects})

Then in the new subreport create a new field called "_THIS" exactly, this means the bean in the collection passed is the same as the value i want

For more info, check the source code of the class here: JRAbstractBeanDataSource

Note: this is available in JasperReport 3.0.0 im not sure if it exists in previous builds. Hope this helps

Update: just checked the SVN, seems like this feature is implemented in JasperReports 2.0.0

Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
mohdajami
  • 9,604
  • 3
  • 32
  • 53
  • 1
    Thank you, glad it helped. Just a side note, when dealing with Jasper or any other open source project, i tend to pull the source code and attach it to the library in Eclipse. This way its easier to dig inside. Good luck – mohdajami Nov 23 '09 at 15:55
  • I've found complementary details here: http://community.jaspersoft.com/questions/533552/solved-problem-passing-datasource-subreport – Alan CN Oct 07 '15 at 20:18
  • "_THIS" is the key to the success! – Junio Nov 08 '21 at 22:15
3

Interesting. I think you'd better use the List, and then define getName() on the Project class. Then in the subreport define a variable "name". It will work this way, and it will allow you to add easily additional information, like project duration, team-lead, etc.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • Thank you for your answer. I considered this and might actually implement it this way, if things come to that. However, regretfully (and admittedly my fault), other parts of the program are using this list of Strings, and was wondering if there was a way to circumvent the hassle and error-prone task of searching and replacing where it has been used. – Kenji Kina Nov 23 '09 at 15:17
0

As Bozho says, in case proyects was an array of complex object you should reference it as a field of type java.util.Collection an then pass it to the inner subreport the same way medopal indicates. And don´t put the _THIS field.

Daniel Carroza
  • 310
  • 1
  • 8
0

To elaborate on this without using _THIS: let's say a java bean has a list of subBeans and this subBean has a complex format and we want to print each subBean in a custom way. I quote an example where the subDataset element is on the report level and the componentElement is in the detail band:

<subDataset name="ListOfSubBeans" uuid="66c86e41-c565-4f18-bccf-1a1b2a567585">
    <field name="subBeanField_1" class="java.lang.String">
        <fieldDescription><![CDATA[subBeanField_1]]></fieldDescription>
    </field>
</subDataset>

...

        <componentElement>
            <reportElement x="780" y="0" width="100" height="30" uuid="f73864b9-46dd-4adb-8dad-a6bd8dfae64e">
                <property name="net.sf.jasperreports.export.headertoolbar.table.name" value=""/>
            </reportElement>
            <jr:list xmlns:jr="http://jasperreports.sourceforge.net/jasperreports/components" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports/components http://jasperreports.sourceforge.net/xsd/components.xsd" printOrder="Vertical">
                <datasetRun subDataset="ListOfSubBeans" uuid="a8dd1c2b-3ac0-4ffa-b9d0-08e4890e199a">
                    <dataSourceExpression><![CDATA[new net.sf.jasperreports.engine.data.JRBeanCollectionDataSource($F{listOfSubBeans})]]></dataSourceExpression>
                </datasetRun>
                <jr:listContents height="30" width="100">
                    <textField>
                        <reportElement x="0" y="0" width="100" height="30" uuid="61700c18-6bb9-45da-a235-b76b9f76a2ea"/>
                        <textFieldExpression><![CDATA[$F{subBeanField_1}]]></textFieldExpression>
                    </textField>
                </jr:listContents>
            </jr:list>
        </componentElement>

...

So, the master dataset has declared that the master bean has a member variable that is a list: listOfSubBeans. This java.util.List is used to feed the datasource of the jr:list, while the fields of the jr:list are declared using a subDataset called ListOfSubBeans (pay attention to case sensitivity).

LovaBill
  • 5,107
  • 1
  • 24
  • 32