Make Components command implemented via API

<?xml encoding=”UTF-8″>By Adam Nagy

If you want to customize the behaviour of Manage >> Layout >> Make Components command then doing the whole thing via the API might be a good alternative. Here is the code which seems to be doing the same – as far as I can tell. This VBA code also sets the Project >> Description iProperty of each created part to the name of the Solid Body that it is referencing from the original part:

' Run this inside a Multi-Solid part
Sub MakeComponentsProgrammatically()
' Folder to place the new components:
' assembly and subcomponents
Dim f As String: f = "C:temptest1"
' Make sure the folder exists
Dim fso As Object
Set fso = ThisApplication.FileManager.FileSystemObject
If Not fso.FolderExists(f) Then Call fso.CreateFolder(f)
Dim doc As PartDocument
Set doc = ThisApplication.ActiveDocument
' Create the assembly
Dim asm As AssemblyDocument
Set asm = ThisApplication.Documents.Add(kAssemblyDocumentObject)
Dim sb As SurfaceBody
For Each sb In doc.ComponentDefinition.SurfaceBodies
' Create part for each body
Dim prt As PartDocument
Set prt = ThisApplication.Documents.Add(kPartDocumentObject)
' Set iProperties >> Project >> Description
' It's inside "Design Tracking Properties"
Dim p As Property
Set p = prt.PropertySets( _
"{32853F0F-3444-11D1-9E93-0060B03C1CA6}")("Description")
p.Expression = sb.name
Dim dpcs As DerivedPartComponents
Set dpcs = prt.ComponentDefinition.ReferenceComponents. _
DerivedPartComponents
Dim dpd As DerivedPartUniformScaleDef
Set dpd = dpcs.CreateUniformScaleDef(doc.FullDocumentName)
' Exclude the other solid bodies
Dim dpe As DerivedPartEntity
For Each dpe In dpd.Solids
' Have to set it for all entities as the default value
' can differ in various cases
dpe.IncludeEntity = dpe.ReferencedEntity Is sb
Next
Call dpcs.Add(dpd)
' Could have any name but we use the solid body's name
Call prt.SaveAs(f + sb.name + ".ipt", False)
' Place an instance of it inside the assembly
Dim mx As Matrix
Set mx = ThisApplication.TransientGeometry.CreateMatrix()
Call asm.ComponentDefinition.Occurrences. _
AddByComponentDefinition(prt.ComponentDefinition, mx)
' Don't need it anymore
Call prt.Close
Next
Call asm.SaveAs( _
f + Left(doc.DisplayName, Len(doc.DisplayName) - 4) + _
".iam", False)
Call asm.Close
End Sub

This is what we start off with:

MC1

And this is what we get after running the code:

MC2

 

 


Comments

13 responses to “Make Components command implemented via API”

  1. Zdenko S. Avatar
    Zdenko S.

    Adam,
    great job, iproperties Description is Box2and it is perfect, but Part Number is same as Description. I do not think we want that way. As you described and I do same way in making components. Component Name should be Part Number in your eg. should be MultiSolid.

  2. Hi Adam,
    This is great stuff!
    Would you happen to have an example showing how to this using nested sketch blocks?
    I am having a hard time tracking one down. (Cross-post here: https://forums.autodesk.com/t5/inventor-customization/derived-assembly-using-sketch-blocks-as-the-base/td-p/6346363
    Thanks,
    Alex.

  3. S Wollner Avatar
    S Wollner

    Hello,
    how can I get the sheet metal definition copied / referenced?

  4. Hi Adam – great as usual but solid pattern is not working. It will not consider in derived – can you update the code to include this solids as well.
    thanks
    jens

  5. Hi Jens,
    Can you please provide non confidential data to investigate?
    Thanks and regards,
    Chandra shekar G

  6. Hi Chandra
    Thanks for your reply and nothing to share from my end – only make a pattern and create new solids for each and run the code. You will see what happened. It will only take the one from where you pattern.
    Thanks
    Jens

  7. The problem was that I assumed that the default value for IncludeEntity was always True – but it was not the case for elements of a pattern. Updated the code and it works for me now.

  8. Hi Jens,
    Hoping that below iLogic code may be helpful. In this, 3rd pattern feature is used as solid body.
    ‘ Run this inside a Multi-Solid part
    Sub Main()
    ‘ Folder to place the new components:
    ‘ assembly and subcomponents
    Dim f As String: f = “C:\temp\test1\”
    ‘ Make sure the folder exists
    Dim fso As Object
    fso = ThisApplication.FileManager.FileSystemObject
    If Not fso.FolderExists(f) Then Call fso.CreateFolder(f)
    Dim doc As PartDocument
    doc = ThisApplication.ActiveDocument
    ‘ doc = ThisDoc.Document
    ‘ Create the assembly
    Dim asm As AssemblyDocument
    asm = ThisApplication.Documents.Add(kAssemblyDocumentObject)
    Dim sb As SurfaceBody
    For Each sb In doc.ComponentDefinition.SurfaceBodies
    ‘ Create part for each body
    Dim prt As PartDocument
    If Not sb.Name.Contains(“@”) Then
    prt = ThisApplication.Documents.Add(kPartDocumentObject)
    ‘ Set iProperties >> Project >> Description
    ‘ It’s inside “Design Tracking Properties”
    Try
    iProperties.Value(“Project”, “Part Number”) = sb.Name
    Catch
    End Try
    Dim dpcs As DerivedPartComponents
    dpcs = prt.ComponentDefinition.ReferenceComponents. _
    DerivedPartComponents
    Dim dpd As DerivedPartUniformScaleDef
    dpd = dpcs.CreateUniformScaleDef(doc.FullDocumentName)
    ‘ Exclude the other solid bodies
    Dim dpe As DerivedPartEntity
    Dim oPCD As PartComponentDefinition = doc.ComponentDefinition
    Dim oRectPatName As String = oPCD.Features.RectangularPatternFeatures(3).Name
    For Each dpe In dpd.Solids
    For Each oSolid As SurfaceBody In oPCD.SurfaceBodies
    For i As Integer = 1 To oSolid.AffectedByFeatures.Count
    If oSolid.AffectedByFeatures(i).Name = oRectPatName Then
    If Not dpe.ReferencedEntity Is oSolid Then
    dpe.IncludeEntity = True
    If Not dpe.ReferencedEntity Is sb Then
    dpe.IncludeEntity = False
    End If
    End If
    End If
    Next
    Next
    Next
    Call dpcs.Add(dpd)
    ‘ Could have any name but we use the solid body’s name
    Call prt.SaveAs(f + sb.Name + “.ipt”, False)
    ‘ Place an instance of it inside the assembly
    Dim mx As Matrix
    mx = ThisApplication.TransientGeometry.CreateMatrix()
    If Not sb.Name.Contains(“@”) Then
    Call asm.ComponentDefinition.Occurrences. _
    AddByComponentDefinition(prt.ComponentDefinition, mx)
    ‘ Don’t need it anymore
    Call prt.Close
    End If
    End If
    Next
    Call asm.SaveAs( _
    f + Left(doc.DisplayName, Len(doc.DisplayName) – 4) + _
    “.iam”, False)
    Call asm.Activate
    End Sub
    Thanks and regards,
    Chandra shekar G

  9. PeterO Avatar
    PeterO

    Hi Adam
    I have adapted your code to run as a Forge plugin. The problem is that it it painfully slow. My guess that the “For Each dpe In dpd.Solids” loop is inefficient. Do you have any thoughts on optimising this code, or should I raise it in another forum?
    Thanks

  10. PeterO Avatar
    PeterO

    I should add, the part in question had 103 solids and took over 90 seconds to process

  11. You could add time stamps at multiple lines in the code to see where it spends most of its time. I assume it’s not a Forge specific issue (unless it’s faster for you on the desktop)
    You can check on the forum if anyone has a better idea: https://forums.autodesk.com/t5/inventor-customization/bd-p/120
    And here is a blog post on improving performance: https://modthemachine.typepad.com/my_weblog/2015/09/improving-your-programs-performance.html

  12. Hi this code is working fine for most parts but I have two parts where the derived entity does not work and the part become empty. I can afterwards select the entity and get those parts to appear manually. How can I check this issue and solve it?

  13. Try to create it through the UI and investigate how things are set up: https://adndevblog.typepad.com/manufacturing/2013/10/discover-object-model.html
    Then try to do the same using the API.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading