I have a web application with a dropdown from where user could select the type of report viz. report1, report2, report3, etc.
Based on the report selected, a Jasper report is compiled on the server and opens as a pop up in PDF format.
On the server side, I am implementing each report in a separate method using below code say for e.g. for report1:
JRBeanCollectionDataSource report1DataSource = new JRBeanCollectionDataSource(resultSetBeanListReport1);
InputStream inputStreamReport1 = new FileInputStream(request.getSession().getServletContext ().getRealPath(jrxmlFilePath + "report1.jrxml"));
JasperDesign jasperDesignReport1 = JRXmlLoader.load(inputStreamReport1);
JasperReport jasperReportReport1 = JasperCompileManager.compileReport(jasperDesignReport1);
bytes = JasperRunManager.runReportToPdf(jasperReportReport1, titleMapReport1, report1DataSource);
Similarly, report2 is in a separate method with below code:
JRBeanCollectionDataSource invstSummDataSource = new JRBeanCollectionDataSource(resultSetBeanListInvstOfSumm);
InputStream inputStreamInvstSumm = new FileInputStream(request.getSession().getServletContext().getRealPath(jrxmlFilePath + "investSummary.jrxml"));
JasperDesign jasperDesignInvstSumm = JRXmlLoader.load(inputStreamInvstSumm);
JasperReport jasperReportInvstSumm = JasperCompileManager.compileReport(jasperDesignInvstSumm);
bytes = JasperRunManager.runReportToPdf(jasperReportInvstSumm, titleMapInvstSumm, invstSummDataSource);
Now I have a requirement that if report1 is selected from the dropdown, the resulting PDF should contain all the reports one after other in the same PDF.
How can I combine above two lines of codes to finally generate a single PDF?
Here is sample code for combining multiple jasper prints
List<JasperPrint> jasperPrints = new ArrayList<JasperPrint>();
// Your code to get Jasperreport objects
JasperReport jasperReportReport1 = JasperCompileManager.compileReport(jasperDesignReport1);
jasperPrints.add(jasperReportReport1);
JasperReport jasperReportReport2 = JasperCompileManager.compileReport(jasperDesignReport2);
jasperPrints.add(jasperReportReport2);
JasperReport jasperReportReport3 = JasperCompileManager.compileReport(jasperDesignReport3);
jasperPrints.add(jasperReportReport3);
JRPdfExporter exporter = new JRPdfExporter();
//Create new FileOutputStream or you can use Http Servlet Response.getOutputStream() to get Servlet output stream
// Or if you want bytes create ByteArrayOutputStream
ByteArrayOutputStream out = new ByteArrayOutputStream();
exporter.setParameter(JRExporterParameter.JASPER_PRINT_LIST, jasperPrints);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, out);
exporter.exportReport();
byte[] bytes = out.toByteArray();
This answer is to help user using latest version of Jasper-Report. In
#Sangram Jadhav accept answer the
JRExporterParameter.JASPER_PRINT_LIST is deprecated
The current code would be:
Map<String, Object> paramMap = new HashMap<String, Object>();
List<JasperPrint> jasperPrintList = new ArrayList<JasperPrint>();
JasperPrint jasperPrint1 = JasperFillManager.fillReport(report1, paramMap);
jasperPrintList.add(jasperPrint1);
JasperPrint jasperPrint2 = JasperFillManager.fillReport(report2, paramMap);
jasperPrintList.add(jasperPrint2);
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(jasperPrintList)); //Set as export input my list with JasperPrint s
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput("pdf/output.pdf")); //or any other out streaam
SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
configuration.setCreatingBatchModeBookmarks(true); //add this so your bookmarks work, you may set other parameters
exporter.setConfiguration(configuration);
exporter.exportReport();
You can either merge reports before generating PDFs using JasperPrint or after generating PDFs using iText.
For the JasperPrint solution: you will generate the 2 (or more) JasperPrints then get the content pages and concat them.
JasperPrint jp1 = JasperFillManager.fillReport(url.openStream(), parameters,
new JRBeanCollectionDataSource(inspBean));
JasperPrint jp2 = JasperFillManager.fillReport(url.openStream(), parameters,
new JRBeanCollectionDataSource(inspBean));
List pages = jp2 .getPages();
for (int j = 0; j < pages.size(); j++) {
JRPrintPage object = (JRPrintPage)pages.get(j);
jp1.addPage(object);
}
JasperViewer.viewReport(jp1,false);
For the iText solution after generating the PDFs:
void concatPDFs(List<InputStream> streamOfPDFFiles, OutputStream outputStream, boolean paginate) {
Document document = new Document();
try {
List<InputStream> pdfs = streamOfPDFFiles;
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
Iterator<InputStream> iteratorPDFs = pdfs.iterator();
// Create Readers for the pdfs.
while (iteratorPDFs.hasNext()) {
InputStream pdf = iteratorPDFs.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages += pdfReader.getNumberOfPages();
}
// Create a writer for the outputstream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
BaseFont bf = BaseFont.createFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
PdfContentByte cb = writer.getDirectContent(); // Holds the PDF
// data
PdfImportedPage page;
int currentPageNumber = 0;
int pageOfCurrentReaderPDF = 0;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Loop through the PDF files and add to the output.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create a new page in the target for each source page.
while (pageOfCurrentReaderPDF < pdfReader.getNumberOfPages()) {
document.newPage();
pageOfCurrentReaderPDF++;
currentPageNumber++;
page = writer.getImportedPage(pdfReader, pageOfCurrentReaderPDF);
cb.addTemplate(page, 0, 0);
// Code for pagination.
if (paginate) {
cb.beginText();
cb.setFontAndSize(bf, 9);
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "" + currentPageNumber + " of " + totalPages, 520, 5, 0);
cb.endText();
}
}
pageOfCurrentReaderPDF = 0;
}
outputStream.flush();
document.close();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (document.isOpen())
document.close();
try {
if (outputStream != null)
outputStream.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
Here is my code which i use on grails code .Its gives me two different report in one pdf.
String reportDir = Util.getReportDirectory() // my report directory
Map reportParams = new LinkedHashMap()
Map reportParams1 = new LinkedHashMap()
String outputReportName="Test_Output_copy"
reportParams.put('parameter name',"parameter")
reportParams1.put('copy',"Customer's Copy")
JasperReportDef reportDef1 = new JasperReportDef(name: 'testBillReport.jasper', fileFormat: JasperExportFormat.PDF_FORMAT,
parameters: reportParams, folder: reportDir)
JasperReportDef reportDef2 = new JasperReportDef(name: 'testBillReport.jasper', fileFormat: JasperExportFormat.PDF_FORMAT,
parameters: reportParams1, folder: reportDir)
List<JasperReportDef> jasperPrintList = new ArrayList<JasperReportDef>();
jasperPrintList.add(reportDef1);
jasperPrintList.add(reportDef2);
ByteArrayOutputStream report1 = jasperService.generateReport(jasperPrintList);
response.setHeader("Content-disposition", "inline;filename="+outputReportName+'.pdf')
response.contentType = "application/pdf"
response.outputStream << report1.toByteArray()
You can try this one this is work for me
JasperPrint jp1 = JasperFillManager.fillReport(reportFile1,reportParams,Connection);
JasperPrint jp2 = JasperFillManager.fillReport(reportFile2,reportParams,Connection);
for (int j = 0; j < jp1.getPages().size(); j++) {
//Add First report to second report
jp2.addPage((JRPrintPage) jp1.getPages().get(j));
}
Related
I am using itextpdf-5.5.4 jar to merge or add two pdf into one PDF.
I did not get any error or exception while running code but displayed below text in Merged PDF. I did not get below text when i open individual PDF's.
The document you are trying to load requires Adobe Reader 8 or higher.
You may not have the Adobe Reader installed or your viewing
environment may not be properly configured to use Adobe Reader.
For information on how to install Adobe Reader and configure your
viewing environment please see
http://www.adobe.com/go/pdf_forms_configure.
void mergePdfFiles(List<InputStream> inputPdfList, OutputStream outputStream) throws Exception {
// Create document and pdfReader objects.
Document document = new Document();
List<PdfReader> readers = new ArrayList<PdfReader>();
int totalPages = 0;
// Create pdf Iterator object using inputPdfList.
Iterator<InputStream> pdfIterator = inputPdfList.iterator();
// Create reader list for the input pdf files.
while (pdfIterator.hasNext()) {
InputStream pdf = pdfIterator.next();
PdfReader pdfReader = new PdfReader(pdf);
readers.add(pdfReader);
totalPages = totalPages + pdfReader.getNumberOfPages();
}
// Create writer for the outputStream
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
// Open document.
document.open();
// Contain the pdf data.
PdfContentByte pageContentByte = writer.getDirectContent();
PdfImportedPage pdfImportedPage;
int currentPdfReaderPage = 1;
Iterator<PdfReader> iteratorPDFReader = readers.iterator();
// Iterate and process the reader list.
while (iteratorPDFReader.hasNext()) {
PdfReader pdfReader = iteratorPDFReader.next();
// Create page and add content.
while (currentPdfReaderPage <= pdfReader.getNumberOfPages()) {
document.newPage();
pdfImportedPage = writer.getImportedPage(pdfReader, currentPdfReaderPage);
pageContentByte.addTemplate(pdfImportedPage, 0, 0);
currentPdfReaderPage++;
}
currentPdfReaderPage = 1;
}
// Close document and outputStream.
outputStream.flush();
document.close();
outputStream.close();
System.out.println("Pdf files merged successfully.");
}
public static void main(String args[]) {
try {
List<InputStream> inputPdfList = new ArrayList<InputStream>();
inputPdfList.add(new FileInputStream("pdf1.pdf"));
inputPdfList.add(new FileInputStream("pdf2.pdf"));
OutputStream outputStream = new FileOutputStream("Merge-PDF.pdf");
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
mergePdfFiles(inputPdfList, byteStream);
byte[] byteS = byteStream.toByteArray();
outputStream.write(byteS);
} catch (Exception e) {
e.printStackTrace();
}
}
Please help me out on this.
We have a requirement where we need to add text watermark on magazines which has multiple rich images on each page. I tried com.itextpdf.jar version 5.0.6 to add the watermark but eventually I am able to remove it using Adobe Acrobat Pro.
I tried below option also but that too didn't work.
stamper.setFreeTextFlattening(true);
Is it possible with iText to add a watermark which can not be removed without much effort.
Below is my implementation.
public static void addWaterMark() throws IOException, DocumentException {
PdfReader reader = new PdfReader("C:/Trade-catalog/Catalog2017.pdf");
ByteArrayOutputStream outputPdf = new ByteArrayOutputStream();
PdfStamper stamper = new PdfStamper(reader, outputPdf);
String bodyWatermarkText = "12345 - John Smith";
String bodyWatermarkRotation = "35";
String footerWatermarkText = "Richard Parker";
BaseFont font = BaseFont.createFont("/fonts/micross.ttf", "Cp1250", BaseFont.EMBEDDED);
PdfGState state = new PdfGState();
state.setFillOpacity(0.3f);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
Rectangle thisPageSize = reader.getPageSize(i);
PdfPatternPainter bodyPainter = stamper.getOverContent(i).createPattern(thisPageSize.getWidth(),
thisPageSize.getHeight());
bodyPainter.setColorFill(new BaseColor(0, 0, 0));
bodyPainter.beginText();
bodyPainter.setTextRenderingMode(PdfPatternPainter.TEXT_RENDER_MODE_FILL);
bodyPainter.setFontAndSize(font, 60);
bodyPainter.showTextAlignedKerned(Element.ALIGN_CENTER, bodyWatermarkText, thisPageSize.getWidth() / 2,
thisPageSize.getHeight() / 2, Integer.valueOf(bodyWatermarkRotation));
bodyPainter.showTextAlignedKerned(Element.ALIGN_RIGHT, footerWatermarkText, thisPageSize.getWidth() * 0.97f,
thisPageSize.getHeight() * 0.015f, 0);
bodyPainter.endText();
PdfContentByte overContent = stamper.getOverContent(i);
overContent.setGState(state);
overContent.setColorFill(new PatternColor(bodyPainter));
overContent.rectangle(thisPageSize.getLeft(), thisPageSize.getBottom(), thisPageSize.getWidth(),
thisPageSize.getHeight());
overContent.fill();
overContent.setFlatness(100);
}
stamper.close();
FileOutputStream outputStream = new FileOutputStream(
"C:/Trade-catalog/output/TradeCatalog2017Watermarked_bodyPainter.pdf");
outputPdf.writeTo(outputStream);
outputPdf.close();
reader.close();
}
I am using iText 2.1.7 to merge some document PDFs into a single PDF. The code below seems to work just fine, however it appears in some instances the rendered PDF is scaled slightly smaller, like at 90% of the PDF if printed directly before processing.
Is there a way to keep the current size?
private void doMerge(List<InputStream> list, OutputStream outputStream) throws DocumentException, IOException {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document, outputStream);
document.open();
PdfContentByte cb = writer.getDirectContent();
for (InputStream in : list) {
PdfReader reader = new PdfReader(in);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
document.newPage();
//import the page from source pdf
PdfImportedPage page = writer.getImportedPage(reader, i);
//add the page to the destination pdf
cb.addTemplate(page, 0, 0);
}
}
outputStream.flush();
document.close();
outputStream.close();
}
The API was already available with that version. I would even suggest to use PdfSmartCopy instead of PdfCopy (or PdfCopyFields if form fields are inside).
private PdfSmartCopy copier;
public void SomeMainMethod(){
Document finalPdf = new Document();
copier = new PdfSmartCopy(finalPdf, outputstream);
//Start adding pdfs
finalPdf.open();
//add n documents
addDocuments(...);
finalPdf.close();
formCopier.close();
}
public void addDocument(InputStream pdfDocument, int startPage, int endPage){
PdfReader reader= new PdfReader(pdfDocument);
int startPage = 1;
int endPage = reader.getNumberOfPages();
for (int i = startPage; i <= endPage; i++) {
copier.addPage(this.copier.getImportedPage(reader,i));
}
if(copier!=null){
//Important: Free Memory!
copier.flush();
copier.freeReader(reader);
}
if (reader!=null) {
reader.close();
reader=null;
}
pdfDocument.close();
}
We are using jasper version 6. We can export to EXCEL ( XLS and XLSX) .
Below code works for XLS and creates a RTL sheet:
exporter = new JRXlsExporter();
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(out));
SimpleXlsReportConfiguration xlsReportConfig = new SimpleXlsReportConfiguration();
xlsReportConfig.setSheetDirection(RunDirectionEnum.RTL);
exporter.setConfiguration(xlsReportConfig);
However when I try the same code to make a XLSX file the sheet direction will not change to RTL:
exporter = new JRXlsxExporter();
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(out));
SimpleXlsxReportConfiguration xlsxReportConfiguration = new SimpleXlsxReportConfiguration();
xlsxReportConfiguration.setSheetDirection(RunDirectionEnum.RTL);
exporter.setConfiguration(xlsxReportConfiguration);
I finally used below code ( It is costy but works) , which is mentioned at https://community.jaspersoft.com/questions/523041/right-left-arabic-reports
public class ReportUtils {
private ReportUtils(){
}
/**
* mirror each page layout
* #param print
*/
public static void mirrorLayout(JasperPrint print) {
int pageWidth = print.getPageWidth();
for (Object element : print.getPages()) {
JRPrintPage page = (JRPrintPage) element;
mirrorLayout(page.getElements(), pageWidth);
}
}
/**
* mirror a list of elements
* #param print
*/
protected static void mirrorLayout(List<?> elements, int totalWidth) {
for (Iterator<?> it = elements.iterator(); it.hasNext();) {
JRPrintElement element = (JRPrintElement) it.next();
int mirrorX = totalWidth - element.getX() - element.getWidth();
element.setX(mirrorX);
if (element instanceof JRPrintFrame) {
JRPrintFrame frame = (JRPrintFrame) element;
mirrorLayout(frame.getElements(), frame.getWidth());
}
}
}
}
Use it like:
Exporter exporter;
ByteArrayOutputStream out = new ByteArrayOutputStream();
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(out));
JasperPrint jasperPrint = JasperFillManager.fillReport(report,
params, dataSource != null ? new JRMapArrayDataSource(
dataSource) : new JREmptyDataSource());
ReportUtils.mirrorLayout(jasperPrint);
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.exportReport();
return out.toByteArray();
Seems to be a bug in the jasper report library tested with v 6.1.1, adding code below after export it will work correctly (with poi libraries included in jasper report distribution, so no bug in POI...).
//out is the file after jasper report export
XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(out));
int ns = workbook.getNumberOfSheets();
for (int i = 0; i < ns; i++) {
XSSFSheet sheet = workbook.getSheetAt(i);
sheet.setRightToLeft(true);
}
FileOutputStream outStream = new FileOutputStream(out);
workbook.write(outStream);
outStream.close();
Current bug report tracker on jaspersoft community
I had a problem generating a report in XLSX, in the last version of JasperReports 6.1, but this code works for me:
Firstly, i configure the jasper print
JRSwapFile swapFile = new JRSwapFile(".", 1024, 1024);
JRVirtualizer virtualizer = new JRSwapFileVirtualizer(100, swapFile, true);
parameters.put(JRParameter.REPORT_VIRTUALIZER, virtualizer);
JasperPrint print = JasperFillManager.fillReport(stream, parameters, dbConnection);
List<JasperPrint> prints = new ArrayList<JasperPrint>();
prints.add(print);
After that, i configure the output for the generated report, in my case the report will be managed in memory by an ByteArrayOutputStream:
ByteArrayOutputStream output = new ByteArrayOutputStream();
I create an instance of JRXlsxExporter for generate a file with the .xslx extension, and putting the printers and the output:
JRXlsxExporter exporter = new JRXlsxExporter();
exporter.setExporterInput(SimpleExporterInput.getInstance(prints));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(output));
The next step is to create the report configuration for the exporter, when i put this code my report works!, so you must use it!:
SimpleXlsxReportConfiguration xlsxReportConfiguration = new SimpleXlsxReportConfiguration();
xlsxReportConfiguration.setSheetDirection(RunDirectionEnum.RTL);
exporter.setConfiguration(xlsxReportConfiguration);
Finally, generate the report and close the outputStream:
exporter.exportReport();
output.flush();
output.close();
I hope that this works for you
I´m trying to merge into one file with one or more PDF files stored files and a JasperReports file using iText.
I did this method.
Map<String, Object> parameters = new HashMap<String, Object>();
List<String> arquivos = new LinkedList<String>();
arquivos.add("/Formulario/teste.jrxml");
arquivos.add("/Formulario/teste.pdf");
try {
Document document = new Document(PageSize.A4);
document.setMargins(0F, 0F, 0F, 0F);
PdfCopy pdfCopy = new PdfCopy(document, new FileOutputStream("c:\\labels\\teste.pdf"));
pdfCopy.setMargins(0, 0, 0, 0);
document.open();
PdfReader pdfReader = null;
InputStream inputStream = null;
for (String arquivo : arquivos) {
inputStream = ReportService.class.getResourceAsStream(arquivo);
if (FilenameUtils.getExtension(arquivo).equals("jrxml")) {
JasperReport report = JasperCompileManager.compileReport(inputStream);
JasperPrint jasperPrint = JasperFillManager.fillReport(report, parameters, new JREmptyDataSource());
inputStream = new ByteArrayInputStream(JasperExportManager.exportReportToPdf(jasperPrint));
}
pdfReader = new PdfReader(inputStream);
for (int i = 1; i <= pdfReader.getNumberOfPages(); i++) {
pdfCopy.addPage(pdfCopy.getImportedPage(pdfReader, i));
}
pdfCopy.freeReader(pdfReader);
pdfReader.close();
}
document.close();
} catch (DocumentException | IOException | JRException e) {
e.printStackTrace();
}
I looked at google, but didn't found any answer. So whats wrong? It's possible to generate these pages in the same margins?