Friday, May 3, 2013

Merge Landscape and Portrait PDFs using ASP.NET

There are situations in every business where it would be nice to have a PDF that is a combination of Portrait and Landscape printing preferences. One of the key business areas, "Billing," is always attempting to achieve this. This article shows how to create PDFs in the different printing preferences of Landscape and Portrait using the Crystal Report "Export to PDF" function, merging them into one single PDF in ASP.NET. A 3rd party COM component called CutePDF was licensed to merge the PDFs to one final report.



The billing department had a history of creating these bills as printed bills and mailing them to the customers. An idea was tossed around to make these bills available online, but the business users and sponsors insisted that online bills match z to z to the printed bill. Needless to say, an excessive amount of time was spent to achieve this using Crystal Report. To add to the horror, the first page of the printed bill was printed in Portrait and the rest of the pages in Landscape. The research started immediately and the deadline was near, like always, in the IT department.

The first step is to create Crystal reports. First, make the page or the pages in Portrait as one report. Make the other page or pages in Landscape as another report. We are not going to show how to create Crystal reports in this article. I'll work on another article soon. The code block below shows how to programmatically export the data to PDF in portrait settings.

I am showing with an example in vb.net, if you want to work in c#.net then please convert the code to c# using this site: http://www.developerfusion.com/tools/convert/vb-to-csharp/


Dim CrReport As ReportDocument

' Report Name to set the printing options 
Dim CrPrintOptions As PrintOptions

'set the export options of the report

Dim CrExportOptions As ExportOptions

Dim CrFormatTypeOptions As New PdfRtfWordFormatOptions()

'define the folder to save the reports 
Dim CrDiskFileDestinationOptions As DiskFileDestinationOptions

' Localise the filepath and load the report 
Dim sPDFName As String = CStr(Now().Millisecond())

Dim sPath As String = "C:\report\" 
'first page of the report 
Dim sPDFFile1 As String = sPath + sPDFName + "_a.pdf"

'Other Pages report 
Dim sPDFFile2 As String = sPath + sPDFName + "_b.pdf"

'the final report name 
Dim sPDFFinal As String =   sPath  + sPDFName + ".pdf"< BR   >       
CrReport = New ReportDocument() 
'load the report 
CrReport.Load(reportPath)

CrDiskFileDestinationOptions = New DiskFileDestinationOptions()

'first page report file name is set 
CrDiskFileDestinationOptions.DiskFileName = sPDFFile1

' Specify a page range (optional) 
CrFormatTypeOptions.FirstPageNumber = 1

' Start Page in the Report 
CrFormatTypeOptions.LastPageNumber = 1

' End Page in the Report 
CrFormatTypeOptions.UsePageRange = True

' Set export options 
CrExportOptions = CrReport.ExportOptions

With CrExportOptions 
    ' Set the destination to a disk file 
    .ExportDestinationType = ExportDestinationType.DiskFile

    ' Set the format to PDF 
    .ExportFormatType = ExportFormatType.PortableDocFormat

    ' Set the destination options to DiskFileDestinationOptions object 
    .DestinationOptions = CrDiskFileDestinationOptions

    .FormatOptions = CrFormatTypeOptions 
End With

'load the dataset 
Dim dsHeader As DataSet
CrReport.SetDataSource(dsHeader)

CrPrintOptions = CrReport.PrintOptions 
'set the paper orientation to portrait for the first page 
With CrPrintOptions 
    .PaperOrientation = PaperOrientation.Portrait 
End With

' Export the report 
       
CrReport.Export()


This code block shows how to programmatically export the data to PDF in Landscape.
With CrPrintOptions 
    'for multi page reports set the page orientation landscape from 3rd page 
    .PaperOrientation = PaperOrientation.Landscape 
    CrFormatTypeOptions.FirstPageNumber = 3 
End With

'set the report name for the 2nd pdf file 
CrDiskFileDestinationOptions.DiskFileName = sPDFFile2

'set maximum page number for lastPageNumber property because 
'it's unknown at the design time 
CrFormatTypeOptions.LastPageNumber = 2000

' End Page in the Report 
CrFormatTypeOptions.UsePageRange = True 

CrReport.Export()
CrReport.Dispose()
Here we show how to merge PDFs into a final report. We use a 3rd party COM component to achieve this, but there are free open source ones to accomplish this as well.


Dim ocutePDF As CutePDFDocument 
'create a new instance of CutePDFDocument 
ocutePDF = New CutePDFDocument

If System.IO.File.Exists(sPDFFile1) Then 
    'merge the files to one final report 
    ocutePDF.mergePDF(sPDFFile1, sPDFFile2, sFinalReport) 
End If


Finally, we show how to display the final PDF in a browser.
Dim client As System.IO.FileStream 
Dim objFile As System.IO.FileInfo = New System.IO.FileInfo(sFile)

' open the final billing report to read 
client = New System.IO.FileStream(sFile, IO.FileMode.Open)

Dim buffer As Byte() = New Byte(CInt(client.Length)) {}

'read the file into byte array 
client.Read(buffer, 0, buffer.Length) 
Response.Clear() 
Response.ClearHeaders() 
Response.ContentType = "application/octet-stream" 
Response.AppendHeader("Content-Disposition", _
    "attachment; filename=" + objFile.Name) 

Response.AppendHeader("Expires", "0") 

Response.AppendHeader("Content-Description", "File Transfer") 
Dim memStream As New IO.MemoryStream(buffer) 
memStream.WriteTo(Response.OutputStream) 
memStream.Close() 
Response.End()

Points of Interest

One more little piece we worked on was to delete the temporary PDF files after creating a final report. This saved hard disk space and made maintenance to support staff less of a headache. Believe me, you want to keep the support staff happy. Happy programming!! And don't forget to have fun.







No comments:

Post a Comment