vbams-wordword-2013

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


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


Solution

  • 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.