iLogic - check if public document is readonly?

iLogic - check if public document is readonly?

ChristianAndersenIsmyname
Advocate Advocate
2,657 Views
11 Replies
Message 1 of 12

iLogic - check if public document is readonly?

ChristianAndersenIsmyname
Advocate
Advocate

Hello, I've tried to google this issue, but can't find a solution.

 

This post have a solution that gives me a error that says something like "Can not find "public"-member readonly on this string type."

 

I've made a part name generator which works perfectly, but I want to add a code that checks if the public excel file is in use by another user (aka readonly).

 

I also want a loop that checks if the file is still read only every second for 5 seconds. If it its read only, it will end the code.

 

So far I've got this:

'-- Get excel file location and sheet
ExcelName = "K:\03. Native Drawings\01. Drawing Nos\Test1.xls"
ExcelSheet = "N-5XXXX"

'-- Check if file is open
i As Integer
For i = 0 To 5 
	
If ExcelName = ReadOnly Then

	System.Threading.Thread.CurrentThread.Sleep(1000) 	'wait 1 second
i = i + 1												'increase i by 1		
	
End If

 

I don't know if the loop function is correctly written, so any help in that area is also very welcome.

0 Likes
Accepted solutions (3)
2,658 Views
11 Replies
Replies (11)
Message 2 of 12

WCrihfield
Mentor
Mentor
Accepted solution

Here is a way to check if the file is ReadOnly:

Dim oFileName As String = "K:\03. Native Drawings\01. Drawing Nos\Test1.xls"
Dim oFInfo As New IO.FileInfo(oFileName)
If oFInfo.IsReadOnly Then
	MsgBox("File is ReadOnly.")
End If

And this other forum post will show you how to check if Excel is already running on your system.

https://forums.autodesk.com/t5/inventor-customization/irregular-error-quot-exception-from-hresult-0x... 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 3 of 12

ChristianAndersenIsmyname
Advocate
Advocate

Thanks for the answer, and this works. But I might have been a bit unclear.

Your code checks if the file itself is ReadOnly (from file properties), while I need it to be checked if the excel file is open at another user (and therefore readonly for me).

0 Likes
Message 4 of 12

WCrihfield
Mentor
Mentor

This might do the trick for you.

I think I probably got most of this from here, then slightly tweaked it.

 

Private Function FileIsOpen(ByVal oPath As String) As Boolean
    Try
        Dim oFS As IO.FileStream = IO.File.Open(oPath, IO.FileMode.Open, IO.FileAccess.ReadWrite, IO.FileShare.None)
        oFS.Close()
        oFS.Dispose()
        oFS = Nothing
        Return False
    Catch oEx As IO.IOException ' File is open
        Return True
    Catch ex As Exception ' Unknown error
        Return True
    End Try
End Function

 You would either need to put this in its own external iLogic rule, then set this rule's options to "Straight VB code", then call it from another rule using AddVbFile at the top, or remove the whole Private Function line & End Fuction, then substitute the oPath for your path in its own variable at the top,

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 5 of 12

ChristianAndersenIsmyname
Advocate
Advocate

I can't seem to get this to work.

 

I've tried to use it as a Straight VB code, but then I get error: (Translated) Sentence is not in a valid area.

I then tried to remove the Sub parts, so I have this code left:

oPath = "K:\03. Native Drawings\01. Drawing Nos\Test1.xls"
'Private Function FileIsOpen(ByVal oPath As String) As Boolean
    Try
        Dim oFS As IO.FileStream = IO.File.Open(oPath, IO.FileMode.Open, IO.FileAccess.ReadWrite, IO.FileShare.None)
        oFS.Close()
        oFS.Dispose()
        oFS = Nothing
'       Return False
    Catch oEx As IO.IOException ' File is open
'        Return True
    Catch ex As Exception ' Unknown error
'        Return True
    End Try
'End Function

Had to 'remove the Return's and End Function for it to even run the code, and now it semms like nothing happens. And I also have no idea what its doing. Tried to look at your reference link, but that didn't made me any smarter.

 

Did I do something wrong?

0 Likes
Message 6 of 12

I found a VBA code that works perfectly. Is it possible to adjust it to ilogic?

I know I can use InventorVb.RunMacro("ApplicationProject", "Module1", "OpenDocument"), but this wont perfectly, unless I write alot more of the code in VBA.

 

Sub OpenDocument()
    Dim sFileName   As String
     
     ' \\ Full path of test file
    sFileName = "K:\03. Native Drawings\01. Drawing Nos\Test1.xls"
     
     ' \\ Only open File if the file is not opened yet
    If Not IsFileLocked(sFileName) Then
        'Application.Documents.Open FileName:=sFileName
    End If
End Sub
 
 ' \\ This function checks if the file is allready opened by another process,
 ' \\ and if the specified type of access is not allowed.
 ' \\ If so the Open method will fail and a error occurs!
Function IsFileLocked(sFile As String) As Boolean
    On Error Resume Next
     
     ' \\ Open the file
    Open sFile For Binary Access Read Write Lock Read Write As #1
     ' \\ Close the file
    Close #1
     
     ' \\ If error occurs the document if open!
    If Err.Number <> 0 Then
         ' \\ msgbox for demonstration purposes
        MsgBox Err.Description, vbExclamation, "Warning File is opened"
         
         '\\ Return true and clear error
        IsFileLocked = True
        Err.Clear
    End If
End Function

 

0 Likes
Message 7 of 12

JhoelForshav
Mentor
Mentor
Accepted solution

Hi @ChristianAndersenIsmyname 

Try this iLogic-code to open excel file if it's not already in use 🙂

 

Sub Main
    Dim sFileName As String
     ' \\ Full path of test file
    sFileName = "K:\03. Native Drawings\01. Drawing Nos\Test1.xls"
    MsgBox(FileInUse(sFileName))
     ' \\ Only open File if the file is not opened yet
    If Not FileInUse(sFileName) Then
		Process.Start(sFileName)
    End If
End Sub
 
Public Function FileInUse(ByVal sFile As String) As Boolean
 Dim thisFileInUse As Boolean = False
 If System.IO.File.Exists(sFile) Then
     Try
       Using f As New IO.FileStream(sFile, System.IO.FileMode.Open, System.IO.FileAccess.ReadWrite, System.IO.FileShare.None)
       End Using
     Catch
       thisFileInUse = True
     End Try
 End If
 Return thisFileInUse
End Function
Message 8 of 12

ChristianAndersenIsmyname
Advocate
Advocate

This works!

 

I've already written everything in VBA now, but iLogic seems to be able to open/write in excel alot faster than VBA. Is this true?

If yes, I might consider writing it in iLogic now istead.

 

VBA Code below if interested.

Option Explicit
Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)

Sub GetPartNumber()
Dim sPath As String
sPath = "K:\03. Native Drawings\01. Drawing Nos"
Dim sName As String
sName = "Test2 – Kopi – Kopi.xls"
Dim sSheet As String
sSheet = "N-5XXXX"
Dim sFile As String
sFile = sPath & "\" & sName
    
    If Not IsFileLocked(sFile) Then
    End If
End Sub
 
Function IsFileLocked(sFile As String) As Boolean
    On Error Resume Next
    Open sFile For Binary Access Read Write Lock Read Write As #1
    Close #1

Dim i As Integer
    If Err.Number <> 0 Then
        For i = 1 To 5
        If i >= 5 Then GoTo Cancel:
            If IsFileLocked = True Then Err.Clear
                IsFileLocked = True
                'Sleep 100
                Next i
                End If
            If IsFileLocked = False Then

'-------------- THIS OPENS EXCEL, BUT DOESNT UPDATE TO CORRECT SHEET
'-------------- MAKE SURE TO NEVER SAVE FILE IN ANOTHER SHEET

    ' Get the active document.
    Dim oDoc As Document
    Set oDoc = ThisApplication.ActiveDocument

    ' Get the PropertySets object.
    Dim oPropSets As PropertySets
    Set oPropSets = oDoc.PropertySets
    Dim oPropSet As PropertySet
    Set oPropSet = oPropSets.Item("Design Tracking Properties")
    Dim oPropSet1 As PropertySet
    Set oPropSet1 = oPropSets.Item("Inventor User Defined Properties")
    Dim oPropSet2 As PropertySet
    Set oPropSet2 = oPropSets.Item("Inventor Document Summary Information")
    
    ' Get iProperties from PropertySets.
    Dim oPartNum As Property
    Set oPartNum = oPropSet.Item("Part Number")
    Dim rPartNum As Property
    Set rPartNum = oPropSet1.Item("Replace - Part Number")
    Dim oStockNum As Property
    Set oStockNum = oPropSet.Item("Stock Number")
    Dim oDescription As Property
    Set oDescription = oPropSet.Item("Description")
    Dim rDescription As Property
    Set rDescription = oPropSet1.Item("Replace - Description")
    Dim oProject As Property
    Set oProject = oPropSet.Item("Project")
    Dim oSign As Property
    Set oSign = oPropSet.Item("Designer")
    Dim oCreated As Property
    Set oCreated = oPropSet.Item("Creation Time")
    Dim oMaterial As Property
    Set oMaterial = oPropSet.Item("Material")
    Dim oDocumentType As Property
    Set oDocumentType = oPropSet2.Item("Category")
    Dim oApprovedBy As Property
    Set oApprovedBy = oPropSet.Item("Mfg Approved By")
    Dim oApprovedDate As Property
    Set oApprovedDate = oPropSet.Item("Mfg Date Approved")
    Dim oCustomer As Property
    Set oCustomer = oPropSet1.Item("Customer")
    Dim oComments As Property
    Set oComments = oPropSet1.Item("Comments")
    Dim oSO As Property
    Set oSO = oPropSet1.Item("SO-Number")

    Dim oExcel As Object
    Dim oBook As Object
    Dim objWorkbook As Object
    Dim oSheet As Object
    Dim oRow As Integer

    Set oExcel = CreateObject("Excel.Application")
    Set oBook = oExcel.Workbooks
    Set objWorkbook = oBook.Open(sFile)
    Set oSheet = objWorkbook.Worksheets(1)
            
oExcel.Visible = False

With oSheet
oRow = 5
Do While .range("F" & oRow) <> ""

oRow = oRow + 1

    Loop
Dim TempPart As String
TempPart = .range("A" & oRow)

'MsgBox TempPart

rPartNum.Value = TempPart

'MsgBox "Inventor: " & rPartNum.Value & vbNewLine & vbNewLine & "Excel: " & .range("A" & oRow)


Dim question As String
question = MsgBox("Part Number: " & rPartNum.Value & " is available." & vbNewLine & vbNewLine & "Generate Part?", vbYesNo, "Sucess!")
If question = vbYes Then

oPartNum.Value = .range("A" & oRow)
.range("B" & oRow) = oStockNum.Value
.range("C" & oRow) = oSO.Value
.range("D" & oRow) = oCustomer.Value
.range("E" & oRow) = oProject.Value
.range("F" & oRow) = rDescription.Value
.range("G" & oRow) = oDocumentType.Value
.range("H" & oRow) = oMaterial.Value
'.range("I" & oRow) = oDimension.Value           'Dimensions shall be Disabled
.range("J" & oRow) = oSign.Value
.range("K" & oRow) = oCreated.Value
.range("L" & oRow) = oApprovedBy.Value
.range("M" & oRow) = oApprovedDate.Value
.range("N" & oRow) = oComments.Value
.range("O" & oRow) = "Thanks Christian, for this amazing tool."

oExcel.ActiveWorkbook.Save
oExcel.Quit
MsgBox oPartNum.Value & " has been generated."

rPartNum.Value = ""
Else
rPartNum.Value = oPartNum.Value
End If

oExcel.ActiveWorkbook.Save
oExcel.Quit

End With


End If
Cancel:
        If i = 5 Then
        MsgBox sFile & " is locked", , "Error"
        End If
End Function

 

 

0 Likes
Message 9 of 12

maxim.teleguz
Advocate
Advocate
Accepted solution

I am only responding to this because i was trying to find a solution and couldnt and this thread kept coming up. 

Here is the universal solution:

Dim oFileName As String = ThisDoc.ModelDocument.FullFileName

Dim oFInfo As New IO.FileInfo(oFileName)
If oFInfo.IsReadOnly Then
	MsgBox("File is ReadOnly.")
End If
Message 10 of 12

WCrihfield
Mentor
Mentor

I guess I'm not seeing the difference in the code you just posted late yesterday and the code I originally posted in the first reply here nearly two years ago.  He already confirmed that this wasn't really what he was looking for.  It sounds like what is needed here, if working with an Excel Workbook type document is to reference the Excel namespace, then create an Excel.Workbook type variable, and set its value using the file path specified.  Then use its property called Workbook.ReadOnly to check its status.  That is a different status/property than the file explorer's file attribute called ReadOnly.

 

@ChristianAndersenIsmyname 

Something like this maybe:

(The two custom functions are ones I commonly use for convenience, and can be skipped in simple situations.)

AddReference "Microsoft.Office.Interop.Excel.dll"
Imports Microsoft.Office.Interop
Imports Microsoft.Office.Interop.Excel
Sub Main
	Dim oExcel As Excel.Application = GetExcel
	Dim oFileName As String = "K:\03. Native Drawings\01. Drawing Nos\Test1.xls"
	Dim oWB As Excel.Workbook = GetWorkbook(oExcel, False, oFileName)
	If IsNothing(oWB) Then
		MsgBox("Could not get the specified Excel Workbook.", , "")
		Exit Sub
	End If
	If oWB.ReadOnly Then
		MsgBox("This Excel Workbook is currently ReadOnly.", , "")
	Else
		MsgBox("This Excel Workbook is Not ReadOnly.", , "")
	End If
End Sub

Function GetExcel() As Excel.Application
	Dim oXL As Excel.Application
	Try
		'try to find an already running instance of the Excel Application
		oXL = GetObject(, "Excel.Application")
	Catch
		'it wasn't found open, so create an instance of it (start the application)
		oXL = CreateObject("Excel.Application")
		'oXL = New Microsoft.Office.Interop.Excel.Application
	Catch
		MsgBox("Failed to Get/Create an instance of the Excel Application. Exiting.", , "")
		Exit Function
	End Try
	Return oXL
End Function

Function GetWorkbook(oExcelApp As Excel.Application, oNew As Boolean, Optional oTemplateOrFullFileName As String = vbNullString) As Workbook
	If oExcelApp Is Nothing Then Return Nothing
	Dim oFileProvided As Boolean = False
	If oTemplateOrFullFileName <> "" Then oFileProvided = True
	Dim oFileExists As Boolean = False
	If oFileProvided Then oFileExists = System.IO.File.Exists(oTemplateOrFullFileName)
	If oNew = False And oFileExists = False Then Return Nothing
	Dim oWBs As Workbooks = oExcelApp.Workbooks
	Dim oWB As Workbook = Nothing
	If oNew = True AndAlso oFileExists Then
		oWB = oWBs.Add(oTemplateOrFullFileName)
		Return oWB
	ElseIf oNew = True AndAlso oFileExists = False Then
		oWB = oWBs.Add
		Return oWB
	End If
	If oWBs.Count > 0 Then
		For Each oWkbk As Workbook In oWBs
			If oWkbk.FullName = oTemplateOrFullFileName Then Return oWkbk
		Next
	ElseIf oWBs.Count = 0 Then
		oWB = oWBs.Open(oTemplateOrFullFileName)
		Return oWB
	End If
End Function

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 11 of 12

ChristianAndersenIsmyname
Advocate
Advocate

@WCrihfield is correct.

The first response is what I wasn’t looking for, but it does check if the file itself is in readonly.

What I was looking at that time was also answered later in the thread (I guess I forgot to verify solution).

Anyway, this was a fun throwback to see how much I’ve improved and dropped excel completely for the superior SQL (no need for readonly!).

Message 12 of 12

maxim.teleguz
Advocate
Advocate

no worries, All i know is his solution was to a static location but I needed a universal any file name solution. Couldn't find it any help online so I wrote it instead and posted it here. This way new people in the future can look at this page and know they are looking at the best solutions. 

As you can tell i look before I respond. Why else would I respond to such an old post? 

0 Likes