Tuesday, July 28, 2015

Vault Copy Design Action Rule Sets & iLogic Rules

You've did a Copy Design in Vault 2015 R2 (or later) of your master template and checked out the copied assembly along with all the necessary files.  You're ready to use the awesome-ness of iLogic to make your job easier so you open up the assembly in Inventor.

Woah!  Stop!  Where are all my iLogic rules?  Call Sherlock Holmes!

The Copy Design process was changed in the Vault 2015 R2 version and began using Action Rule Sets.  A rule set is a collection of property rules that determine file property behavior during a copy operation.

The default Rule Set is the culprit that stole your iLogic rules.  It is set up to remove iLogic rules!  If you are using Rule Sets in order to control file properties then you are familiar with editing the Rule Sets.  This post is only going to show you how to copy the Default Rule Set in order to create a version that keeps the iLogic rules in the copied assembly.

You need to be logged in as an Administrator to the Vault in order to manage Action Rules.

1. Start the CopyDesign Process
2. Click on the Vault symbol and select Action Rules.


3. Select the Default Rule Set and then click Copy… at the top.

4. Call it iLogic Template Rule Set or something similar.
5. Edit that newly created Rule Set.
6.     Select the iLogicRuleStatus in the lower right window then change the Value to User and then             click Replace.

8. Hit OK on all the dialog boxes to get back to the main CopyDesign.

To set the Action Rule Set to use during the Copy Design Process:

1. Start the CopyDesign Process
2. Click the drop down arrow under the Selected Rule Set button and select the newly created rule set.


This Rule Set is saved locally.  The default location is:
C:\Users\username\AppData\Roaming\Autodesk\Autodesk Copy Design 2016\CopyDesignRuleSets

I hope that helps you solve the case of the missing iLogic rules.

"Nothing clears up a case so much as stating it to another person." ~ Sherlock Holmes

Thanks,
Randy

Wednesday, July 22, 2015

External Rules & Inventor 2016

Hey folks, I hope that you've had a chance to look at Inventor 2016 and more specifically, the way External Rules are handled in the latest release.

Inventor 2016 allows us to set the External Rules Directories just as previous releases had, but now, the files that are in those directories will automatically show up in the External Rules tab of the iLogic Browser.

To set the External Rules Directory, go to the Tools tab of the Ribbon, expand the flyout for the Options panel and select iLogic Configuration.


Once the directories are set, rules that are in the specified folder will automatically be there for you to use!

You can also add additional files.  Right mouse click in the External Rules tab of the iLogic Browser and select Add External Rule.  Browse to the location of your rule and select it.  Inventor will create the folder structure for you under a Manually Added heading.

This makes sharing external rules throughout your design group a simpler process.

Can you think of other ways that this can help you organize your external rules?  Let me know in the Comments section below!

"You can’t wait for inspiration. You have to go after it with a club." ~ Jack London

Thanks!
Randy

Friday, July 10, 2015

HoleTable Modifications

Hey all, long time since my last post.  I apologize for that.  Busy is a good thing, right?

I recently had a chance to look at something in the Inventor API that I had yet to have a reason to: Hole Tables.  A client was spending time on many drawings modifying a hole table column based upon the hole type.  The holes are iFeatures and he could not find a way of adding this data to the iFeature so that it would populate in the hole table automatically.

This presented me with a chance to see what access we had to Hole Tables in the Inventor API.

First, I checked for a hole table and for a drawing view.  If either doesn't exist then I'd warn the user.

    '    Declare variables
        Dim oDrawDoc As DrawingDocument
        oDrawDoc = ThisApplication.ActiveDocument
        Dim oSheet1 As Sheet
        oSheet1 = oDrawDoc.Sheets.Item(1)
    
    '    Check for a hole table
        If oSheet1.HoleTables.Count = 0 Then 
            MessageBox.Show("Please ensure a hole table is present on the current drawing.", "No Hole Table",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

    '    Check for drawing views
        If oSheet1.DrawingViews.Count = 0 Then 
            MessageBox.Show("Please ensure a drawing view is present on the current drawing.", "No Hole Table",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

Next, I cycled through the Hole Table columns to determine which column numbers were the columns that I needed to either get data from or write data to.  If any of those columns don't exist then I'd warn the user.

    '    Declare variables        
        Dim oView As DrawingView
        oView = oSheet1.DrawingViews.Item(1)
        Dim oHoleTable As HoleTable
        oHoleTable = oSheet1.HoleTables.Item(1)
        Dim oRow As HoleTableRow
        Dim oColumn As HoleTableColumn
        
    '    Cycle thru each column to determine the XDIM, YDIM, DESCRIPTION and CALLOUT columns.
        iXDIMColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oXDIMColumnName = oColumn.Title
            If UCase(oXDIMColumnName) = "XDIM" Then Exit For
            iXDIMColumn = iXDIMColumn + 1
        Next
        If iXDIMColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named XDIM.", "No XDIM column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If
        
        iYDIMColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oYDIMColumnName = oColumn.Title
            If UCase(oYDIMColumnName) = "YDIM" Then Exit For
            iYDIMColumn = iYDIMColumn + 1
        Next
        If iYDIMColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named YDIM.", "No YDIM column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

        iDescColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oDescColumnName = oColumn.Title
            If UCase(oDescColumnName) = "DESCRIPTION" Then Exit For
            iDescColumn = iDescColumn + 1
        Next
        If iDescColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named DESCRIPTION.", "No DESCRIPTION column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If
        
        iCalloutColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oCalloutColumnName = oColumn.Title
            If UCase(oCalloutColumnName) = "CALLOUT" Then Exit For
            iCalloutColumn = iCalloutColumn + 1
        Next
        If iCalloutColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named CALLOUT.", "No CALLOUT column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

Lastly, I checked the DESCRIPTION column and read it's text.  The client had specific data that he would add to the CALLOUT column based upon the DESCRIPTION column.  I did this with a Select Case but there are many other ways of accomplishing this.  The client also wished to modify the CALLOUT column for any additional holes that are part of the same iFeature.  I accomplished this by concatenating the XDIM & YDIM for all holes and if they matched the threaded hole then I modified their CALLOUT column as well.

    '    Cycle thru each row in hole table.  Split Description column (5th) and set callout based on text for rows where XDIM and YDIM match.
        For Each oRow In oHoleTable.HoleTableRows
            oText = oRow.Item(iDescColumn).Text
            Dim oTextLeft As String() = oText.Split(New Char() {"U"c})
            sThreadData = oTextLeft(0)
            
            Select Case sThreadData 
                Case "5/16-24 "
                    sCallout = "SAE2"
                Case "7/16-20 "
                    sCallout = "SAE4"
                Case "9/16-18 "
                    sCallout = "SAE6"
                Case "3/4-16 "
                    sCallout = "SAE8"
                Case "7/8-14 "
                    sCallout = "SAE10"
                Case "1 1/16-12 "
                    sCallout = "SAE12"
                Case "1 5/16-12 "
                    sCallout = "SAE16"
                Case "1 5/8-12 "
                    sCallout = "SAE20"
                Case "1 7/8-12 "
                    sCallout = "SAE24"
                Case "2 1/2-12 "
                    sCallout = "SAE32"
                Case Else
            End Select
            
        '    Concatenate XDIM & YDIM
            If Not sCallout = "" Then
                sLocation = oRow.Item(2).Text & oRow.Item(3).Text
                Call ChangeCallout(oRow,oHoleTable,sLocation,sCallout,iXDIMColumn,iYDIMColumn,iCalloutColumn)
            End If
            
            sCallout = ""
    Next

End Sub

Private Sub ChangeCallout(ByVal oRow As HoleTableRow, oHoleTable As HoleTable, sLocation As String, sCallout As String, iXDIMColumn As Integer,iYDIMColumn As Integer, iCalloutColumn As Integer)
    For Each oRow In oHoleTable.HoleTableRows
        If oRow.Item(iXDIMColumn).Text & oRow.Item(iYDIMColumn).Text = sLocation Then
            oRow.Item(iCalloutColumn).Text = sCallout
        End If
    Next
End Sub

The entire code is here:

Sub Main
    '    Declare variables
        Dim oDrawDoc As DrawingDocument
        oDrawDoc = ThisApplication.ActiveDocument
        Dim oSheet1 As Sheet
        oSheet1 = oDrawDoc.Sheets.Item(1)
    
    '    Check for a hole table
        If oSheet1.HoleTables.Count = 0 Then 
            MessageBox.Show("Please ensure a hole table is present on the current drawing.", "No Hole Table",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

    '    Check for drawing views
        If oSheet1.DrawingViews.Count = 0 Then 
            MessageBox.Show("Please ensure a drawing view is present on the current drawing.", "No Hole Table",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

    '    Declare variables        
        Dim oView As DrawingView
        oView = oSheet1.DrawingViews.Item(1)
        Dim oHoleTable As HoleTable
        oHoleTable = oSheet1.HoleTables.Item(1)
        Dim oRow As HoleTableRow
        Dim oColumn As HoleTableColumn
        
    '    Cycle thru each column to determine the XDIM, YDIM, DESCRIPTION and CALLOUT columns.
        iXDIMColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oXDIMColumnName = oColumn.Title
            If UCase(oXDIMColumnName) = "XDIM" Then Exit For
            iXDIMColumn = iXDIMColumn + 1
        Next
        If iXDIMColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named XDIM.", "No XDIM column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If
        
        iYDIMColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oYDIMColumnName = oColumn.Title
            If UCase(oYDIMColumnName) = "YDIM" Then Exit For
            iYDIMColumn = iYDIMColumn + 1
        Next
        If iYDIMColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named YDIM.", "No YDIM column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If

        iDescColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oDescColumnName = oColumn.Title
            If UCase(oDescColumnName) = "DESCRIPTION" Then Exit For
            iDescColumn = iDescColumn + 1
        Next
        If iDescColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named DESCRIPTION.", "No DESCRIPTION column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If
        
        iCalloutColumn = 1
        For Each oColumn In oHoleTable.HoleTableColumns
            oCalloutColumnName = oColumn.Title
            If UCase(oCalloutColumnName) = "CALLOUT" Then Exit For
            iCalloutColumn = iCalloutColumn + 1
        Next
        If iCalloutColumn > oHoleTable.HoleTableColumns.Count Then 
            MessageBox.Show("Please ensure hole table has a column named CALLOUT.", "No CALLOUT column",MessageBoxButtons.OK,MessageBoxIcon.Warning)
            Return
        End If
            
    '    Cycle thru each row in hole table.  Split Description column (5th) and set callout based on text for rows where XDIM and YDIM match.
        For Each oRow In oHoleTable.HoleTableRows
            oText = oRow.Item(iDescColumn).Text
            Dim oTextLeft As String() = oText.Split(New Char() {"U"c})
            sThreadData = oTextLeft(0)
            
            Select Case sThreadData 
                Case "5/16-24 "
                    sCallout = "SAE2"
                Case "7/16-20 "
                    sCallout = "SAE4"
                Case "9/16-18 "
                    sCallout = "SAE6"
                Case "3/4-16 "
                    sCallout = "SAE8"
                Case "7/8-14 "
                    sCallout = "SAE10"
                Case "1 1/16-12 "
                    sCallout = "SAE12"
                Case "1 5/16-12 "
                    sCallout = "SAE16"
                Case "1 5/8-12 "
                    sCallout = "SAE20"
                Case "1 7/8-12 "
                    sCallout = "SAE24"
                Case "2 1/2-12 "
                    sCallout = "SAE32"
                Case Else
            End Select
            
        '    Concatenate XDIM & YDIM
            If Not sCallout = "" Then
                sLocation = oRow.Item(2).Text & oRow.Item(3).Text
                Call ChangeCallout(oRow,oHoleTable,sLocation,sCallout,iXDIMColumn,iYDIMColumn,iCalloutColumn)
            End If
            
            sCallout = ""
    Next

End Sub

Private Sub ChangeCallout(ByVal oRow As HoleTableRow, oHoleTable As HoleTable, sLocation As String, sCallout As String, iXDIMColumn As Integer,iYDIMColumn As Integer, iCalloutColumn As Integer)
    For Each oRow In oHoleTable.HoleTableRows
        If oRow.Item(iXDIMColumn).Text & oRow.Item(iYDIMColumn).Text = sLocation Then
            oRow.Item(iCalloutColumn).Text = sCallout
        End If
    Next
End Sub


"A very small man can cast a very large shadow" ~ Varys

Happy Coding!

Randy

Wednesday, June 10, 2015

Inventor Automation Workshop

Attending the Work Smarter, Not Harder: Streamline Your Design Process and See Instant ROI webcast. Join me?

Monday, December 1, 2014

We're going to need a bigger box...

Wouldn't it be nice if every time you reached into your toolbox you could pull out the perfect tool for the job?  You never had to use a pair of pliers to remove a spark plug?  You never had to resort to hacking through that wire with dull scissors?

The Inventor iLogic integrated development environment, (IDE), provides an awesome set of tools for quickly crafting conditional automation code.  i.e. "If this hole increases in size by x, Then thicken they webbing member by y."

This conditional logic is in fact the central theme of this blog; if this happens, then do that.  Pretty simple right?

What happens when simple conditional logic or using the provided code snippets don't measure up to the task at hand?  Fear not!  There is a solution.  A solution that's not well documented or advertised but that's been available nearly since iLogic's inception.  "...pssst, you can use, (reference), other code libraries and frameworks within the iLogic IDE.

After you've made the reference, you can call into those libraries and execute publicly exposed functions just as if they were your own.  

You can add references in two ways, AddReference "System.Drawing.dll" or through the Imports statement, as in Imports System.IO.  Inventor iLogic automatically "includes" the following .NET framework libraries or namespaces:
  • System
  • System.Math
  • System.Collections
  • Microsoft.VisualBasic
  • Autodesk.iLogic.Interfaces
  • Autodesk.iLogic.Runtime
Hmmmmm, seems that iLogic is capable of  leveraging the Microsoft .NET framework.  Well isn't that handy.  More later...



Let's take a look at a simple example that checks to see if a file exists.

Imports System.IO

Sub Main()
    Dim fName As String = "C:\Temp\rt1.ipt"
    If file.Exists(fname) Then 
        MsgBox(fName & " exists!")
    End If
End Sub

If the file is really there, we get this result:


Let's try another:

Imports System.IO

Sub Main()
    Dim path As String = "C:\temp\text.txt"
    File.AppendAllText(path, "test message" + vbCr)
End Sub



The above code snippet can be very useful for adding entries to a "log file".

I've always been a firm believer that if you intend to use a block of code more than once it deserves to me its own method or function.  Let's look at some other ways to code this in a little more efficient and professional manner.

Option 1 (Method)

Imports System.IO

Sub Main()
    Dim path As String = "C:\temp\text.txt"
    Call LogWriter(path,"Message passed as argument")
End Sub

Private Sub LogWriter(ByVal path As String, ByVal msg as String)
    File.AppendAllText(path, msg + vbCr)
End Sub

Now whenever we need to write a new line to our log file we just pass the path and the message, and the Call keyword is optional.  

LogWriter(path,"Message passed from a method")

We don't "expect" anything to go wrong because the .AppendAllText will create the file if it doesn't exist.  Oh wait, what if I typed the folder path wrong?

Let's add some error handling.


Imports System.IO

    Sub Main()
        Dim path As String = "C:\temp\text.txt"
        LogWriter(path, "Message passed as argument")
    End Sub

    Private Sub LogWriter(ByVal path As String, ByVal msg As String)
        Try
            File.AppendAllText(path, msg + vbCr)
        Catch ex As Exception
            MsgBox(ex.Message, MsgBoxStyle.Critical, "Something has gone horribly wrong!")
        End Try

    End Sub

The Try/Catch block is your friend.  Think of it as the modern-day equivalent of the old 
On Error Resume Next.  The concept is super simple, "Try" this block of code, "Catch and handle any errors."
You may also be interested in File.Move, File.Copy, File.Exists or File.Replace.  Check out all of the File Class methods or the entire.NET Framework Class collection.
In the coming weeks/months extend this post to include "methods vs. functions", linking to data sources and expanded form functionality.
If you've learned one new thing by reading this post I've achieved my goal.

Happy Trails!


Thursday, November 20, 2014

Generate Drawings using iLogic Webcast

Hey everyone,

Wanted to give everyone a heads up that our own Carl Smith will be hosting a webinar today and discussing using iLogic to generate Inventor drawings.

It's free and I'm sure you'll pick up at least one thing that will help you in all your automation endeavors.

Generate Drawings using iLogic Webcast

Thursday, November 20
11:00 AM Eastern Time

REGISTER NOW


In case the above link doesn't work:

http://www.imaginit.com/Events/Registration/eventid/a2w700000000FBJAA2

Thanks,
Randy

Monday, September 29, 2014

Drawing View Scale Part II

In my last post, I discussed one solution to get a drawing view scale.  That solution found the drawing view with the lowest numerical value as part of view name (VIEW1, VIEW5, etc.) and used it's scale as an iProperty of the drawing.


Another solution that my client wanted was to present all the view names and allow the user to select which view he/she wanted to represent the scale in the title block.


Like the first solution, we cycled through each sheet on the drawing and looked at the view name.  If the view name begins with "VIEW" then it was used to build a one dimensional array.  We also concatenated the view scale with the view name to satisfy the needs of seeing both the view name and the view scale.

'    Cycle thru each sheet.  Build array of View Name and View Scale.
     For Each oSheet In oSheets
         oViews = oSheet.DrawingViews
         For Each oView In oViews
             oViewName = oView.Name
             If Left(oViewName,4) = "VIEW" Then
                 oScale = oView.Scale
                 oConc = oViewName & ": @ " & oScale
                 oViewList.Add(oConc)
             End If
         Next
     Next

We then sorted the array and set a MultiValue list using that array.

'    Sort array
     oViewList.Sort

'    Set Multi-Value List from array
     MultiValue.List("ViewList") = oViewList

Next we presented an input box to the user using the MultiValue list.

'    Present Input Box for user selection
     selected = InputListBox("Select a view from the list", _
     MultiValue.List("ViewList"), oViewList.item(0), Title := "Views", _
     ListName := "View Name @ Scale")

Next we extracted the view name and view scale from the user selection.

'    Extract View Name and View Scale from user selection    
     delimpos = InStr(selected, "@")
     oSelectedView = Left(selected,delimpos - 1)
     oSelectedScale = Right(selected,Len(selected)-delimpos)

Finally, the view scale was pushed to a custom iProperty that was displayed in the drawing title block.

'    Set custom iProperty based on user selection
     iProperties.Value("Custom", "Scale") = RoundToFraction(oSelectedScale, 1/8, _
     RoundingMethod.Round) & ":1"

The full code is listed here:

'    Setting Variables
     Dim oDrawDoc As DrawingDocument = ThisDrawing.Document
     Dim oSheet As Sheet
     Dim oSheets As Sheets
     oSheets = oDrawDoc.Sheets
     Dim oView As DrawingView
     Dim oViews As DrawingViews
    
     Dim oScale As Double
     Dim oViewName As String
     Dim oConc as String
     Dim oSelectedView As String
     Dim oSelectedScale As String
     Dim oViewList As New ArrayList
    
'    Cycle thru each sheet.  Build array of View Name and View Scale.
     For Each oSheet In oSheets
         oViews = oSheet.DrawingViews
         For Each oView In oViews
             oViewName = oView.Name
             If Left(oViewName,4) = "VIEW" Then
                 oScale = oView.Scale
                 oConc = oViewName & ": @ " & oScale
                 oViewList.Add(oConc)
             End If
         Next
     Next

'    Sort array
     oViewList.Sort

'    Set Multi-Value List from array
     MultiValue.List("ViewList") = oViewList
    
'    Present Input Box for user selection
     selected = InputListBox("Select a view from the list", _
     MultiValue.List("ViewList"), oViewList.item(0), Title := "Views", _
     ListName := "View Name @ Scale")
    
'    Extract View Name and View Scale from user selection    
     delimpos = InStr(selected, "@")
     oSelectedView = Left(selected,delimpos - 1)
     oSelectedScale = Right(selected,Len(selected)-delimpos)

'    Set custom iProperty based on user selection
     iProperties.Value("Custom", "Scale") = RoundToFraction(oSelectedScale, 1/8, _
     RoundingMethod.Round) & ":1"
    
'    Update
     iLogicVb.UpdateWhenDone = True

PS - Sorry about the formatting.  I can't seem to get those extra spaces out of the sections where I've broken up the code.

Please leave a comment and let me know what you think.

Randy

"Opportunity is missed by most people because it is dressed in overalls and looks like work." - Thomas Edison