Thursday 28 August 2014

Mouse usage

Using CAD all day I had to get a proper mouse, with the right ergonomics and components to make it last and make it fun again.
                Did a little survey on gaming mouse and found out that I am a palm user (mouse grip wise) so I decided to get the Kone XTD. I had to disabled all LED’s and made it as common as possible for office work.
                The nice thing about it is that it has two thumb buttons that I have customized as Enter and Escape, my two commands I use mainly on the keyboard. You can make your own macros stored in the mouse that will work on any other computer.
                The other day I was looking over the stat’s page and realized that I am doing around 5500 clicks, 4000 scrolls and about 30 m travel (on max speed) EVERY DAY.
                In 1.5 months I have done 300k clicks, 200k scrolls, and around 1700 m (on max speed).
Fortunately it’s still holding strong and I hope to have it for a long time. I was looking to get the Logitech MX but it has an infinite scroll meaning that the wheel will spin without control at the smallest touch and you don’t want that in AutoCAD or Inventor for that matter.

Here are some screenshots of the stats:





What are yours? You can use free programs like
Or

ADS.

Thursday 21 August 2014

Save As PDF DWF iLogic

A while back I posted a blog about locating a certain project folder on the network before doing the PDF, DWF export. I used a simple ilogic command calling the saveas function:

ThisDoc.Document.SaveAs(strNameDWF & (".dwf") , True)
ThisDoc.Document.SaveAs(strNamePDF & (".pdf") , True)

Unfortunately as in the save as Inventor dialog it only saves the first sheet. On save as you need to click on options to choose all sheets as well as "print in colors" and dpi resolution.

So just as in the Save As dialog where you need to click options to export all sheets we need to add more complex code:





I wanted to have all sheets exported and the dwf file to contain a full 3d model for better visualization and markup.

Her's how the final code looks like:


' set the filepath of the contracts folder to start with.
strStartFolder = "G:\Commercial & Engineering\Engineering\Contracts\"
' get the filename without extension
oFileName = ThisDoc.FileName(False)  
'get the project type by reading the first 6 
'digits of the filename EX 105280 or 105281
strFolderType = ( Left (oFileName,6)) 
'get the last 3 digits of the project no start 
'after first 7 digits of filename Ex 005 or 109
strFolderNo = (Mid (oFileName,7, 3)) 
'get the first 9 digits to compose project 
'type and number Ex 105281005 or 105281109
strFolderProj = ( Left (oFileName,9)) 
'et the document revision to use in the new filename
oRevNum = iProperties.Value("Project", "Revision Number") 

'Set folder for project based on Contract No
If strFolderNo < "100" Then
strFolder3 = "\001-099\"
ElseIf strFolderNo >= "100" Then
strFolder3 = "\100-199\"
ElseIf strFolderNo >= "200" Then
strFolder3 = "\200-299\"
End If

'Find folder in start path that contains Folder Type string 
Dim dir1() As String = System.IO.Directory.GetDirectories _
(strStartFolder, strFolderType & "*")
'Add Contract No folder to our folder
Dim dir2 As String = String.Concat(dir1) & strFolder3

'Find folder in new path containing Folder Type 
Dim dir3() As String = System.IO.Directory.GetDirectories _
(dir2, strFolderProj & "*")
'Add Drawing folder to our path
dir4 = String.Concat(dir3) & "\Drawing\"
dir5 = String.Concat(dir4) & "\PDF"

' verify if foder exists, create if not
If Not System.IO.Directory.Exists(dir5) Then
    System.IO.Directory.CreateDirectory(dir5)
End If

'------------------- Complex code added to save all sheets    ----------------
oPDFAddIn = ThisApplication.ApplicationAddIns.ItemById _
("{0AC6FD96-2F4D-42CE-8BE0-8AEA580399E4}")
oDWFAddIn = ThisApplication.ApplicationAddIns.ItemById _
("{0AC6FD95-2F4D-42CE-8BE0-8AEA580399E4}")
oDocument = ThisApplication.ActiveDocument
oContext = ThisApplication.TransientObjects.CreateTranslationContext
oContext.Type = IOMechanismEnum.kFileBrowseIOMechanism
oOptions = ThisApplication.TransientObjects.CreateNameValueMap
oDataMedium = ThisApplication.TransientObjects.CreateDataMedium

If oPDFAddIn.HasSaveCopyAsOptions(oDataMedium, oContext, oOptions) Then
    oOptions.Value("All_Color_AS_Black") = 1
    oOptions.Value("Remove_Line_Weights") = 1
    oOptions.Value("Vector_Resolution") = 400
    'this publish all doens't work
    oOptions.Value("Sheet_Range") = Inventor.PrintRangeEnum.kPrintAllSheets
    'try a different publish all command
    'oOptions.Value("Publish_All_Sheets") = 1
    'oOptions.Value("Custom_Begin_Sheet") = 2
    'oOptions.Value("Custom_End_Sheet") = 4
End If

 'Set the PDF target file name
oDataMedium.FileName = dir5 & "\" & oFileName & "_Rev" & oRevNum & ".pdf"
'Publish document
oPDFAddIn.SaveCopyAs(oDocument, oContext, oOptions, oDataMedium)
i = MessageBox.Show("View the PDF file?", "Title",MessageBoxButtons.YesNo)
If i = vbYes Then : launchviewer = 1 : Else : launchviewer = 0 : End If 
If launchviewer = 1 Then ThisDoc.Launch(oDataMedium.FileName)


If oDWFAddIn.HasSaveCopyAsOptions(oDataMedium, oContext, oOptions) Then
    oOptions.Value("Launch_Viewer") = launchviewer
    oOptions.Value("Publish_All_Component_Props") = 1
    oOptions.Value("Publish_All_Physical_Props") = 1
    oOptions.Value("Password") = 0
    oOptions.Value("Publish_3D_Models") = Publish_3D_Models
    If TypeOf oDocument Is DrawingDocument Then
        Dim oSheets As NameValueMap
        oSheets = ThisApplication.TransientObjects.CreateNameValueMap
        oOptions.Value("Publish_Mode") = DWFPublishModeEnum.kCustomDWFPublish
        oOptions.Value("Publish_All_Sheets") = 1
        ' Publish the first sheet AND its 3D model
        Dim oSheet1Options As NameValueMap
        oSheet1Options = ThisApplication.TransientObjects.CreateNameValueMap
        oSheet1Options.Add("Name", "Sheet:1")
        oSheet1Options.Add("3DModel", True)
        oSheets.Value("Sheet1") = oSheet1Options
    End If
End If

 'Set the DWF target file name
oDataMedium.FileName = dir4 & oFileName & "_Rev" & oRevNum & ".dwf"
'Publish document
oDWFAddIn.SaveCopyAs(oDocument, oContext, oOptions, oDataMedium)
i = MessageBox.Show("View the DWF file?", "Title",MessageBoxButtons.YesNo)
If i = vbYes Then : launchviewer = 1 : Else : launchviewer = 0 : End If 
If launchviewer = 1 Then ThisDoc.Launch(oDataMedium.FileName)
'------------------- End Complex code added In To save all sheets --------------


Again, thanks to Curtis Waguespack for his code that I've used here. Check his blog, he even has a code that does batch export for all components of an assembly.

Best of luck.
ADS.

Thursday 14 August 2014

Component Tags in Inventor

As you are aware if you have done any routed systems there is no way of labeling same valve (or components for that matter) with different names / tags / id_numbers and call it on the drawing. You can create leader notes in the drawing but if they need changing you need to manually do it and it’s time consuming if you have large assemblies and multiple sheets and views. I have seen the same problem for people doing assemblies of electric components.
A 2” ball valve can have different identification tags in the P&ID but be a reused library component in Inventor.

I've been searching for a solution to this problem for the last 8 years or so and I couldn't find anything on autodesk forums or other discussion groups.
I instinctively knew that we would need to use the assembly browser name (occurrence name) but didn't see how to get it to show up in the drawing.

I have got together bits of iLogic codes from the internet that can get the assembly occurrence name and link it to the override value of my custom style balloons.
For this I have created a new balloon style called “Tags” and made it of type “Hexagon” with just the “Item” info in it.

The code processes just balloons of style “Tags” for we don’t want to change parts list balloons as well.
Because changing the occurrence name in the assembly involves a lot of steps (find component in browser / edit parent subassembly / change name of component / activate top level again) it is better to do it from the drawing.
You need to use “balloon” command, because “auto-balloon” cannot label same component on different views more than once.

Place balloons as you would normally do using “balloon” command and override the field with your text. You only need to do it once per component then run the code

When running the code it will prompt you if you want to set names from the balloons or from the browser. Choose balloon to send the override value to the model browser (occurrence name).

Continue placing balloons on all views and then run the code again. Choose to set the value from the browser to get the value on all new balloons.

This way I can balloon same component multiple times on same view if wanted.

As you can see the Occurrence name in browser and iproperties changed but the part number, stock number and other properties didn't changed.


Here's the code with explanatory comments:

' Set a reference to the drawing document.
' This assumes a drawing document is active.
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument

' Set Reference to Active Sheet
Dim oSheet As Sheet
oSheet = oDrawDoc.ActiveSheet

'get the name and path of the first model in the drawing
oAsmName = ThisDrawing.ModelDocument.FullFileName

' Set Reference to the Assembly and Open Silently
Dim oAsmDoc As AssemblyDocument
oAsmDoc = ThisApplication.Documents.Open(oAsmName, False)

' Set a reference to the assembly component definintion.
Dim oAsmCompDef As AssemblyComponentDefinition
oAsmCompDef = oAsmDoc.ComponentDefinition

Dim oBalloon As Balloon

'Ask the user if he wants to set the component name from browser
'or if he wants to set the browser name from overwritten balloon value
booleanParam = InputRadioBox("Set name from?: ", "Browser", "Balloon", True, Title :="Read/Write")


'Start a counter for sheets to process
Dim SheetCount As Long
SheetCount = 1
Dim oSheets As Sheet
'step through each drawing sheet
For Each oSheets In oDrawDoc.Sheets

    ' Iterate over each balloon on the sheet.
    For Each oBalloon In oSheet.Balloons
        Dim leader As Leader
        Leader = oBalloon.Leader
        'assuming the leader is a single line segment
        Dim leaderNode As LeaderNode = leader.AllNodes(2)
       
        Dim intent As GeometryIntent
        intent = leaderNode.AttachedEntity
   
        Dim curve As DrawingCurve
        curve = intent.Geometry
   
        Dim edgePx As EdgeProxy
        edgePx= curve.ModelGeometry
   
        Dim occurrencedrg As ComponentOccurrence
        occurrencedrg = edgePx.ContainingOccurrence
        
        Dim oBalloonValueSet As BalloonValueSet
       
        ' Iterate over each value set (attached balloons) in a balloon.
        For Each oBalloonValueSet In oBalloon.BalloonValueSets
            'only process if balloon of style of type "Tags"
            If oBalloon.Style.Name = "Tags" Then
                'if user wants to get name from browser
                If booleanParam = True Then
                    ' Set balloon value from browser.
                    oBalloonValueSet.OverrideValue = occurrencedrg.Name
                'if user wants to set browser name from balloon
                ElseIf booleanParam = False Then
                    ' Set browser name from balloon override value.
                    occurrencedrg.Name = oBalloonValueSet.OverrideValue
                End If
            End If
        Next
    Next
'Increase sheet counter
    SheetCount = SheetCount +1
Next



Best of  luck

ADS.

Thursday 7 August 2014

Info Table in Drawing

I have been toying with getting certain information from the models to the drawing and set it up neatly in a table.
                Unfortunately getting it in a General table is not possible but adding that info into a Parts List table is.
                At this point I need to mention that my table has no Parts in it (I use part list on single model not assembly) but rather a collection of parameters and, properties, found on the model. You can virtually add any info from the model to the drawing and show it on a neat table rather than using leader texts.
                A couple of examples of what you can get (what I can think of at the moment):
-          Sheet metal flat size
-          Model size
-          Any parameter (like volume) or iProperties from the model (user custom iProperties or not)
-          Color of the model
-          Suppressed and available features
-          Surface area of model (for painting and coating calcs) (need a bit of ilogic first to calculate area)
-          Etc.
What I needed was to get a list of active tank connections, size, type, position angle and description from the model as in the image bellow:



A typical code that looks for a part number and then writes to the description column of that row if the part number matches would be (Kudos to Curtis Waguespack):
' Set a reference to the drawing document.
' This assumes a drawing document is active.
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
   
' Set a reference to the first parts list on the active sheet.
' This assumes that a parts list is on the active sheet.
Dim oPartList As PartsList
oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1)
  
' Iterate through the contents of the parts list.
Dim i As Long
For i = 1 To oPartList.PartsListRows.Count
'look at only the part number column
oCell  = oPartList.PartsListRows.Item(i).Item("PART NUMBER")
                'find a specific part number
                If oCell.Value = "12-345" Then
                'identify the cell in the description column for the row that
                'the part number was found in
                oCell2 = oPartList.PartsListRows.Item(i).Item("DESCRIPTION")
                'write to the target cell
                oCell2.Value = "Bingo!"
                End if
Next

                Now you can play with:
-          If part number matches or contains....
-          If description or any other properties matches or contains....
-          If model is in a certain folder or location on disk (kind of tell if its library)
-          If weight over xx...
-          Whatever you can think off..  
and add a certain text or value to cell of the table like image bellow:



So first add a parts list (even if you have just a part on the model).


Edit the part list, click Column Chooser, User Properties. Add New Property and type all the properties you want to have in the table.



Take off visibility of the part in the table. If you right click on the model row you have the option to “Insert Custom Part” or “Remove Custom Part” and that’s what we’ll use in our ilogic code to get our info to show up.



Add a new rule in the Ilogic code browser.



Hope the comments on the code are self-explanatory:

' Set a reference to the drawing document.
' This assumes a drawing document is active.
Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument

'get the name of the first model in the drawing
modelName = IO.Path.GetFileName(ThisDrawing.ModelDocument.FullFileName)  

' Set a reference to the first parts list on the active sheet
' This assumes that a parts list is on the active sheet.
Dim oPartList As PartsList
oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1)

'count existing nr of rowsin the table
oCountRow = oPartList.PartsListRows.Count

        At this point it was easier to delete the current table and write the info again because the number of connections on the model can increase decrease an I didn't wanted to start playing with count, compare, delete, add. etc.
        You can only add and remove Custom Parts from the table so the "count existing rows to process" needs to be -1 that can't be deleted.


'remove the current rows
Dim i As Long
    For i = 1 To oCountRow - 1 ' can't delete last row that is not custom part
    oPartList.PartsListRows.Item(1).Remove() 'remove the first row al the time so you don't get error when removing row (i) say:4 on a 3 row table
Next

        You need to keep track of the number of rows you are writing in separately because the model can have 30 connections total but only 5 unsequenced connections active. Connection 30 in the model will not appear as N30 on the drawing but rather the next available sequenced number so we will use the row count in the first cell as well.


'Start at first row of the table and keep track of added rows
Dim row As Integer
row = 1

'Add the values we need
'Loop trough the nr of instances we need to add
For i = 1 To 25 '25 max tank connections at the moment
   
    'set oMyPar as the current N i connection
    oMyPar = Parameter(modelName, "N" & i & "_Conn")
   
    'don't throw error if the parameter is not created yet (does not exist)
    Parameter.Quiet=True
   
    'check if the parameter is set to true - Connection N(i) is used in the model
    If oMyPar = True Then

        'add another custom row to the table with options (position at index row, before index true)
        'to add Custom parts before the actual model part set as not visible In table
        oPartList.PartsListRows.Add(row, True)
       
        Instead of using Item(“Column name here”) you can use a number to indicate the column number like Item(1).

        oCell_Item  = oPartList.PartsListRows.Item(row).Item("Item")
       
        This is where we add the connection number based on the current row number rather than getting it from the model (not sequential).

        oCell_Item.Value = "N" & row
        oCell_Size = oPartList.PartsListRows.Item(row).Item("Size")
        oCell_Size.Value = Parameter(modelName, "N" & i & "_Size")
        oCell_Type = oPartList.PartsListRows.Item(row).Item("Type")
        oCell_Type.Value = Parameter(modelName, "N" & i & "_Type")
        oCell_Ang = oPartList.PartsListRows.Item(row).Item("Angle")
        oCell_Ang.Value = Parameter(modelName, "N" & i & "_Angle")
        oCell_Desc = oPartList.PartsListRows.Item(row).Item("Description")
        oCell_Desc.Value = Parameter(modelName, "N" & i & "_Desc")
       
        'increase row number for next loop
        row = row + 1
    End If
Next

                Again, I am not a programmer myself, and I just gathered this of the internet and got it customised for my case. I hope I have at least guided you in the right direction, and not confused you more.
                Here is the code again without my comments all over.

Dim oDrawDoc As DrawingDocument
oDrawDoc = ThisApplication.ActiveDocument
modelName = IO.Path.GetFileName(ThisDrawing.ModelDocument.FullFileName)   

Dim oPartList As PartsList
oPartList = oDrawDoc.ActiveSheet.PartsLists.Item(1)
oCountRow = oPartList.PartsListRows.Count
Dim i As Long
    For i = 1 To oCountRow - 1
    oPartList.PartsListRows.Item(1).Remove
Next
Dim row As Integer
row = 1
For i = 1 To 25
    oMyPar = Parameter(modelName, "N" & i & "_Conn")
    Parameter.Quiet=True
    If oMyPar = True Then
        oPartList.PartsListRows.Add(row, True) 

        oCell_Item  = oPartList.PartsListRows.Item(row).Item("Item")
        oCell_Item.Value = "N" & row
        oCell_Size = oPartList.PartsListRows.Item(row).Item("Size")
        oCell_Size.Value = Parameter(modelName, "N" & i & "_Size")
        oCell_Type = oPartList.PartsListRows.Item(row).Item("Type")
        oCell_Type.Value = Parameter(modelName, "N" & i & "_Type")
        oCell_Ang = oPartList.PartsListRows.Item(row).Item("Angle")
        oCell_Ang.Value = Parameter(modelName, "N" & i & "_Angle")
        oCell_Desc = oPartList.PartsListRows.Item(row).Item("Description")
        oCell_Desc.Value = Parameter(modelName, "N" & i & "_Desc")
        row = row + 1
    End If
Next