Reputation: 429
I have created Balances report using Jaspersoft Studio. I have also created hyperlink on a field in this report with below properties:
Link Type: ReportExecution
Parameters: _report
The value of above parameter is "GLLedger" which is another jasper report present in the same folder.
In Java, when I invoke this report, and click the hyperlink, then GLLedger report does not appear but get below warning on console:
Hyperlink of type ReportExecution
Implement your own JRHyperlinkListener to manage this type of event.
In Java, I am using JasperViewer to preview report. Below is the code:
JasperPrint jasperPrint = JasperFillManager.fillReport(reportPath, hm, connection);
JasperViewer v = new JasperViewer(jasperPrint, false);
v.setVisible(true);
Can you please guide as how to call another report from one jasper report?
Upvotes: 2
Views: 1370
Reputation: 21710
If you like to use this in a swing application your main problem (at least in jasper report version <6.1.1) is that you have no direct method to add a JRHyperLinkListener
From source code of JRViewer
:
//FIXME add a method to do addHyperlinkListener without subclassing
protected JRViewerPanel createViewerPanel(){return new JRViewerPanel(viewerContext);}
I will show you a way how you can subclass this class, implement the JRHyperlinkListener
and open a new frame with a report name received from link.
Creating a class that extends the net.sf.jasperreports.swing.JRViewer
and implements the net.sf.jasperreports.view.JRHyperlinkListener
, I'm adding imports since library have old classes with same name,
import java.awt.BorderLayout;
import java.util.HashMap;
import javax.swing.JFrame;
import net.sf.jasperreports.engine.JRException;
import net.sf.jasperreports.engine.JRPrintHyperlink;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.swing.JRViewer;
import net.sf.jasperreports.swing.JRViewerPanel;
import net.sf.jasperreports.view.JRHyperlinkListener;
public class HyperLinkTest extends JRViewer implements JRHyperlinkListener {
private static final long serialVersionUID = -6429615130889276357L;
public HyperLinkTest(JasperPrint jrPrint){
super(jrPrint);
}
/**
* Since JRViewerPanel is protected our only way to add listener is
* to Override
*/
@Override
protected JRViewerPanel createViewerPanel()
{
JRViewerPanel panel = new JRViewerPanel(viewerContext);
panel.addHyperlinkListener(this);
return panel;
}
/**
* The listener gets the hyperlink reference and open relative report
*/
@Override
public void gotoHyperlink(JRPrintHyperlink arg) throws JRException {
JasperReport report = JasperCompileManager.compileReport("jasper/" + arg.getHyperlinkReference() + ".jrxml");
JasperPrint jasperPrint = JasperFillManager.fillReport(report, new HashMap<String, Object>());
HyperLinkTest nextReport = new HyperLinkTest(jasperPrint);
openReport("Navigated to", JFrame.DISPOSE_ON_CLOSE, nextReport);
}
/**
* static method that creates a frame and adds the JRViewer to it and
* open a new frame with the viewer
*/
public static void openReport(String title, int defaultCloseOperation, JRViewer hyperLinkReport){
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame = new JFrame(title);
frame.setDefaultCloseOperation(defaultCloseOperation);
frame.getContentPane().setLayout(new BorderLayout());
frame.getContentPane().add(hyperLinkReport,BorderLayout.CENTER);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
/**
* Main method to test
*/
public static void main(String[] args) throws JRException {
JasperReport report = JasperCompileManager.compileReport("jasper/hyperlink1.jrxml");
JasperPrint jasperPrint = JasperFillManager.fillReport(report, new HashMap<String, Object>());
HyperLinkTest test = new HyperLinkTest(jasperPrint);
openReport("Test hyperlink", JFrame.EXIT_ON_CLOSE, test);
}
}
As can be seen in code I'm using hyperlinkType="ReportExecution"
and in passing name of next report in hyperlinkReferenceExpression
.
Report 1 (hyperlink1.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="hyperlink1" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="601103bc-66ab-45a5-8422-ccb6f3e02ec2">
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="50">
<textField hyperlinkType="ReportExecution">
<reportElement x="0" y="0" width="100" height="20" uuid="8dc8f664-60b3-4b10-8a55-23120bea1f85"/>
<textElement>
<font size="14" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Hello"]]></textFieldExpression>
<hyperlinkReferenceExpression><![CDATA["hyperlink2"]]></hyperlinkReferenceExpression>
</textField>
</band>
</title>
</jasperReport>
Report 2 (hyperlink2.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="hyperlink1" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="601103bc-66ab-45a5-8422-ccb6f3e02ec2">
<queryString>
<![CDATA[]]>
</queryString>
<title>
<band height="50">
<textField hyperlinkType="ReportExecution">
<reportElement x="113" y="0" width="100" height="20" uuid="8dc8f664-60b3-4b10-8a55-23120bea1f85"/>
<textElement>
<font size="14" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["World"]]></textFieldExpression>
<anchorNameExpression><![CDATA["World"]]></anchorNameExpression>
<hyperlinkReferenceExpression><![CDATA["hyperlink1"]]></hyperlinkReferenceExpression>
</textField>
</band>
</title>
</jasperReport>
First window will open with "Hello", if you click "Hello", second window will open with "World"
Notes: If I did this application probably I would pre-compile all
.jrxml
to.jasper
, hence avoid compiling during run-time and probably I would have used multiple classes (1 for frame, 1 for viewer) avoiding static methods, however I have simplified to better fit SO format, concentrating on showing how aJRHyperLinkListener
can be implemented in a Swing application.
Can you please tell me how to pass connection Object and other parameters from first report to second from this comment
To pass objects (fields, parameters, variables or any other expression) to the JRHyperlinkListener
you should hyperlinkParameter
in jrxml.
Example (see the hyperlinkParameter
and it's hyperlinkParameterExpression
)
<?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="hyperlink1" pageWidth="595" pageHeight="842" whenNoDataType="AllSectionsNoDetail" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="601103bc-66ab-45a5-8422-ccb6f3e02ec2">
<parameter name="reportDate" class="java.util.Date" isForPrompting="false">
<defaultValueExpression><![CDATA[new java.util.Date()]]></defaultValueExpression>
</parameter>
....
<textField hyperlinkType="ReportExecution">
<reportElement x="0" y="0" width="100" height="20" uuid="8dc8f664-60b3-4b10-8a55-23120bea1f85"/>
<textElement>
<font size="14" isBold="true"/>
</textElement>
<textFieldExpression><![CDATA["Hello"]]></textFieldExpression>
<hyperlinkReferenceExpression><![CDATA["hyperlink2"]]></hyperlinkReferenceExpression>
<hyperlinkParameter name="reportTime">
<hyperlinkParameterExpression><![CDATA[$P{reportDate}]]></hyperlinkParameterExpression>
</hyperlinkParameter>
</textField>
....
</jasperReport>
This parameter can now be accessed by the JRHyperlinkListener
, in example I pass it to parameter map for next report, naturally the jphlp.getValue()
will continue to be instanceof java.util.Date
@Override
public void gotoHyperlink(JRPrintHyperlink arg) throws JRException {
Map<String, Object> nextReportParams = new HashMap<>();
List<JRPrintHyperlinkParameter> params = arg.getHyperlinkParameters().getParameters();
for (JRPrintHyperlinkParameter jphlp : params) {
if ("reportTime".equals(jphlp.getName())){
nextReportParams.put("previousReportTime",jphlp.getValue());
}
}
JasperReport report = JasperCompileManager.compileReport("jasper/" + arg.getHyperlinkReference() + ".jrxml");
JasperPrint jasperPrint = JasperFillManager.fillReport(report, nextReportParams);
HyperLinkTest nextReport = new HyperLinkTest(jasperPrint);
openReport("Navigated to", JFrame.DISPOSE_ON_CLOSE, nextReport);
}
Notes: Watch out passing main report datasource (this will be at the end, you cannot re-use it, if you do not rewind it first) and connection (this may be closed), it's better to pass a new connection to next report.
Upvotes: 3