How to catch silent failure of wdDialogFileSaveAs if file is locked?

803 Views Asked by At

I created a dialog with three buttons, where the third should save a Word document (Office Pro Plus 2013, BTW) as a PDF file.

Private Sub Button_Dokument_mit_Grafik_als_PDF_speichern_Click()
    Dim Grafik As Boolean
    Grafik = Options.PrintDrawingObjects
    Options.PrintDrawingObjects = True
    With Dialogs(wdDialogFileSaveAs)
        .Format = wdFormatPDF
        ' .Format = 17 '17 = PDF
        .Show
    End With
    Options.PrintDrawingObjects = Grafik
End Sub

If the PDF exists I can choose to overwrite it, which does work in most cases.

If the PDF to be overwritten is already open, in Adobe Reader for instance, then the file isn't saved, as it is locked. I don't get any notification that the file is locked.

How can I catch this and pop up the same message that I get when saving manually within Word?

EDIT:
To explain why my question is different to others that have been answered:
I don't need to check if the file is open in Word already. I'm saving the file as a PDF not as a Word file.
I need to check if the file is open and locked in any other application, such as Adobe Reader, Edge or whatever.

This check is done by Word (and/or the OS?) already, and THIS is the event I need to catch. I don't understand why I need to catch it at all, as the result of the check if the file does exist does come up, but the result of the check if the file is locked seems to be ignored.

The VBA code behaves as if the file has been saved, but it is not, if locked by any application other than Word.

I have no clue which code snippet exactly I would need to grab from Detect whether Excel workbook is already open

2

There are 2 best solutions below

24
CSS On BEST ANSWER

Here is what you might be looking for:

Sub SaveAsPdf()
    Dim Grafik As Boolean
    Grafik = Options.PrintDrawingObjects
    Options.PrintDrawingObjects = True

    Dim fDialog As FileDialog
    Set fDialog = Application.FileDialog(msoFileDialogSaveAs)

    fDialog.Title = "Save a file"
    'works only in Word2016 not in word 2013; 
    'fDialog.InitialFileName = "*.pdf"
    'we can use the filterindex property instead
    fDialog.FilterIndex = 7

    If fDialog.Show = -1 Then
        Dim selectedFilePath As String
        selectedFilePath = fDialog.SelectedItems(1)
        If IsFileInUse(selectedFilePath) Then
            MsgBox "The target pdf file you are trying to save is locked or used by other application." & vbCrLf & _
            "Please close the pdf file and try again.", vbExclamation
        Else
            ActiveDocument.SaveAs2 selectedFilePath, wdFormatPDF
        End If
    End If

    Options.PrintDrawingObjects = Grafik
End Sub

Private Function IsFileInUse(ByVal filePath As String) As Boolean
    On Error Resume Next
    Open filePath For Binary Access Read Lock Read As #1
    Close #1
    IsFileInUse = IIf(Err.Number > 0, True, False)
    On Error GoTo 0
End Function

If you would like to use wdDialogFileSaveAs dialog, you can try the below code:

The Display method will display the dialog box without executing the actual functionality. You can validate the result of the display to identify the button clicked and use the execute method to execute the actual functionality.

'Save As Pdf using wdDialogFileSaveAs dialog
'However, it doesn't work as expected.
'The Display method should
Sub SaveAsPdf()
    Dim dlg As Dialog
    Dim dlgResult As Long
    Set dlg = Dialogs(wdDialogFileSaveAs)
    With dlg
        .Format = wdFormatPDF
        dlgResult = .Display
        If dlgResult = -1 Then 'user clicks save button;
            If .Name <> "" Then
                If IsFileInUse(.Name) Then
                    MsgBox "The target pdf file you are trying to save is locked or used by other application." & vbCrLf & _
"Please close the pdf file and try again.", vbExclamation
                Else
                    .Execute
                End If
            End If
        End If
    End With
End Sub

Please note that, the above code (wdDialogFileSaveAs dialog) doesn't work as expected in Word 2016 at least in my local enviornment. The Display method executes the actual functionality once the save button is clicked. Also it returns -2 as a dialog result if Save button is clicked.

0
myfxp On

Thanks to the help of @CSS (see answer and comments above), this is the full currently working code (unless I'd still find any flaws):

Private Sub Button_Dokument_mit_Grafik_als_PDF_speichern_Click()
    Dim Grafik As Boolean
    Grafik = Options.PrintDrawingObjects
    Options.PrintDrawingObjects = True

    Dim dlg As Dialog
    Dim dlgResult As Long
    Set dlg = Dialogs(wdDialogFileSaveAs)
    With dlg
        .Format = wdFormatPDF
        dlgResult = .Display
        If dlgResult = -1 Then 'user clicked save button
            If .Name <> "" Then
                If IsFileInUse(.Name) Then
                    MsgBox "The target PDF file you are trying to save is locked or used by other application." & vbCrLf & _
                    "Please close the PDF file and try again.", vbExclamation
                Else
                    .Execute
                End If
            End If
        End If
    End With

    Options.PrintDrawingObjects = Grafik
End Sub

Private Function IsFileInUse(ByVal filePath As String) As Boolean
    On Error Resume Next
    Open filePath For Binary Access Read Lock Read As #1
    Close #1
    IsFileInUse = IIf(Err.Number > 0, True, False)
    On Error GoTo 0
End Function

Thanks to @CSS again. :)

You may want to edit your answer, though, so that it does reflect the finally working code. I've given appropriate thanks.