Die Inventor FAQ wird unterstützt von:

Inventor FAQ Logo

02.05.2017

Inventor automatisieren: Programmieren für Konstrukteure (Teil 17)

Teil 16 verpasst? Dann hier weiter!

Alle Beiträge der Serie

Im letzten Teil haben wir uns einige Codebeispiele angeschaut. Heute gehen wir durch die Komponenten einer Baugruppe. Mit in Baugruppen verbauten Dateien haben wir uns schon mehrfach beschäftigt (Hier auch ein Bespiel, bei dem es um den Export von Abwicklungen aus Blechteilen in einer IAM geht). Wir haben auf die referenzierten Dateien in der Baugruppe zurück gegriffen mittels:

oDoc.ReferencedDocuments
oDoc.AllReferencedDocuments

Dabei bekommen wir alle verbauten Dateien in einer IAM und zwar jede Komponente einmal! Ist also in einer IAM ein Bauteil mehrfach verbaut, wird es mittels ReferencedDocuments nur einmal "abgerufen". In dieser Baugruppe sind manche Bauteile wie die Schrauben mehrfach verbaut, was dazu führt, das in der IAM zwar nur 14 Dateien aber 21 Komponenten enthalten sind.

image

Die in einer IAM enthaltenen Komponenten sind die einzelnen Einträge im Browserbaum. Wenn wir also durch die Komponenten gehen, ist es so, also würden wir Schritt für Schritt durch den Baum gehen wobei auch mehrere gleichen Komponenten auftauchen können.

image

Schauen wir uns eine IAM mittels unseres Infotools an, finden wir die Komponenten in dieser IAM unter

ComponentDefinition > Occurrences

image

Anders als bei den ReferencedDocuments und AllReferencedDocuments wo entweder auf die Dateien der Hauptbaugruppenebene (ReferencedDocuments) oder alle in der IAM, also auch indirekt über die Unterbaugruppen enthaltenen Dateien (AllReferencedDocuments) zugegriffen werden kann, enthalten die Occurrences nur die Dateien der Baugruppe, auf die wir gerade zugreifen.

Im Bild oben sieht man unter Occurrences die Eigenschaft Count = 12 was den 12 Komponenten der ersten Ebene im Bild des Browserbaumes weiter oben entspricht.

Mit unserem ersten Programmbeispiel gehen wir durch alle Komponenten (Occurrences) und gegeben von jeder Einzelkomponente (Occurrence) den Name aus im Direktfenster.

image

Public Sub IAM_Occurrences()
Dim oDoc As AssemblyDocument
Set oDoc = ThisApplication.ActiveDocument

'Alle Occurences in der IAM
Dim Occurrences As ComponentOccurrences
Set Occurrences = oDoc.ComponentDefinition.Occurrences
'eine Occurences innerhalb aller Occurences
Dim Occurrence As ComponentOccurrence
'Gehen durch alle Occurrences der IAM und gibt den Name aus
For Each Occurrence In Occurrences
    Debug.Print Occurrence.Name
Next
End Sub

Mit diesem Programm können wir nun schon durch die ersten Baugruppenebene durch alle Komponente gehen und sie verwenden und sei es nur, das wir uns den Name ausgeben lassen.

Jetzt haben wir aber ein kleines Problem, wenn wir nicht nur die Komponenten der ersten Ebene ausgeben wollen, sondern uns auch durch alle Unterbaugruppe (und deren Unterbaugruppe usw.) hangeln wollen. Wir müssen dann bei jeder Occurrence prüfen, ob es eine IAM ist und dann in diese IAM einsteigen, deren Occurrences durchgehen und sollte wieder eine IAM dabei sein, dort rein gehen, alle Occurrences durchgehen usw usf. Das ist mit einer verschachtelten Schleife in einer Schleife in einer Schleife nicht zu machen, denn wie wollen wir da verschachtelte IAMs angehen, wenn wir nur z.B. 10 Ebenen anschauen, die IAM aber eine Tiefe von 15 Ebenen hätte? Problem klar? Ich hoffe.

Lösung: Wir rufen aus dem Hauptprogramm ein Unerprogramm auf, dem wir als Parameter alle Occurrences der aktuelle IAM übergeben. Ist nun eine er Occurrence (aus den Occurrences) eine IAM, rufen wir wieder das Unterprogramm auf und übergeben ihr dieses Unterbaugruppen-Occurrence (und ist darin wieder eine IAM ruft diese wieder das Unterprogramm auf usw. usf.)

image

image ==> image

Ist vielleicht jetzt zu Beginn etwas kompliziert, aber wenn ihr das ein bisschen durchdenkt, werden ihr es verstehen, da bin ich mir sicher.

Public Sub IAM_COMP_infos()
Dim oAsmDoc As AssemblyDocument
Set oAsmDoc = ThisApplication.ActiveDocument
'Anstatt nun direkt durch die Occurrences zu gehen
'übergeben wir die Occurrences (alle Komponenten) an eine andere Sub
Call TraverseAssembly(oAsmDoc.ComponentDefinition.Occurrences)
End Sub
Private Sub TraverseAssembly(Occurrences As ComponentOccurrences)
    Dim Occurrence As ComponentOccurrence
    For Each Occurrence In Occurrences
        Debug.Print Occurrence.Name
        'Ist die Occurrence eine Baugruppe, ruft wir diese Sub ebenfalls auf
        'Die SUB ruft also sich selbst auf und ggf. wieder und wieder
        'bis sie durch die IAM Unterstruktur durch ist auf der untersten Eben
        'und geht dann weiter in der nächste Ebene
        If Occurrence.DefinitionDocumentType = kAssemblyDocumentObject Then
            Call TraverseAssembly(Occurrence.SubOccurrences)
        End If
    Next
End Sub

Stellt sich die Frage, wann brauche ich ReferencedDocuments und wann Occurences? Wenn es darum geht, etwas mit der in der IAM enthaltenen Datei zu machen (Zeichnung suchen und drucken, Blech suchen und Abwicklung exportieren), also Dinge, die auch mit der Datei selbst (wenn du sie separat öffnest) machen kannst, ist ReferencedDocuments super.

Willst du was mit einem Browserelement machen (Komponente tauschen, Abhängigkeit einer Komponte ändern, Adaptivität/Unterdrückung/Sichtbarkeit/… einer Komponenten ändern) betrifft das immer einen Browserknoten und ist nicht Sache der Datei selbst. Dann sind die Occurences der richtige Weg.

Baugruppenstruktur in CSV exportieren

Und hier noch eine praktische Anwendung. Export der Baugruppenstruktur in eine IAM.

image

Das steckt auch das Arbeiten mit Textdateien mit drin (eine csv-Datei ist nichts anderes als eine Textdatei mit einer bestimmte Struktur). Versucht, das Beispiel zu verstehen und probiert ein bisschen damit herum!

Public Sub WriteAssemblyStructure()
'Quelle: http://modthemachine.typepad.com/my_weblog/2010/01/exporting-assembly-structure-to-excel.html
'Leicht abgeändert von JW 29092013
    ' Check that an assembly is open.
    Dim asmDoc As AssemblyDocument
    Dim docType As DocumentTypeEnum
    docType = ThisApplication.ActiveDocumentType
    If docType <> kAssemblyDocumentObject Then
        MsgBox "An assembly must be active."
        Exit Sub
    Else
        Set asmDoc = ThisApplication.ActiveEditDocument
    End If

    ' Get the name of the file to create.
    Dim csvFilename As String
    Dim saveDialog As FileDialog
'    Call ThisApplication.CreateFileDialog(saveDialog)
'    With saveDialog
'        .Filter = "CSV (Command delimited)(*.csv)|*.csv"
'        .DialogTitle = "Specify output filename"
'        .OptionsEnabled = False
'        .SuppressResolutionWarnings = True
'        .ShowSave
'
'        If .FileName = "" Then
'            Exit Sub
'        Else
'            csvFilename = .FileName
'        End If
'    End With

csvFilename = Environ("HOMEPATH") & "\" + Left$(asmDoc.DisplayName, Len(asmDoc.DisplayName) - 4) + ".csv"
'If Dir(Environ("IVFAQToolbox_Neutralformate")) = "" Then MkDir Environ("IVFAQToolbox_Neutralformate")
    ' Open the file.
    Dim FilePointer As Integer
    FilePointer = FreeFile
    Open csvFilename For Output As #FilePointer

    ' Write the top-level assembly name.
    Print #FilePointer, asmDoc.DisplayName & ";" & _
          asmDoc.FullFileName

    ' Read through the assembly and write the structure out.
    Call WriteStructure(asmDoc.ComponentDefinition.Occurrences, _
                        1, FilePointer)

    ' Close the file.
    Close #FilePointer

    MsgBox "Datei erstellt auf Desktop: " & vbCr & csvFilename
    Shell "explorer.exe """ & csvFilename & "", vbNormalFocus
End Sub



Private Sub WriteStructure( _
            ByVal Occurrences As ComponentOccurrences, _
            ByVal Level As Integer, _
            ByVal FilePointer As Integer)

    ' Iterate through the occurrences in the current level.
    Dim occ As ComponentOccurrence
    For Each occ In Occurrences
        ' Write information for this occurrence to the file.
        If occ.IsSubstituteOccurrence = True Or occ.Suppressed = True Then GoTo naechste
        Print #FilePointer, String$(Level, ";") & _
              occ.Name & ";" & occ.Definition.Document.FullFileName

        ' If this occurrence is a subassembly iterate
        ' over its occurrences.
        If occ.DefinitionDocumentType = kAssemblyDocumentObject Then
            Call WriteStructure(occ.SubOccurrences, Level + 1, _
                                FilePointer)
        End If
naechste:
    Next
End Sub

 

Leaf Occurrences

Neben den ReferencedDocuments und den Occurences gibt es noch die Leaf Occurrences, die alle Bauteile in der gesamte Baugruppenstruktur abrufen. Im Beispiel unten seht ihr das in der Ausgabe nur Bauteil sind, allerdings aus der gesamten IAM-Struktur. Den Quelltext dazu findet ihr im Link unten!

image

Brian Ekins hat diese 3 Konzepte in seinem Blog übrigens besser (und professioneller ;) ) beschrieben, als ich es jemals könnten. Wenn ihr meinen kleinen Beitrag verstanden habt, schaut euch seinen Beitrag an, um das Thema zu vertiefen!

Weiter zu Teil 18

Kommentare:

  1. Schöner Artikel, aber wie genau kann ich ein Element später verwenden? Angenommen ich lasse mir alle Elemente in einer Form ausgeben die unterdrückt sind. nun möchte ich eines dieser Elemente nicht mehr unterdrückt haben, ich möchte das gerne mit einer Checkbox lösen, klicke ich die checkbox des jeweiligen elementes soll die unterdrückung für dieses explizite element aufgehoben werden. Das setzt aber voraus das er ja irgendwo eine Id gespeichert hat auf die er hier zurückgreift um das ELement zu finden.

    Wäre schön wenn du das in deinem nächsten Artikel vielleicht aufgreifen könntest.

    Danke und Gruß
    Markus

    AntwortenLöschen
    Antworten
    1. Hallo Markus,
      Geht es dir um die Komponenten in der Hauptbaugruppenebene (also die, die direkt in der aktuellen IAM verbaut sind)? Dann nutze die Name-Eigenschaft. In der IAM muss jeder Baumeintragname eindeutig sein, deswegen werden die auch nummeriert bei gleichen Teilen also XXXX:1, XXXX:2 usw.
      Rest schaue ich mir an.

      Löschen
    2. Danke schonmal für die Antwort. Mir geht es um jegliches Finden von Komponenten in allen Ebenen. Ich denke das man das hier über den Internalname machen muss. die Uniqid sozusagen die ein eindeutig ist. Nur wie stellt man das an?

      Danke schonmal. Gibt es eine Möglichkeit mit dir in Kontakt zu treten via Email oder Skype oder Google hangouts?

      Löschen
    3. Da wirst du aber auch die Baugruppe brauchen, in der die Komponente enthalten ist. Fragen stellst du am besten in den entsprechenden Foren bei Autodesk oder cad.de. Ich würde hier mein Glück probieren.
      https://forums.autodesk.com/t5/inventor-customization/bd-p/120

      Löschen
  2. Hi Jürgen ich wollte eigentlich mit dir in Kontakt treten bezüglich deines Blogs, darf man direkt zu dir verlinken, oder eigene RSS in eigene Artikel einbinden etc. Hab dir mal eine Anfrage auf google hangouts geschickt um weiteres ggfs. besprechen zu können.

    Gruß

    AntwortenLöschen
    Antworten
    1. Dieser Kommentar wurde vom Autor entfernt.

      Löschen
    2. Kontakt über Emailadresse im Impressum. Bloginhalte verwenden: https://inventorfaq.blogspot.de/2012/09/inhalte-aus-der-inventor-faq-kopieren.html

      Löschen

War der Beitrag hilfreich oder hast du eine Ergänzung dazu?
Ist noch eine Frage offen?
Ich freue mich auf deine Rückmeldung!

Related Posts Plugin for WordPress, Blogger...
Inventor FAQ Newsletter. Emailadresse: