I am developing the Invoice printing System using the Jasper report, Now I have can print the report but it will take 2000ms to load the report, also 2000ms take to start the printing,
These are I am using the JAR FILES,
commons-beanutils-1.4
commons-digester-1.7
commons-logging-1.0.3
commons-beanutils-1.4
groovy-all-1.7.5
batik-all-1.7
barcode4j-2.1
itextpdf-5.1.0
jasperreports-6.0.3
xercesImpl-2.11.0
xml-apis-ext-1.3.04
preparedStatement = conn.prepareStatement(sqlString);
resultSet = preparedStatement.executeQuery();
if (resultSet.next()) {
HashMap<String, Object> hm = new HashMap<>();
JasperDesign jasperDesign = JRXmlLoader.load(new File(
"C:/Invoice/Invoice.jrxml"));
JRDesignQuery designQuery = new JRDesignQuery();
designQuery.setText(sqlString);
jasperDesign.setQuery(designQuery);
JasperReport jasperReport = JasperCompileManager
.compileReport(jasperDesign);
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport, null, conn);
for (int i = 0; i < copies; i++) {
JasperPrintManager.printReport(jasperPrint, false);
}
JasperViewer.viewReport(jasperPrint);
The above code I used to print the report but, getting too much time to load the report. Please suggest my fault and some other idea...
I guess the SQL query could be the problem. Have you tried executing it in a sql query tool and check how long it runs? Optimizing it should yield a performance win.
You are also running the query twice: before the report and when you are filling it via the JasperFillManager.fillReport() call.
If there are no specific reasons to check wheter the query contains any records, I would recommand to let JasperReports handle the query and the case that no record is found. You can determine a specific behaviour in that case via the "When No Data Type" property in the reportdesign.
Related
I have total 5 reports in 5 different files and i want to make only single excel file which contains these five reports and five different sheets how it will be possible with jasper report?
Please help
Thanks in advance
Instead of creating 5 reports just use one report and set the property net.sf.jasperreports.export.xls.one.page.per.sheet to true.
Then just rename them with net.sf.jasperreports.export.xls.sheet.name
and use the Page Break element
Search on the internet for more information if needed. There are actually a lot of examples for this.
First you have to create JasperPrint objects for each sheet as you normally would.
JasperPrint firstSheet = ...;
JasperPrint secondSheet = ...;
JasperPrint thirdSheet = ...;
JasperPrint fourthSheet = ...;
JasperPrint fifthSheet = ...;
Now JasperPrint already have the datasource at this point. Use the Arraylist to add the JasperPrint object and the exporter will use each object to create a sheet
JRXlsxExporter exporter = new JRXlsxExporter();
ArrayList<JasperPrint> list = new ArrayList<JasperPrint>();
list.add(firstSheet);
list.add(secondSheet);
list.add(thirdSheet);
list.add(fourthSheet);
list.add(fifthSheet);
exporter.setExporterInput(SimpleExporterInput.getInstance(list));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputFile));
exporter.exportReport();
And you need to use net.sf.jasperreports.engine.export.ooxml.JRXlsxExporter as import
I have a requirement,where I can select multiple records,and choose the action to generate zipped report with document each(pdf in my case) for each of the selected entries.
For example Employee1,Employee2,Employee3 would be selected,and when I choose to generate report,3 reports should be generated one each for the employee,and the output has to be zipped and downloaded.
For now what I do is generate the jasperPrint and export the report to ZipOutputstream with a new zipentry for each of the employee.
This means running the queries thrice and adding the outputstream to zip.
Is there a better way of doing it?
Your solution is normally the correct way, the alternatives are if you need to avoid multiple queries.
Load all you data in to a List<Employee> pass a new JRBeanCollectionDataSource(List<Employee>) for each Employee. (This decrease queries but increase memory usage).
If you have control of the pages (example 1 employee per page), you can generate 1 pdf with all employees and then use itext to split it in multiple pdf.
PdfReader reader = new PdfReader("nameOfReport.pdf");
int n = reader.getNumberOfPages();
int i = 0;
while ( i < n ) {
Document document = new Document(reader.getPageSizeWithRotation(1));
PdfCopy writer = new PdfCopy(document, new FileOutputStream("Employee_" + i + ".pdf"));
document.open();
PdfImportedPage page = writer.getImportedPage(reader, ++i);
writer.addPage(page);
document.close();
writer.close();
}
I am using jasper reports and want to give user to select the db name as input control and want to use that in query.
tool used is ireport /jasper soft studio 6.x
Got the solution for above question I used list of input control and then used the parameter value as
$P!{parametername}
Same as usage of table name as parameter/input control in jasper.
If I am understanding correctly, following code might help you.
Ofcourse "foo DB" and "baz DB" should have same tables.
Connection conn;
// Change the DB depend on input value.
if (userInput.equals("foo")){
conn = DriverManager.getConnection("jdbc:mysql://localhost/foo", "user", "password");
}
else if (userInput.equals("baz")){
conn = DriverManager.getConnection("jdbc:mysql://localhost/baz", "user", "password");
}
else{
// error
}
JasperReport jasper = (JasperReport)JRLoader.loadObject(your_jasper_filePath);
Map paramMap = new HashMap();
paramMap.put("param1", "some_param1");
paramMap.put("param2", "some_param2");
JasperPrint print = JasperFillManager.fillReport(jasper, paramMap, conn);
JasperExportManager.exportReportToPdfFile(print, PdfPath);
Is it possible to execute "insert query" in IReports/jasper reports during report generation?
Yes, the idea you need is parameters using this syntax: $P!{PARAM_NAME}.
So your entire SQL query (or other type of query) could be simply $P!{SQL}. Then you pass in exactly the dynamic SQL that you need.
UPDATE:
After reading Sharad's comment, I realized that my answer above is not good. What I wrote is true... but it fails to address the core question.
No, your report cannot really execute an insert statement. Strictly speaking, I'm sure it's not impossible. You could add a scriptlet or custom function in a .jar file that makes a connection and does an insert. But realistically speaking... a report will execute one or more queries. The JR framework is not intended to execute inserts or updates.
Yes you can. You can execute the query when you want to display the report. Here is a sample that works for me.
try {
Map parameters = new HashMap();
connectionString ="jdbc:mysql://localhost/myDb", "myUsername", "myPassword"
Class.forName("com.mysql.jdbc.Driver");
Connection conn = DriverManager.getConnection(connectionString);
PreparedStatement stmt = conn.prepareStatement(query);
ResultSet rs = stmt.executeQuery();
JRResultSetDataSource rsdt = new JRResultSetDataSource(rs);
JasperPrint jp;
jp = JasperFillManager.fillReport("sourceFileName.jasper", parameters, rsdt);
JasperViewer jv = new JasperViewer(jp, false);
jv.setVisible(true);
} catch (ClassNotFoundException | SQLException | JRException ex) {
ex.printStackTrace();
}
Well I have a Cyrstal report which has 4 sub reports on and it is linked through an ItemID column and a Culture, so it has a parameter value "?Pm-ItemID" and "?Pm-Culture" now i'm using DataSet to load the data to the Crystal Report's datasource, when I run the report its giving me an error which was an asking parameter field was not suplied, so i think my question would be what am I going to pass to those ParameterFields?
here's an idea.
ReportDocument myreport = new ReportDocument();
myreport.Load("C:\MyReport.rpt");
DataSet ds = GenerateReportData();
myreport.SetDataSource(ds);
//Loop through each to Load the DataSet
for (int i = 0; i < myreport.Subreports.Count; i++)
{
ReportDocument subreport = myreport.SubReports[i];
DataSet subds = GenerateReportData(subreport.name)
subreport.SetDataSource(subds);
}
//I can see that there's a parameterfields in myreport.ParameterFields
//As I look through inside it there are 8 ParameterFields repeating Pm-ItemID and Pm-Culture
foreach (ParameterField pf in myreport.ParameterFields)
{
myreport.SetParameterValue(pf.Name, Value???);
}
Well, I see what's wrong.
ReportDocument subreport = myreport.SubReports[i];
DataSet subds = GenerateReportData(subreport.name)
subreport.SetDataSource(subds);
should not be done this way, it should be
DataSet subds = GenerateReportData(subreport.name)
myreport.SubReports[i].SetDataSource(subds);
I don't know about Crystal, but in SSRS it works like this:
1) create a subreport and create some parameters
2) create the main report, put there the subreport and in the properties you can specify what to bind to the subreport's parameters
Conclusion: I don't think this is supposed to be set in code, rather report designer.