Hot News:

Mit Unterstützung durch:

  Foren auf CAD.de (alle Foren)
  AutoCAD ObjectARX und .NET
  Blöcke per Blocktablerecord einlesen und bearbeiten

Antwort erstellen  Neues Thema erstellen
CAD.de Login | Logout | Profil | Profil bearbeiten | Registrieren | Voreinstellungen | Hilfe | Suchen

Anzeige:

Darstellung des Themas zum Ausdrucken. Bitte dann die Druckfunktion des Browsers verwenden. | Suche nach Beiträgen nächster neuer Beitrag | nächster älterer Beitrag
  
Gut zu wissen: Hilfreiche Tipps und Tricks aus der Praxis prägnant, und auf den Punkt gebracht für Autodesk Produkte
Autor Thema:  Blöcke per Blocktablerecord einlesen und bearbeiten (2082 mal gelesen)
ManuelKuhn
Mitglied
Techniker und DvD :-)


Sehen Sie sich das Profil von ManuelKuhn an!   Senden Sie eine Private Message an ManuelKuhn  Schreiben Sie einen Gästebucheintrag für ManuelKuhn

Beiträge: 100
Registriert: 23.03.2005

Intel XEON W3503 @ 2.4GHz
8 GB DDR3
NVIDIA QUADRO FX3800
WinXP Prof SP3 x64
ACAD 2007 + ProSteel 17.2/ 18
ACAD 2010 + ProSteel V8i S3
Rhino 3D V4
Autodesk VIZ-2006
Max2011 Design
Visual Studio 2008

erstellt am: 24. Mrz. 2011 08:34    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

Moin Moin zusammen,

ich hänge hier irgendwie an einem Problem, wo ich nicht weiterkomme....

Folgender Sachverhalt:
Ich habe vor, alle Blöcke in allen Layouts einzulesen, die Doppelten auszufiltern, dann die vorhandenen Attribute zu bearbeiten und die Änderungen in die entsprechenden Blöcke zurück zu schreiben. Bisher gehe ich so vor, dass ich mir die Blöcke in einem "Listview" anzeigen lasse, der User wählt dann den gewünschten Block aus, diesen Blocknamen übergebe ich dann an ein neues Formular, das wiederrum die Zeichnung nach dem gewählten Blocknamen durchsucht und dann die enthaltenen Attribute und ihre Werte in einem "DataGridView" darstellen soll, nun kann der User diese dort bearbeiten und anschließen die Änderungen speichern.

Das einlesen der Blocknamen ins Listview klappt ohne Probleme über folgenden Code:
(Der Filter für die Doppelten Definitionen fehlt noch)


Code:

Private Sub frmMainDialoge_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
   
        Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument

            Dim acCurDb As Database = acDoc.Database

            Using acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

            Dim bt As BlockTable

            bt = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)

            For Each Acadid As ObjectId In bt

                Dim dbobj As Autodesk.AutoCAD.DatabaseServices.DBObject = acTrans.GetObject _
                                                                    (Acadid, OpenMode.ForRead)

                Dim btr As BlockTableRecord = TryCast(dbobj, BlockTableRecord)

                If btr.IsLayout = False Then

                    Me.lstBBlocks.Items.Add(btr.Name)

                End If

                dbobj.Dispose()

            Next

            bt.Dispose()

        End Using

    End Sub



Die Übergabe an das neue Formular, mache ich über eine Settingsvariable, da ich irgendwie keine andere Möglichkeit gefunden habe. Es gibt wohl die Möglichkeit, das ganze über ein "Overloads Sub" zu machen, das funktioniert aber nur, wenn das Projekt ein "Windows-Forms" Projekt ist und keine
"Class Library"...


Code:

Private Sub btnEdit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnEdit.Click

    If lstBBlocks.SelectedIndex = -1 Then
        MsgBox("Please choose Block to edit!", MsgBoxStyle.Information, "Info")
        Exit Sub
    End If

    My.Settings.selitem = lstBBlocks.SelectedItem

    Dim frmProbs As New frmPropbs

    frmProbs.ShowDialog()

End Sub



Hier, im neuen Formular, kommt nun mein Problem; ich durchsuche ja nun die Zeichnungsdatenbank nochmals, um den entsprechenden Block mit dem gewählten Namen zu finden um anschließend seine Attribute in mein "DataGridView" zu schreiben (Momentan gebe ich mir zum Testen nur eine Messagebox mit dem Tag aus), allerdings bekomme ich das irgendwie nicht hin... hier der Code:


Code:

Private Sub frmProbs_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim acDoc As Document = Application.DocumentManager.MdiActiveDocument
    Dim acCurDb As Database = acDoc.Database

    Dim acTrans As Transaction = acCurDb.TransactionManager.StartTransaction()

    Dim bt As BlockTable
    Dim AcadBlkRef As BlockReference
    Dim AcadAttCol As AttributeCollection
    Dím AcadAttID As ObjectId
    Dim AcadAttRef As AttributeReference
    Dim BlockId As ObjectId
    Dim btr As New BlockTableRecord

    Try

    bt = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead)

    For Each AcadId As ObjectId In bt

        Dim dbobj As Autodesk.AutoCAD.DatabaseServices.DBObject = acTrans.GetObject _
                                                            (AcadId, OpenMode.ForRead)

        btr = DirectCast(acTrans.GetObject(AcadId, OpenMode.ForRead), BlockTableRecord)

        If btr.Name = My.Settings.selitem Then

            BlockId = AcadId

            Exit For

        Else : End If

    Next
       
    btr.Dispose()

    AcadBlkRef = acTrans.GetObject(BlockId, OpenMode.ForRead)

    AcadAttCol = AcadBlkRef.AttributeCollection

    For Each AcadAttID In AcadAttCol

        AcadAttRef = DirectCast(acTrans.GetObject(AcadAttID, OpenMode.ForRead), _
                                                              AttributeReference)

        MsgBox(AcadAttRef.Tag)

    Next

    bt.Dispose()

    acTrans.Commit()

    Catch ex As Autodesk.AutoCAD.Runtime.Exception

        MsgBox("Exception: " + ex.Message)

    Finally

        acTrans.Dispose()

    End Try

End Sub



Beim Punkt "AcadBlkRef = acTrans.GetObject(BlockId, OpenMode.ForRead)" fliege ich immer raus, mit dem Fehler:

Zitat:
Unable to cast object of type 'Autodesk.AutoCAD.DatabaseServices.BlockTableRecord' to type 'Autodesk.AutoCAD.DatabaseServices.BlockReference'.

mir ist schon irgendwie klar, was passiert... die Variable BlockId kommt ja aus meinem "Blocktablerecord", aber sie stellt doch nur die ID dar, welche ich hier meiner BlockReferenz zuweisen will, ich werd da nicht schlau draus...

Hoffe jemand hat ne Idee für mich...

Grüße
Manu

PS: Sorry, ich weiß es ist viel zu lesen, aber ich hab mir gedacht, ich schreibe den kompletten zusammenhang, dass es verständlicher ist, wo was herkommt.

------------------
Etwaige Rechtschreibfehler sind gewollt und dienen der allgemeinen Belustigung 

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Brischke
Moderator
CAD on demand GmbH




Sehen Sie sich das Profil von Brischke an!   Senden Sie eine Private Message an Brischke  Schreiben Sie einen Gästebucheintrag für Brischke

Beiträge: 4171
Registriert: 17.05.2001

AutoCAD 20XX, defun-tools

erstellt am: 24. Mrz. 2011 12:14    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities Nur für ManuelKuhn 10 Unities + Antwort hilfreich

Hallo ManuelKuhn.

es ist, wie die Fehlermeldung schon sagt: Du hast die Id eines BlockTableRecords (Blockdefinition) und willst diese casten zu einer Blockreferenz(Insert). Das funzt nicht.

Du kannst die BlockReferenzen aus dem geöffneten BlocktableRecord mit der Methode GetReferences (oder so ähnlich) ermitteln. Dann hast du alle ID's der Blockreferenzen.

Bei Fragen ...

Grüße Holger

------------------
Holger Brischke
CAD on demand GmbH
Individuelle Lösungen von Heute auf Morgen.


defun-tools Das Download-Portal für AutoCAD-Zusatzprogramme!

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

ManuelKuhn
Mitglied
Techniker und DvD :-)


Sehen Sie sich das Profil von ManuelKuhn an!   Senden Sie eine Private Message an ManuelKuhn  Schreiben Sie einen Gästebucheintrag für ManuelKuhn

Beiträge: 100
Registriert: 23.03.2005

Intel XEON W3503 @ 2.4GHz
8 GB DDR3
NVIDIA QUADRO FX3800
WinXP Prof SP3 x64
ACAD 2007 + ProSteel 17.2/ 18
ACAD 2010 + ProSteel V8i S3
Rhino 3D V4
Autodesk VIZ-2006
Max2011 Design
Visual Studio 2008

erstellt am: 25. Mrz. 2011 09:06    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

Guten Morgen Holger,

vielen Dank, das war mir eben irgendwie unklar, ich dachte eigentlich dass dort nur die Objekt ID Übergeben (Quasi der Block) wird!

Ich werds ausprobieren und mich wieder melden!

Schönen Tag noch!

Grüße
Manu

------------------
Etwaige Rechtschreibfehler sind gewollt und dienen der allgemeinen Belustigung 

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

ManuelKuhn
Mitglied
Techniker und DvD :-)


Sehen Sie sich das Profil von ManuelKuhn an!   Senden Sie eine Private Message an ManuelKuhn  Schreiben Sie einen Gästebucheintrag für ManuelKuhn

Beiträge: 100
Registriert: 23.03.2005

Intel XEON W3503 @ 2.4GHz
8 GB DDR3
NVIDIA QUADRO FX3800
WinXP Prof SP3 x64
ACAD 2007 + ProSteel 17.2/ 18
ACAD 2010 + ProSteel V8i S3
Rhino 3D V4
Autodesk VIZ-2006
Max2011 Design
Visual Studio 2008

erstellt am: 31. Mrz. 2011 08:34    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

Hallo zusammen,

habe das ganze hinbekommen, wollte nur kurz den Code posten, falls es mal jemand gebrauchen kann!    

Code:

Private Sub frmProbs_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    Dim acDoc As Document = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument
    Dim acCurDb As Database = acDoc.Database
    Dim AcadAttCol As AttributeCollection
    Dim AcadAttID As ObjectId
    Dim AcadAttRef As AttributeReference
    Dim BlockId As ObjectId
    Dim btr As New BlockTableRecord
    Dim db As Database = HostApplicationServices.WorkingDatabase
    Dim tm As Autodesk.AutoCAD.DatabaseServices.TransactionManager
    Dim blkRef As BlockReference = Nothing
    Dim btrblock As New BlockTableRecord
    Dim checkVal As Boolean

    checkVal = False
    tm = db.TransactionManager

    Try

        Using tr As Transaction = tm.StartTransaction()

            Try

                Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, _
                                             OpenMode.ForRead, False), BlockTable)

                For Each AcadId As ObjectId In bt

                    btr = DirectCast(tr.GetObject(AcadId, OpenMode.ForRead, False), _
                                                                     BlockTableRecord)

                    For Each BlockId In btr

                        Dim blkrefObj As DBObject = DirectCast(tr.GetObject(BlockId, _
                                                           OpenMode.ForRead), DBObject)

                        blkRef = TryCast(blkrefObj, BlockReference)

                        If blkRef IsNot Nothing Then

                            Dim btrBlockID As ObjectId = blkRef.BlockTableRecord

                            btrblock = DirectCast(tr.GetObject(btrBlockID, _
                                             OpenMode.ForRead), BlockTableRecord)

                            If btrblock.Name = My.Settings.selitem Then

                                checkVal = True

                                GoTo Exit_For

                            Else : End If

                        End If

                    Next

                Next

Exit_For:
                If checkVal = True Then

                    Me.Text = btrblock.Name

                    AcadAttCol = blkRef.AttributeCollection

                    Dim subObj As DBObject

                    For Each AcadAttID In AcadAttCol

                        subObj = DirectCast(tr.GetObject(AcadAttID, OpenMode.ForRead), _
                                                                                DBObject)

                        AcadAttRef = DirectCast(subObj, AttributeReference)

                        If AcadAttRef Is Nothing Then

                            MsgBox("No Attributes found!", MsgBoxStyle.Critical, "ERROR")

                        Else

                            gridView.Rows.Add(AcadAttRef.Tag, AcadAttRef.TextString)

                            AcadAttRef.Dispose()

                        End If

                        subObj.Dispose()

                    Next

                    blkRef.Dispose()

                    btrblock.Dispose()

                    btr.Dispose()

                Else : End If

            Finally

                tr.Dispose()

            End Try

        End Using

    Finally

    End Try

End Sub


------------------
Etwaige Rechtschreibfehler sind gewollt und dienen der allgemeinen Belustigung    

[Diese Nachricht wurde von ManuelKuhn am 31. Mrz. 2011 editiert.]

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP


Ex-Mitglied

erstellt am: 31. Mrz. 2011 09:51    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat

Hi,

danke, dass Du den Code gepostet hast; ein gutes Beispiel für 'Sinn eines Forums voll verstanden'! 

Und gleich eine Korrektur (siehe es als Empfehlung, nicht als Kritik!) Ich glaube nur, dass Du bei großen DWG's ziemlich langsam sein wirst mit dem Durchscannen durch die ganze Zeichnungsdatenbank.

Mein Ansatz daher grob/verbal:

BlockTable durchscannen nach eine BlockDefinition mit dem gesuchten Namen
Haben wir die Blockdefinition (BlockTableRecord), dann hat diese eine eigene Funktion, abgeleitete BlockReferenzen zu finden, und fertig, da bist Du schon. 

Code:
tm = db.TransactionManager

Try
  Using tr As Transaction = tm.StartTransaction()
    Try
      Dim tBlRefIDs As ObjectIdCollection = Nothing
      Dim bt As BlockTable = DirectCast(tr.GetObject(db.BlockTableId, OpenMode.ForRead, False), BlockTable)
      For Each AcadId As ObjectId In bt
        'erst mal pruefen, ob diese ObjektID nicht als 'gelöscht' markiert ist
        If (AcadId.IsValid) AndAlso (Not AcadId.IsErased) Then
          'hier werden die Blockdefinitionen durchgescannt, um zur gesuchten BlockDefinition zu kommen
          btr = DirectCast(tr.GetObject(AcadId, OpenMode.ForRead, False), BlockTableRecord)
          If btr.Name = My.Settings.selitem Then
            Me.Text = btr.Name
            'nun haben wir die Blockdefinition, die wir suchen
            'aus dem holen wir die IDs der eingefügten BlockReferenzen
            tBlRefIDs = btr.GetBlockReferenceIds(False, True)
            Exit For
          End If
        End If
      Next

      'und jetzt können wir die BlockReferenzen direkt durchgehen (ohne alles durchzuscannen)
      If (tBlRefIDs IsNot Nothing) AndAlso (tBlRefIDs.Count > 0) Then
        For Each tBlRefID As ObjectId In tBlRefIDs
          Dim tBlRef As BlockReference = CType(tr.GetObject(tBlRefID, OpenMode.ForRead), BlockReference)
          AcadAttCol = blkRef.AttributeCollection
          For Each AcadAttID In AcadAttCol
            AcadAttRef = DirectCast(tr.GetObject(AcadAttID, OpenMode.ForRead), AttributeReference)
            If AcadAttRef Is Nothing Then  'kann es eigentlich nicht sein
              MsgBox("No Attributes found!", MsgBoxStyle.Critical, "ERROR")
              'hier solltest Du, wenn Du schon darauf pruefst, ein EXIT FOR einbauen
              '  sonst bekommt der User Anfälle, wenn er in einer Schleife die Meldung 1000 mal bekommt
            Else
              gridView.Rows.Add(AcadAttRef.Tag, AcadAttRef.TextString)
              'das bitte nicht: AcadAttRef.Dispose()
            End If
          Next
        Next
      End If
    Catch ex2 As Exception
      MsgBox("Fehler aufgetreten (ErrPos=2)" & vbNewLine & ex2.Message)
    Finally
      'das bitte nicht, wenn Du mit 'Using TR ...' arbeitest, dann macht das schon .Dispose 
      '        tr.Dispose()
    End Try
  End Using
Catch ex As Exception
  MsgBox("Fehler aufgetreten (ErrPos=1)" & vbNewLine & ex.Message)
End Try



Code ungetestet, ich hab ja Deine Form-Controls nicht.    Aber es geht mehr um den Sinn.

Viel Erfolg, - alfred -

------------------
www.hollaus.at

ManuelKuhn
Mitglied
Techniker und DvD :-)


Sehen Sie sich das Profil von ManuelKuhn an!   Senden Sie eine Private Message an ManuelKuhn  Schreiben Sie einen Gästebucheintrag für ManuelKuhn

Beiträge: 100
Registriert: 23.03.2005

Intel XEON W3503 @ 2.4GHz
8 GB DDR3
NVIDIA QUADRO FX3800
WinXP Prof SP3 x64
ACAD 2007 + ProSteel 17.2/ 18
ACAD 2010 + ProSteel V8i S3
Rhino 3D V4
Autodesk VIZ-2006
Max2011 Design
Visual Studio 2008

erstellt am: 31. Mrz. 2011 20:32    Editieren oder löschen Sie diesen Beitrag!  <-- editieren / zitieren -->   Antwort mit Zitat in Fett Antwort mit kursivem Zitat    Unities abgeben: 1 Unity (wenig hilfreich, aber dennoch)2 Unities3 Unities4 Unities5 Unities6 Unities7 Unities8 Unities9 Unities10 Unities

Zitat:
Original erstellt von a.n.:
Hi,

danke, dass Du den Code gepostet hast; ein gutes Beispiel für 'Sinn eines Forums voll verstanden'!  

Und gleich eine Korrektur (siehe es als Empfehlung, nicht als Kritik!) Ich glaube nur, dass Du bei großen DWG's ziemlich langsam sein wirst mit dem Durchscannen durch die ganze Zeichnungsdatenbank.


Hi Alfred,

danke für die "Blumen"  so sollte es meiner Meinung nach auch sein!

Versteh ich nicht als Kritik (wobei konstruktive Kritik immer gut ist, denn "Nobody is perfekt") ich bin immer auf der Suche, meinen Code besser und Sinnvoller zu gestalten, vorallem effektiver! Ich werds auf jeden Fall versuchen und entsprechen implementieren!

Grüße
Manu

------------------
Etwaige Rechtschreibfehler sind gewollt und dienen der allgemeinen Belustigung 

Eine Antwort auf diesen Beitrag verfassen (mit Zitat/Zitat des Beitrags) IP

Anzeige.:

Anzeige: (Infos zum Werbeplatz >>)

Darstellung des Themas zum Ausdrucken. Bitte dann die Druckfunktion des Browsers verwenden. | Suche nach Beiträgen

nächster neuerer Beitrag | nächster älterer Beitrag
Antwort erstellen


Diesen Beitrag mit Lesezeichen versehen ... | Nach anderen Beiträgen suchen | CAD.de-Newsletter

Administrative Optionen: Beitrag schliessen | Archivieren/Bewegen | Beitrag melden!

Fragen und Anregungen: Kritik-Forum | Neues aus der Community: Community-Forum

(c)2023 CAD.de | Impressum | Datenschutz