Attribute VB_Name = "basPrintPDF"
'*******************************************************************************
' Project   : Generic
'
' Module    : basPrintPDF
' DateTime  : 12/3/2007 09:20
' Author    : Alex Dybenko <Alex@Dybenko.com>
' Purpose   : Print PDF files by passing File path
' References: API calls
' Index     :(Updated on 12/3/2007)
'*******************************************************************************

Option Compare Database
Option Explicit

Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _
(ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Public Function PrintPDF(FileName As Variant) As Boolean
'Purpose  : Main function to print PDF File.
'           If you get an error stating the command cannot be executed
'           add more time to the Sleep calls. 1 second = 1000
'DateTime : 12/3/2007 09:21
'Author   : Alex Dybenko
'Reference:


    Dim Error282Count As Integer    '' Count of "Can't open DDE channel" errors
    Dim AcroDDEFailed As Boolean    '' Set to true if a DDE connection cannot be established
    Dim strCmd As String            '' DDE command
    Dim lStatus As Long             '' response from ShellExecute command
    Const Max282Errors = 6          '' Number of times we will ignore "Can't open DDE channel" errors
    Dim lngChanel As Long
                                    '' before accepting the fact that Acrobat is not started. We need
                                    '' to test more than once, because it might just be busy loading
    Static strAcroPath As String    '' Path to acrobat, determined by FindExecutable
    Dim bCloseAcrobat As Boolean    '' If we open acrobat, we will close it when we are done

    On Error GoTo ErrHandler
    '' If acrobat is already running (and hidden), shelling it will cause it to be shown.
    '' We do not want that. So try a DDE connect, which will fail if acrobat is not running
    '' I have looked at other API means of testing this, but it may be running as a process (no window)
    '' and there does not seem to be many graceful ways of testing for this.

    Error282Count = Max282Errors    '' we only need to try once to see if it is already running.
    AcroDDEFailed = False             '' ErrHandler will set to true if Acro is not running

    lngChanel = DDEInitiate("acroview", "control")

    If AcroDDEFailed = True Then

        '' Use the FindExecutable API function to grab the path to our PDF handler.
        '' This should be Acrobat Reader or Acrobat, but it might be something else.
        '' When we try to DDE link to it, non-acrobat will error out. This is ok.
        If Len(strAcroPath) = 0 Then
            strAcroPath = String(128, 32)
            lStatus = FindExecutable(FileName, vbNullString, strAcroPath)
            If lStatus <= 32 Then
                MsgBox "Acrobat could not be found on this computer. Printing cancelled", vbCritical, "Problem"
                Exit Function
            End If
        End If
        '' Launch the PDF handler
        lStatus = Shell(strAcroPath, vbHide)
        If (lStatus >= 0) And (lStatus <= 32) Then
            MsgBox "An error occured launching Acrobat. Printing cancelled", _
                    vbCritical, "Problem"
            Exit Function
        End If
        bCloseAcrobat = True  '' We will try to close Acrobat when we are done
    End If
    Sleep 2000              '' Lets take a break here to let Acrobat finish loading
    Error282Count = 0       '' This time, we will allow all acceptable tries, as
    AcroDDEFailed = False   '' Acrobat is running, but may be busy loading its Modules
    lngChanel = DDEInitiate("acroview", "control")
    If AcroDDEFailed = True Then
        MsgBox "An error occured connecting to Acrobat. Printing cancelled", _
                vbCritical, "Problem"
        Exit Function
    End If
    strCmd = "[FilePrintSilent(" & Chr(34) & FileName & Chr(34) & ")]"
    DDEExecute lngChanel, strCmd

    PrintPDF = True
    If bCloseAcrobat = True Then
        If InStr(strAcroPath, "6.0") = 0 Then
            strCmd = "[AppExit()]"
            DDEExecute lngChanel, strCmd
        End If
    End If

exit_PrintPDF:
    On Error Resume Next
    DDETerminateAll
    Exit Function

ErrHandler:
    If Err.Number = 282 Then    '' Can't open DDE channel
        '' This error may happen because Acro is not fully loaded.
        '' Give it Max282Errors attempts before returning AcroDDEFailed = True
        Error282Count = Error282Count + 1
        If Error282Count <= Max282Errors Then
            Sleep 3000
            Resume
        Else
            AcroDDEFailed = True
            Resume Next
        End If
    End If

    MsgBox "Error in PrintPDF sub Error# " & Err.Number & " " & Err.Description & "."

End Function


'Private Sub PauseFor(iSeconds As Integer)
''' Pauses for iSecond seconds
'  Dim sngTimer As Single
'
'  sngTimer = Timer
'  While Timer - sngTimer < iSeconds
'    DoEvents
'  Wend
'
'End Sub
'
'
