10 Replies Latest reply on Nov 18, 2015 5:49 PM by Tim Lewis

    How do I check if a PDF file is read only?

    Tim Lewis

      I am using the most recent version of SolidWorks 2015 Professional, and would like to check to see if a PDF file is read only.  So far, I've tried three approaches with no success.

       

      Approach #1: Catching the "Permission Denied" Error (Source)

       

      Function IsFileOpen1(filename As String) As Boolean
          Dim filenum As Integer, errnum As Integer
      
          On Error Resume Next   ' Turn error checking off.
          filenum = FreeFile()   ' Get a free file number.
          ' Attempt to open the file and lock it.
          Open filename For Input Lock Read As #filenum
          Close filenum          ' Close the file.
          errnum = Err           ' Save the error number that occurred.
          On Error GoTo 0        ' Turn error checking back on.
      
          ' Check to see which error occurred.
          Select Case errnum
      
              ' No error occurred.
              ' File is NOT already open by another user.
              Case 0
               IsFileOpen1 = False
      
              ' Error number for "Permission Denied."
              ' File is already opened by another user.
              Case 70
                  IsFileOpen1 = True
      
              ' Another error occurred.
              Case Else
                  Error errnum
          End Select
      
      End Function
      

       

      The problem with this is that the error is not captured.  Specifically, I get the following error on line #07:

      Capture.JPG

      I don't understand why VBA isn't obeying the "On Error Resume Next" command.

       

      Approach #2: Use the "GetAttr()" Command to Check if the File Is Read Only (Source)

       

      Function IsFileOpen2(filename As String) As Boolean
          With CreateObject("Scripting.FileSystemObject")
              If .FileExists(filename) Then
                  If GetAttr(filename) And vbReadOnly Then
                       IsFileOpen2 = True
                  Else
                       IsFileOpen2 = False
                  End If
          End With
      End Function
      

       

      The problem here is that the GetAttr function always returns "32" (i.e. "vbArchive" or "File has been changed since last backup") whether the file is open or not.  To be clear, at no point have I ever seen it be equal to "0" (i.e. "vbNormal" or "Normal") or "1" (i.e. "vbReadOnly" "Read-only").

       

      Approach #3: Use Outputs from the "SaveAs" Command to Check if SolidWorks Was Successful in Saving the File (Source)

       

      Dim exportData As SldWorks.ExportPdfData, status As Boolean, nErrors As Long, nWarnings As Long
      Set swApp = Application.SldWorks
      Set swModel = swApp.ActiveDoc
      Set exportData = swApp.GetExportFileData(swExportPdfData)
      exportData.ExportAs3D = True
      FilePath = Replace(swModel.GetPathName, ".sldprt", " (3D).pdf", 1, -1, vbTextCompare)
      status = swModel.Extension.SaveAs(FilePath, swSaveAsCurrentVersion, swSaveAsOptions_Silent, exportData, nErrors, nWarnings)
      If Not status Then
          MsgBox "PDF creation failed."
      End If
      

       

      The problem is that whether the file is indeed read-only or not, the value returned to "status" is always "False", and the value of "nErrors" is always "swGenericSaveError".

       

      Ultimately, if the file is not open, the PDF is saved successfully, but I want to be able to warn the user that the file failed to save, if that does happen.

        • Re: How do I check if a PDF file is read only?
          Chris Manger

          This is the code I use in my Export PDF macro:

           

              ' Checks if PDF file already exist in the directory
              Set fso = CreateObject("Scripting.FileSystemObject")
              If fso.FileExists(FileSave) = True Then
                  'Checks to see if file is read-only
                  If GetAttr(FileSave) And vbReadOnly Then
                      MsgBox "A PDF for '" & Filename & "' already exist and is read-only.  Please fix the file attribute and re-run the macro.", vbOKOnly + vbExclamation, "File is Read-Only"
                      GoTo Finish
                  End If
                  iResponse = MsgBox("A PDF for '" & Filename & "' already exist, are you sure you want to overwrite the file?", vbYesNo + vbQuestion + vbDefaultButton2, "File Exist")
                  If iResponse = vbYes Then
                  ' Checks to see if the file is open
                      If FileLocked(FileSave) Then
                         MsgBox "'" + FileSave + "' is open by you or another user.  Please close the file and re-run the macro.", vbOKOnly + vbExclamation, "File Is Open"
                         errorfinish = True
                         GoTo Finish
                      End If
                  Else
                      errorfinish = True
                      GoTo Finish
                  End If
              End If
          
            • Re: How do I check if a PDF file is read only?
              Tim Lewis

              Strange.  What does GetAttr(FileSave) (from Line #05) return when the file you're trying to save is open? When it's closed?

               

              For me, it always returns "32" (i.e. "vbArchive" or "File has been changed since last backup") no matter whether the file is open or closed.

               

              I should add that these files are being stored on a server, not the local hard drive.  I don't know if that makes any difference.

                • Re: How do I check if a PDF file is read only?
                  Jim Sculley

                  Note the subtle difference between your code and Chris' code:

                   

                  Yours:

                  If GetAttr(filename) = vbReadOnly Then 
                  

                   

                  Chris':

                  If GetAttr(FileSave) And vbReadOnly Then
                  

                   

                   

                  If you read the Remarks section of the MSDN docs for GetAttr you will see:

                   

                  "To determine which attributes are set, use the And operator to perform a bitwise comparison of the value returned by the GetAttr function and the value of the individual file attribute you want. If the result is not zero, that attribute is set for the named file."

                   

                  You shouldn't be paying any attention to the actual value returned, you should only pay attention to the result of performing a bitwise AND between the result and the flag(s) you are interested in.  If the AND is non-zero, the flag is set.

                   

                  Jim S.

                    • Re: How do I check if a PDF file is read only?
                      Tim Lewis

                      You are right, I should have had it with the "and".  However, making that change doesn't fix the problem.  See the screen recording here: http://autode.sk/1MTpPeA.  As you can see, the execution behaves as if the file is not open even though it actually is.  The reason for this is because the value returned by the GetAttr() function is "32", not "1", like it should be.  Therefore, when that value gets compared with the "vbReadOnly" value, it obviously ends up being false no matter what it is.

                        • Re: How do I check if a PDF file is read only?
                          Jim Sculley

                          You have wrongly assumed that opening a file causes its read only attribute to be set.  If you right click on your PDF file, and look at it's properties, you will see a 'Read only' checkbox.  This is what GetAttr is looking at.  If you check the box, the result of GetAttr will be 33 which indicates that both the vbArchive and vbReadOnly bits are set.

                           

                          The bottom line is that GetAttr won't tell you if a file is open.

                           

                          Your first approach is the correct way, but the code you posted isn't valid VB (you are missing some colons).  It should look like this:

                           

                          Function IsFileOpen(FileName As String)
                                  Dim ff As Long, ErrNo As Long
                             
                                  On Error Resume Next
                                  ff = FreeFile()
                                  Open FileName For Input Lock Read As #ff
                                  Close ff
                                  ErrNo = Err
                                  On Error GoTo 0
                             
                                  Select Case ErrNo
                                      Case 0:    IsFileOpen = False
                                      Case 70:  IsFileOpen = True
                                      Case Else: Error ErrNo
                                  End Select
                          End Function
                          

                           

                          The value of ErrNo is '70' when I have the PDF open (or if the read only attribute is set)  and '0' otherwise.

                           

                          Jim S.

                      • Re: How do I check if a PDF file is read only?
                        Chris Manger

                        The FileLocked in my code checks to see if the file is open.

                    • Re: How do I check if a PDF file is read only?
                      Ivana Kolin

                      which option do you have selected by Tools - Oprions - General - Error trapping? Break on all errors?