|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
In order to convert a file to PDF with the demo software, you should either have one of the freeware PDF printers or Adobe Acrobat. If you don't have any of them, the file will be sent to your default printer. IntroductionNowadays, PDF is the standard file format used in many reporting tools. The application that I developed with VB.NET for my job needed to convert a lot of Microsoft Project and Excel files to PDF files, and place them to custom specified directories without any user interaction. Almost everybody at the office has some free PDF printer instead of Adobe Acrobat - either PDF995 or FreePDF. They are both very nice converters, but my problem was they always pop (naturally) the Save As dialog. I read the documentation of both printers, searched a while on the Internet, and actually found a lot of examples for how to automate the printing, but none of them in VB.NET. So, I thought, VB.NET is (already) a nice OOP language, why not use it to make a simple-to-use class for easily converting files into PDF. BackgroundIf you have Adobe Acrobat, you will also have a PDF printer. Acrobat has also provided, in the Acrobat SDK, very handy and easy to understand examples for how to silently convert any file to PDF with VB.NET. In their examples, they also show how to find the default application for every known file extension. For this example, this is not needed, because most of the file extensions in Windows have already an associated application, so all we need is to start a process with the verb
and also:
More detailed information about verbs and file associations can be found here. Using the CodeNow that we know what a verb is, we will use it to print our file. One possibility to print an existing file is to start a process, giving the file name and the verb “ Before starting to explain the details about PDF995 and FreePDF XP, we will discuss, in short, the start of a process. The .NET Framework has the 'Define properties for the print process
Dim procStartInfo As ProcessStartInfo = Nothing
procStartInfo = New ProcessStartInfo
procStartInfo.FileName = "c:\file.xls" ' e.g. an excel file
procStartInfo.Verb = "Print" ' print please
'Make process invisible
procStartInfo.CreateNoWindow = True
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden
'start print process for the file with/from the associated application
Dim procPrint As Process = Process.Start(procStartInfo)
If Not procPrint Is Nothing Then
procPrint.WaitForExit()
End If
More information about the The PDF995 printer uses an INI file to store its settings. The INI file resides in the res subdirectory of the printer's installation path. Further read of the developer's FAQ says, that in order to bypass the “Save As” dialog and to place the PDF file to a custom directory, all we need to do is override the following INI file options:
The FreePDF XP printer, on the other hand, uses the Windows registry to store its settings, and also, first converts the file to a PostScript, and then the PS file to a PDF file. To put the PDF file into the user specified directory, we need to temporarily set the
Summarizing the actions we need to undertake gives us the following: PDF995 stores its settings in an INI file, so we need to:
FreePDF XP stores its settings in the registry (full path: HKEY_LOCAL_MACHINE\SOFTWARE\shbox\FreePdfXP) and uses a PS intermediate file, so we need to:
Now we know how to design our base printer class. We need, by all means, a function to save the original printer settings, a function to restore the original printer settings, a variable to keep the full path of the desired file to print, and a Imports System.IO
'we want an abstract base class
Public MustInherit Class CPrinter
Protected _strFileToPrint As String = ""
'save original settings
Protected MustOverride Sub pushSettings()
'restore original settings
Protected MustOverride Sub popSettings()
'start printing process (adopted from Adobe PDF SDK examples)
Public Overridable Sub PrintFile()
'Define properties for the print process
Dim procStartInfo As ProcessStartInfo = Nothing
If System.IO.File.Exists(_strFileToPrint) Then
procStartInfo = New ProcessStartInfo
procStartInfo.FileName = _strFileToPrint
procStartInfo.Verb = "Print"
'Make process invisible
procStartInfo.CreateNoWindow = True
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden
'start print process for the file with/from the associated application
Dim procPrint As Process = Process.Start(procStartInfo)
'give the system some time
System.Threading.Thread.Sleep(2500)
If Not procPrint Is Nothing Then
procPrint.WaitForExit()
End If
End If
End Sub
End Class
Now that we have an The PDF995 Printer ClassImports Microsoft.Win32
Imports System.IO
Public Class CPrinterPDF995 : Inherits CPrinter
'the INI that we want to change in oder to "silently" use the PDF printer
Private Const strOriginalIniFile As String = "pdf995.ini"
'we want to recover the original INI file after every print
Private Const strOriginalIniSave As String = "pdf995.ini_ORIGINAL"
'used to locate PDF995 installation directory
Private Const strRegPath As String = _
"Software\Microsoft\Windows\CurrentVersion\Uninstall\Pdf995"
Protected Overrides Sub pushSettings()
Dim strIniPath As String = RetrieveIniPath()
'save original INI file first
FileSystem.Rename(strIniPath + strOriginalIniFile, _
strIniPath + strOriginalIniSave)
Me.createCustomIni()
End Sub
Protected Overrides Sub popSettings()
Dim strIniPath As String = RetrieveIniPath()
'restore original INI file
File.Delete(strIniPath + strOriginalIniFile)
FileSystem.Rename(strIniPath + strOriginalIniSave, _
strIniPath + strOriginalIniFile)
End Sub
Private Sub createIni()
Dim strFileToPrint As String = MyBase.strFileToPrint
Dim strIniPath As String = RetrieveIniPath()
Dim fi As System.IO.FileInfo = New System.IO.FileInfo(strFileToPrint)
Dim strPDFOutputDirectory As String = fi.DirectoryName + "\"
Dim oWriter As StreamWriter = Nothing
fi = Nothing
'write INI file, create PDF from "strFileToPrint" and save it to "directory"
oWriter = New StreamWriter(strIniPath + "pdf995.ini", False, _
System.Text.Encoding.Unicode)
oWriter.WriteLine("[Parameters]")
oWriter.WriteLine("Install = 0")
oWriter.WriteLine("Quiet = 1")
oWriter.WriteLine("AutoLaunch = 0")
oWriter.WriteLine("Document Name = " + strFileToPrint)
oWriter.WriteLine("User File = " + strFileToPrint + ".pdf")
oWriter.WriteLine("Output File = " + strFileToPrint + ".pdf")
oWriter.WriteLine("Initial Dir = " + strPDFOutputDirectory)
oWriter.WriteLine("Use GPL Ghostcript = 1")
oWriter.Close()
oWriter = Nothing
System.Threading.Thread.Sleep(1000) ' give Pdf995 some time
End Sub
Public Overrides Sub printFile()
Me.pushSettings()
MyBase.PrintFile()
Me.popSettings()
End Sub
End Class
The FreePDF Printer ClassImports Microsoft.Win32
Imports System.IO
Public Class CPrinterXFreePDF : Inherits CPrinter
'freepdf.exe full path
Private strFreePDFExe As String = ""
'PS temp directory, needed for silent ps to pdf creation
Private strPSTempDir As String = ""
'FreePDF path in registry
Private Const strRegPath As String = "SOFTWARE\shbox\FreePdfXP"
Public Overrides Sub printFile()
Dim fi As System.IO.FileInfo = New System.IO.FileInfo(fileToPrint)
Dim strFileToPrintDir As String = fi.DirectoryName + "\"
fi = Nothing
Me.pushSettings()
Dim strCmd As String = strFreePDFExe + " /3 delps,end ""eBook"" """ + _
fileToPrint + ".pdf"" """ + _
strFileToPrintDir + Environment.UserName + _
"000001.ps"""
'create the PS file
MyBase.PrintFile()
'create PDF from PS file, can also be started with System.Diagnostics.Process
Shell(strCmd, AppWinStyle.Hide, True)
Me.popSettings()
End Sub
Protected Overrides Sub pushSettings()
Dim regKey As RegistryKey = Nothing
Dim fi As System.IO.FileInfo = New System.IO.FileInfo(MyBase.strFileToPrint)
Dim strPSPath As String = fi.DirectoryName + "\"
fi = Nothing
regKey = Registry.LocalMachine.OpenSubKey(strRegPath, True)
'fpDir = freepdf.exe directory
strFreePDFExe = regKey.GetValue("fpDir") + "freepdf.exe"
'psDir = location for temp PS files, save it
strPSTempDir = regKey.GetValue("psDir")
'set currently new PS files location
If Not String.IsNullOrEmpty(strPSPath) Then
regKey.SetValue("psDir", strPSPath)
End If
regKey.Close()
regKey = Nothing
End Sub
Protected Overrides Sub popSettings()
Dim regKey As RegistryKey = Nothing
regKey = Registry.LocalMachine.OpenSubKey(strRegPath, True)
'restore original psDir
regKey.SetValue("psDir", strPSTempDir)
regKey.Close()
regKey = Nothing
End Sub
You can always instantiate an object from one of the classes and convert a file like this: Dim oPrinter As CPrinterPDF995 = New CPrinterPDF995
oPrinter.fileToPrint = "c:\temp\report.xls"
oPrinter.printFile()
oPrinter = Nothing
I hope the commented code is self-explanatory and will help you save some time at home or at work. If you have any trouble understanding it, ask, and I'll be glad if I can help. Also, do not forget to set the desired printer as the default printer system-wide, from the Control Panel or from within the code.
Happy converting! :-) History
|
||||||||||||||||||||||