Reporting Services, la piattaforma di presentazione delle informazioni di SQL Server, consente, tra i vari formati disponibili, di estrarre report in formato PDF.

In scenari in cui vengono sviluppati molti report, può nascere (e spesso nasce) la necessità di poter avere in un singolo PDF l’intera collezione (o un sottoinsieme a piacere) di rappresentazioni.

Non esiste, nativamente, un modo per rispondere a questa esigenza.

E’ possibile, però, risolvere con qualche riga di codice e, ad esempio, costruire un’applicazione .Net che permetta di fare il merge di N file in un unico.

 

Supponendo di avere già a disposizione i render dei report da unire in unico file (perché, ad esempio, generati tramite le schedulazioni di Reporting), possiamo costruire una soluzione utilizzando la libreria iTextSharp.

Di seguito un esempio di applicazione console, scritta in C#, in grado di risolvere il problema:

 

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

/*
 * http://sourceforge.net/projects/itextsharp/
 * iTextSharp is a C# port of iText, and open source Java library for PDF generation and manipulation
 */

using iTextSharp.text;
using iTextSharp.text.pdf;

public class MergePdf
{
    private string _destinationfile;
    private readonly IList _fileList = new ArrayList();

    public MergePdf(IList fileList)
    {
        if (fileList == null) throw new ArgumentNullException("fileList");
        this._fileList = fileList;
    }

    public void AddFile(string pathnname)
    {
        _fileList.Add(pathnname);
    }

    public void Execute()
    {
        var document = new Document();
        try
        {
            var writer = PdfWriter.GetInstance(document, new FileStream(_destinationfile, FileMode.Create));

            document.Open();

            var directContent = writer.DirectContent;

            foreach (string filename in _fileList)
            {
                var reader = new PdfReader(filename);
                var numberOfPages = reader.NumberOfPages;

                var i = 0;
                while (i < numberOfPages)
                {
                    i++;
                    document.SetPageSize(reader.GetPageSizeWithRotation(1));
                    document.NewPage();

                    if (i == 1)
                    {
                        var chunk = new Chunk(" ");
                        chunk.SetLocalDestination(filename);
                        document.Add(chunk);
                    }

                    var page = writer.GetImportedPage(reader, i);
                    var rotation = reader.GetPageRotation(i);
                    if (rotation == 90 || rotation == 270)
                    {
                        directContent.AddTemplate(page, 0, -1f, 1f, 0, 0, reader.GetPageSizeWithRotation(i).Height);
                    }
                    else
                    {
                        directContent.AddTemplate(page, 1f, 0, 0, 1f, 0, 0);
                    }
                }
            }
        }
        catch (Exception e) { throw e; }
        finally { document.Close(); }
    }

    public string DestinationFile
    {
        get { return _destinationfile; }
        set { _destinationfile = value; }
    }
}

namespace MCSMergePDF
{
    class Program
    {
        static void Main()
        {
            var pdf = new MergePdf(RetrieveFileList()) { DestinationFile = RetrieveDestinationFile() };
            pdf.Execute();
        }

        /* Method to retrieve the files to merge */
        private static IList RetrieveFileList()
        {
            IList fileList = new ArrayList();
            fileList.Add(@"c:\test\1.pdf");
            fileList.Add(@"c:\test\2.pdf");
            fileList.Add(@"c:\test\3.pdf");
            fileList.Add(@"c:\test\4.pdf");

            return fileList;
        }

        /* Method to retrieve the file to create */
        private static string RetrieveDestinationFile()
        {
            return @"c:\test\merge.pdf";
        }
    }
}

Questo il risultato:

image