Click here to Skip to main content
Click here to Skip to main content

PDF Merge

, 13 Dec 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
This Windows application lets you merge image and PDF files in a given folder into one PDF file.

PDF_Merge/Merge_Pdf.jpg

Introduction

This complete Windows application lets you merge image and PDF files in a given folder into one PDF file. It also lets you password protect the PDF file. It uses free iTextSharp library.

Using the code

To use this program, simply select a folder and click Process. The program will create a PDF file within each folder and subfolder. The file will have the same name as the folder plus the PDF extension.

Here is the code:



	Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
			cbFileType.SelectedIndex = 0
	End Sub

	Private Sub btnFrom_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnFrom.Click
			fldFrom.ShowDialog()
			txtFrom.Text = fldFrom.SelectedPath
	End Sub

	Private Sub btnProcess_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcess.Click

	btnProcess.Enabled = False

			Dim sFromPath As String = txtFrom.Text
			If Not Directory.Exists(sFromPath) Then
					MsgBox("Folder does not exist")
					Exit Sub
			End If

			txtOutput.Text = ""
			txtOutput.Text += "Starting..." & vbCrLf
			ProccessFolder(sFromPath)
	txtOutput.Text += "Done!"

	btnProcess.Enabled = True

	End Sub

Private Function PadExt(ByVal s As String) As String
	s = UCase(s)
	If s.Length > 3 Then
		s = s.Substring(1, 3)
	End If
	Return s
End Function

	Function GetPageCount(ByVal sFolderPath As String) As Integer
			Dim iRet As Integer = 0
			Dim oFiles As String() = Directory.GetFiles(sFolderPath)

			For i As Integer = 0 To oFiles.Length - 1
					Dim sFromFilePath As String = oFiles(i)
					Dim oFileInfo As New FileInfo(sFromFilePath)
					Dim sFileType As String = cbFileType.SelectedItem
		Dim sExt As String = PadExt(oFileInfo.Extension)

					Select Case sFileType
							Case "All"
									If sExt = "PDF" Then
											iRet += 1
									ElseIf sExt = "JPG" Or sExt = "TIF" Then
											iRet += 1
									End If

							Case "PDF"
									If sExt = "PDF" Then
											iRet += 1
									End If

							Case "JPG", "TIF"
									If sExt = "JPG" Or sExt = "TIF" Then
											iRet += 1
									End If
					End Select
			Next

			Return iRet
	End Function

	Sub ProccessFolder(ByVal sFolderPath As String)

			Dim bOutputfileAlreadyExists As Boolean = False
			Dim oFolderInfo As New System.IO.DirectoryInfo(sFolderPath)
	Dim sOutFilePath As String = sFolderPath & "\" & oFolderInfo.Name & ".pdf"

	If chkCreateInParentFolder.Checked Then
		sOutFilePath = oFolderInfo.Parent.FullName & "\" & oFolderInfo.Name & ".pdf"
	End If

	If IO.File.Exists(sOutFilePath) Then
		Try
			IO.File.Delete(sOutFilePath)
		Catch ex As Exception
			txtOutput.Text += "Output file already exists: " & sOutFilePath & _
							 " and could not be deleted." & vbTab & vbCrLf
			bOutputfileAlreadyExists = True
		End Try
	End If

			Dim iPageCount As Integer = GetPageCount(sFolderPath)
			If iPageCount > 0 And bOutputfileAlreadyExists = False Then
					txtOutput.Text += "Processing folder: " & sFolderPath & " - " & iPageCount & " files." & vbCrLf

					Dim oFiles As String() = Directory.GetFiles(sFolderPath)
					ProgressBar1.Maximum = oFiles.Length

					Dim oPdfDoc As New iTextSharp.text.Document()
					Dim oPdfWriter As PdfWriter = PdfWriter.GetInstance(oPdfDoc, New FileStream(sOutFilePath, FileMode.Create))
					If txtPassword.Text <> "" Then
							oPdfWriter.SetEncryption(PdfWriter.STRENGTH40BITS, txtPassword.Text, txtPassword.Text, PdfWriter.AllowCopy)
					End If
					oPdfDoc.Open()

		System.Array.Sort(Of String)(oFiles)

					For i As Integer = 0 To oFiles.Length - 1
							Dim sFromFilePath As String = oFiles(i)
							Dim oFileInfo As New FileInfo(sFromFilePath)
							Dim sFileType As String = cbFileType.SelectedItem
			Dim sExt As String = PadExt(oFileInfo.Extension)

							Try
									Select Case sFileType
											Case "All"
													If sExt = "PDF" Then
															AddPdf(sFromFilePath, oPdfDoc, oPdfWriter)
													ElseIf sExt = "JPG" Or sExt = "TIF" Then
							AddImage(sFromFilePath, oPdfDoc, oPdfWriter, sExt)
													End If

											Case "PDF"
													If sExt = "PDF" Then
							AddPdf(sFromFilePath, oPdfDoc, oPdfWriter)
													End If

											Case "JPG", "TIF"
													If sExt = "JPG" Or sExt = "TIF" Then
							AddImage(sFromFilePath, oPdfDoc, oPdfWriter, sExt)
													End If

									End Select

							Catch ex As Exception
									txtOutput.Text += sFromFilePath & vbTab & ex.Message & vbCrLf
							End Try

			If chkDeleteSourceFiles.Checked Then
				Try
					IO.File.Delete(sFromFilePath)
				Catch ex As Exception
					txtOutput.Text += "Could not delete " & sFromFilePath & _
					 ", " & ex.Message & vbCrLf
				End Try
			End If

							ProgressBar1.Value = i
					Next

					Try
							oPdfDoc.Close()
							oPdfWriter.Close()
					Catch ex As Exception
							txtOutput.Text += ex.Message & vbCrLf
							Try
									IO.File.Delete(sOutFilePath)
							Catch ex2 As Exception
							End Try
					End Try

					ProgressBar1.Value = 0
			End If

	Dim oFolders As String() = Directory.GetDirectories(sFolderPath)
			For i As Integer = 0 To oFolders.Length - 1
					Dim sChildFolder As String = oFolders(i)
					Dim iPos As Integer = sChildFolder.LastIndexOf("\")
					Dim sFolderName As String = sChildFolder.Substring(iPos + 1)
					ProccessFolder(sChildFolder)
			Next

	End Sub

Sub AddPdf(ByVal sInFilePath As String, ByRef oPdfDoc As iTextSharp.text.Document, ByRef oPdfWriter As PdfWriter)

	Dim oDirectContent As iTextSharp.text.pdf.PdfContentByte = oPdfWriter.DirectContent
	Dim oPdfReader As iTextSharp.text.pdf.PdfReader = New iTextSharp.text.pdf.PdfReader(sInFilePath)
	Dim iNumberOfPages As Integer = oPdfReader.NumberOfPages
	Dim iPage As Integer = 0

	Do While (iPage < iNumberOfPages)
		iPage += 1
		oPdfDoc.SetPageSize(oPdfReader.GetPageSizeWithRotation(iPage))
		oPdfDoc.NewPage()

		Dim oPdfImportedPage As iTextSharp.text.pdf.PdfImportedPage = oPdfWriter.GetImportedPage(oPdfReader, iPage)
		Dim iRotation As Integer = oPdfReader.GetPageRotation(iPage)
		If (iRotation = 90) Or (iRotation = 270) Then
			oDirectContent.AddTemplate(oPdfImportedPage, 0, -1.0F, 1.0F, 0, 0, oPdfReader.GetPageSizeWithRotation(iPage).Height)
		Else
			oDirectContent.AddTemplate(oPdfImportedPage, 1.0F, 0, 0, 1.0F, 0, 0)
		End If
	Loop

End Sub

Sub AddImage(ByVal sInFilePath As String, ByRef oPdfDoc As iTextSharp.text.Document, ByRef oPdfWriter As PdfWriter, ByVal sExt As String)

	If chkResize.Checked = False Then
		Dim oDirectContent As iTextSharp.text.pdf.PdfContentByte = oPdfWriter.DirectContent
		Dim oPdfImage As iTextSharp.text.Image
		oPdfImage = iTextSharp.text.Image.GetInstance(sInFilePath)
		oPdfImage.SetAbsolutePosition(1, 1)
		oPdfDoc.SetPageSize(New iTextSharp.text.Rectangle(oPdfImage.Width, oPdfImage.Height))
		oPdfDoc.NewPage()
		oDirectContent.AddImage(oPdfImage)
		Exit Sub
	End If

	Dim oImage As System.Drawing.Image = System.Drawing.Image.FromFile(sInFilePath)

	'Multi-Page Tiff
	If sExt = "TIF" Then
		Dim iPageCount As Integer = oImage.GetFrameCount(Imaging.FrameDimension.Page)
		If iPageCount > 1 Then
			For iPage As Integer = 0 To iPageCount - 1
				oImage.SelectActiveFrame(Imaging.FrameDimension.Page, iPage)
				Dim oMemoryStream As New IO.MemoryStream()
				oImage.Save(oMemoryStream, System.Drawing.Imaging.ImageFormat.Png)
				Dim oImage2 As System.Drawing.Image = System.Drawing.Image.FromStream(oMemoryStream)
				AddImage2(oImage2, oPdfDoc, oPdfWriter)
				oMemoryStream.Close()
			Next
			Exit Sub
		End If
	End If

	AddImage2(oImage, oPdfDoc, oPdfWriter)
End Sub


Sub AddImage2(ByRef oImage As System.Drawing.Image, ByRef oPdfDoc As iTextSharp.text.Document, ByRef oPdfWriter As PdfWriter)

	Dim oDirectContent As iTextSharp.text.pdf.PdfContentByte = oPdfWriter.DirectContent
	Dim oPdfImage As iTextSharp.text.Image
	Dim iWidth As Single = oImage.Width
	Dim iHeight As Single = oImage.Height
	Dim iAspectRatio As Double = iWidth / iHeight

	Dim iWidthPage As Single = iTextSharp.text.PageSize.LETTER.Width
	Dim iHeightPage As Single = iTextSharp.text.PageSize.LETTER.Height
	Dim iPageAspectRatio As Double = iWidthPage / iHeightPage

	Dim iWidthGoal As Single = 0
	Dim iHeightGoal As Single = 0
	Dim bFitsWithin As Boolean = False

	If iWidth < iWidthPage And iHeight < iHeightPage Then
		'Image fits within the page
		bFitsWithin = True
		iWidthGoal = iWidth
		iHeightGoal = iHeight

	ElseIf iAspectRatio > iPageAspectRatio Then
		'Width is too big
		iWidthGoal = iWidthPage
		iHeightGoal = iWidthPage * (iHeight / iWidth)

	Else
		'Height is too big
		iWidthGoal = iHeightPage * (iWidth / iHeight)
		iHeightGoal = iHeightPage
	End If

	If bFitsWithin = False Then
		oImage = FixedSize(oImage, iWidthGoal, iHeightGoal)
	End If

	oPdfImage = iTextSharp.text.Image.GetInstance(oImage, System.Drawing.Imaging.ImageFormat.Png)
	oPdfImage.SetAbsolutePosition(1, 1)
	oPdfDoc.SetPageSize(iTextSharp.text.PageSize.LETTER)

	oPdfDoc.NewPage()
	oPdfImage.ScaleAbsolute(iWidthGoal, iHeightGoal)
	oDirectContent.AddImage(oPdfImage)
End Sub

Private Shared Function FixedSize(ByVal imgPhoto As System.Drawing.Image, _
			ByVal Width As Integer, ByVal Height As Integer) As System.Drawing.Image

	Dim sourceWidth As Integer = imgPhoto.Width
	Dim sourceHeight As Integer = imgPhoto.Height
	Dim sourceX As Integer = 0
	Dim sourceY As Integer = 0
	Dim destX As Integer = 0
	Dim destY As Integer = 0

	Dim nPercent As Single = 0
	Dim nPercentW As Single = 0
	Dim nPercentH As Single = 0

	nPercentW = (CSng(Width) / CSng(sourceWidth))
	nPercentH = (CSng(Height) / CSng(sourceHeight))

	If nPercentH < nPercentW Then
		nPercent = nPercentH
		destX = CInt(((Width - (sourceWidth * nPercent)) / 2))
	Else
		nPercent = nPercentW
		destY = CInt(((Height - (sourceHeight * nPercent)) / 2))
	End If

	Dim destWidth As Integer = CInt((sourceWidth * nPercent))
	Dim destHeight As Integer = CInt((sourceHeight * nPercent))

	Dim bmPhoto As New Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb)
	bmPhoto.SetResolution(imgPhoto.HorizontalResolution, imgPhoto.VerticalResolution)

	Dim grPhoto As Graphics = Graphics.FromImage(bmPhoto)
	grPhoto.Clear(Color.White)
	grPhoto.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic

	grPhoto.DrawImage(imgPhoto, New Rectangle(destX, destY, destWidth, destHeight), _
			New Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), GraphicsUnit.Pixel)

	grPhoto.Dispose()
	Return bmPhoto
End Function

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Igor Krupitsky
Web Developer
United States United States
Igor is a business intelligence consultant working in Tampa, Florida. He has a BS in Finance from University of South Carolina and Masters in Information Management System from University of South Florida. He also has following professional certifications: MCSD, MCDBA, MCAD.

Comments and Discussions

 
SuggestionSuper!!! PinmemberMember 105113768-Jan-14 4:48 
QuestionMy vote 5 Pinmemberleoncio_774-Jul-13 15:46 
Questionunable to open oPdfDoc PinmemberMember 1001129224-Apr-13 14:45 
QuestionNice 5/5 Pinmembernoelse4-Apr-13 4:52 
I was trying to use PDFbox, but was getting weird Null Reference errors that were coming from outside of my code.
 
THis is not only faster, smaller, cleaner, I also am not getting weird errors.
 
Great piece of code to learn from!
QuestionThanks but the merged pdf file doesn't retain the text box fields Pinmemberalex Ding7-Jan-13 8:41 
GeneralMy vote of 5 Pinmemberalex Ding5-Jan-13 18:31 
GeneralMy vote of 5 PinmemberLasse Oscarsson7-Oct-12 2:35 
Question5 with remark Pinmemberbugene25-Jul-11 1:29 
GeneralMy vote of 5 PinmemberChillerPerser29-May-11 23:08 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.141022.2 | Last Updated 14 Dec 2013
Article Copyright 2010 by Igor Krupitsky
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid