-1

I need to generate 5 Crystal reports and combine them in one PDF file. Originally I wanted to create one report with these 5 reports as subreports then output it to PDF. This won't work, however, because each of these reports already has subreports, and reports within subreports are not supported.

I guess I need to output each report to PDF behind the scenes then use something like iTextSharp to combine these reports. I've found a few examples, but none of them is really applicable to my situation. I would appreciate any code example for this task.

Thank you.

Peter
  • 121
  • 1
  • 12

3 Answers3

0

I would use PDFSam free version if you are going to manually combine them to one PDF.

But, if you want to do it with Crystal Reports, why not use sub reports and have them all combine into one that way?

https://youtu.be/xxwWFAtGSIM?t=1m06s

8CT8
  • 11
  • 1
  • Thank you. I've mentioned in my post that each of my reports already has sub reports, Crystal reports do not support sub report within sub report. – Peter Oct 25 '16 at 22:34
0

You can write your own application to export both reports to PDF and then use one of the open source projects to combine them into 1 pdf. For example this one: https://sourceforge.net/projects/pdfmerge/

You can also get one of the existing applications that can do this for you. This one is free http://www.r-tag.com/Pages/CommunityEdition.aspx

Lan
  • 1,335
  • 1
  • 9
  • 14
0

working sample [ c# , using vs 2015 cm]- [as per your point ..... no more files .in server]

1) crystalreports added to sample-project named as "CrystalReport1.rpt , CrystalReport2.rpt" [ simple design]

2) Required Files : ( merging streams) itext lib : https://www.nuget.org/packages/iTextSharp ( command :: Install-Package iTextSharp -Version 5.5.11)

3) Required Namespace

using System;
using System.IO;
using System.Collections.Generic;

using CrystalDecisions.CrystalReports.Engine;
using CrystalDecisions.Shared;

using iTextSharp.text;
using iTextSharp.text.pdf;
Step  1:  Reference code 

        //reploace this event to your related event .......
        protected void Page_Load(object sender, EventArgs e)
        {
            //hold the more than one report outputs [bytes]
            List<byte[]> files = new List<byte[]>();

            //for testing purpose LOOP used,
            //u can change as per your requirement and your report name
            for (int i = 1; i <= 2; i++) {

                ReportDocument crdReport1 = new ReportDocument();

                //put your related report names.....
                crdReport1.Load(Server.MapPath(string.Format("CrystalReport{0}.rpt", i)));

                Stream stream1 = crdReport1.ExportToStream(ExportFormatType.PortableDocFormat);

                //prepare the "bytes" from "stream"               
                files.Add(PrepareBytes(stream1));
                //finally the result added to LIST
            }

            Response.Clear();
            Response.Buffer = true;
            Response.ContentType = "application/pdf";     

            //merge the all reports & show the reports            
            Response.BinaryWrite(MergeReports(files).ToArray());

            Response.End();        
        }

Step 2: Reference code (credits :: https://stackoverflow.com/a/221941 )

//prepare the report bytes

 private byte[] PrepareBytes(Stream stream)
    {          
        using (MemoryStream ms = new MemoryStream())
        {
            byte[] buffer = new byte[stream.Length];
            int read;
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
            {
                ms.Write(buffer, 0, read);
            }
           return ms.ToArray();
        }           
    }

Step 3: Reference code ( credits :: https://stackoverflow.com/a/6780582 )

//Merge the reports

private MemoryStream MergeReports(List<byte[]> files)
    {
        if (files.Count > 1)
        {
            PdfReader pdfFile;
            Document doc;
            PdfWriter pCopy;
            MemoryStream msOutput = new MemoryStream();

            pdfFile = new PdfReader(files[0]);

            doc = new Document();
            pCopy = new PdfSmartCopy(doc, msOutput);

            doc.Open();

            for (int k = 0; k < files.Count; k++)
            {
                pdfFile = new PdfReader(files[k]);
                for (int i = 1; i < pdfFile.NumberOfPages + 1; i++)
                {
                    ((PdfSmartCopy)pCopy).AddPage(pCopy.GetImportedPage(pdfFile, i));
                }
                pCopy.FreeReader(pdfFile);
            }

            pdfFile.Close();
            pCopy.Close();
            doc.Close();

            return msOutput;
        }
        else if (files.Count == 1)
        {
            return new MemoryStream(files[0]);
        }

        return null;
    }

so, you can change the logic in step : 1 ( as per you reports )

ravi polara
  • 564
  • 3
  • 14