Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: Help with deleting multiple copies of blocks (not anon) with selection set

  1. #1
    Member
    Join Date
    2010-08
    Posts
    40
    Login to Give a bone
    0

    Default Help with deleting multiple copies of blocks (not anon) with selection set

    As part of a larger routine ive inserted multiple copies of four different blocks (all named, none anon), so now im trying to delete them all at once when im done with them. so i figured create a selection set, the erase. im i going about it all wrong? heres the code for the eraser so far:
    Code:
    Private Sub eraser()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim mytvs(3) As TypedValue
                mytvs(3) = New TypedValue(2, "Standard")
                mytvs(3) = New TypedValue(2, "Compact")
                mytvs(3) = New TypedValue(2, "Handicap")
                mytvs(3) = New TypedValue(2, "Van")
                Dim myfilter As New SelectionFilter(mytvs)
                Dim mypsr As PromptSelectionResult = ed.SelectAll(myfilter)
                If mypsr.Status = PromptStatus.OK Then
                    Dim sset As SelectionSet = mypsr.Value
                    Dim bt As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
                    Dim btr As BlockTableRecord = bt(sset.GetObjectIds.ToString).GetObject(OpenMode.ForRead)
                    For Each obid As ObjectId In btr.GetBlockReferenceIds(True, True)
                        Dim ent As Entity = obid.GetObject(OpenMode.ForWrite)
                        ent.Erase()
                    Next
                End If
                tr.Commit()
            End Using
        End Sub
    i think the highlited portion is the problem.

  2. #2
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,719
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    Rather than attempting to create a selection set of the blocks added to the Database during your Transaction's Using statement (because you only need one Transaction), testing that the selection set is valid, iterating the selection set, and deleting each ObjectId... Perhaps it would be simpler to instead just store the Block's ObjectId to an IEnumerable, public static List<ObjectId>, or public static List<Entity> Property Object at the time the Block's are added to the Database, that can then be used to 'clean up' after the fact?
    Last edited by RenderMan; 2012-10-19 at 12:58 AM.
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  3. #3
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,719
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    In the event the C# jargon doesn't make sense:

    Pseudo-code (C#):
    Code:
    public static List<ObjectId> myBlocks { get; set; }
    Pseudo-code (VB.NET, converted using developerFusion):
    Code:
    Public Shared Property myBlocks() As List(Of ObjectId)
        Get
            Return m_myBlocks
        End Get
        Set
            m_myBlocks = Value
        End Set
    End Property
    Private Shared m_myBlocks As List(Of ObjectId)
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  4. #4
    I could stop if I wanted to
    Join Date
    2007-08
    Posts
    202
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    Hi,

    I agree with RenderMan, the best way is to store the BlockReference ObjectIdS in a collection (ObjectIdCollection) when they're added to the Database. But there's no need to use a class property as the ObjectIdCollection won't be got from outside of the class, a private field would do the trick (and don't set the field static/Shared which means per session rather than per document).

    If you want to keep on the SelectionSet route, change your selection filter building to :
    Code:
                Dim mytvs(1) As TypedValue
                mytvs(0) = New TypedValue(0, "INSERT")
                mytvs(1) = New TypedValue(2, "Standard,Compact,Handicap,Van")
                Dim myfilter As New SelectionFilter(mytvs)
    And don't use the BlockTableRecord.GetBlockReferenceIds() method, just iterate the Selection set :
    Code:
                    Dim sset As SelectionSet = mypsr.Value
                    For Each obid As ObjectId In sset.GetObjectId()
                        Dim ent As Entity = obid.GetObject(OpenMode.ForWrite)
                        ent.Erase()
                    Next
    If you want to go on the BlockTableRecord.GetBlockReferenceIds() method, you do not need a selection set, iterate the BlockTable looking for BlockTableRecord which Name matches the ones you're looking for, the get the references ObjectId, open them and erase them.

  5. #5
    Member
    Join Date
    2010-08
    Posts
    40
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    I'm definetly open to not using a selection set. hrmm so your saying create an objectidcollection within my block insertion sub, then pass that collection to the eraser sub? Insertion and deletion are performed with seperate button click events if that matters.

  6. #6
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,719
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    Quote Originally Posted by 'gile' View Post
    But there's no need to use a class property as the ObjectIdCollection won't be got from outside of the class, a private field would do the trick (and don't set the field static/Shared which means per session rather than per document).
    Perhaps my logic is flawed (I am still only learning)... How is using a non-static (per-Document) Field better, more efficient, etc. than using a single static List<ObjectId>, which in theory *should* invoke the Add() Method at the time the BlockReference is added to the Database, and invokes the Remove() Method when done (perhaps in a Finally block?)...???

    Quote Originally Posted by cmccartney View Post
    I'm definetly open to not using a selection set. hrmm so your saying create an objectidcollection within my block insertion sub, then pass that collection to the eraser sub? Insertion and deletion are performed with seperate button click events if that matters.
    So long as the ObjectId Collection remains in scope (which it *should*, if you're passing it as a parameter)... Yes, that is correct (AFAIK).
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  7. #7
    I could stop if I wanted to
    Join Date
    2007-08
    Posts
    202
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    If your insertion sub and your eraser sub are within the same class (as they should), within this class you can define a private field in this class (out of any method). This field can be considered as global variable within the class and can be accessed by both subs.

    Code:
    Public Class Dialog
    
        Private blocks As ObjectIdCollection
    
        Private Sub btnInsert_Click(sender As Object, e As EventArgs) Handles btnInsert.Click
            ' ...
            Dim id As ObjectId = modelSpace.AppendEntity(blockRef)
            blocks.Add(id)
            ' ...
        End Sub
    
        Private Sub btnErase_Click(sender As Object, e As EventArgs) Handles btnErase.Click
            ' ...
            For Each id As ObjectId In blocks
                Dim br As BlockReference = id.GetObject(OpenMode.ForWrite)
                br.Erase()
            Next
            blocks.Clear()
            ' ...
        End Sub
    
        ' ...
    End Class

  8. #8
    I could stop if I wanted to
    Join Date
    2007-08
    Posts
    202
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    Perhaps my logic is flawed (I am still only learning)... How is using a non-static (per-Document) Field better, more efficient, etc. than using a single static List<ObjectId>, which in theory *should* invoke the Add() Method at the time the BlockReference is added to the Database, and invokes the Remove() Method when done (perhaps in a Finally block?)...???
    I'll try to explain my point.
    Firstly, I think it's not necessary to define a property as long as the data won't be used from outside of the class. A class field is sufficient. This field may be any type which suits the purpose: a List<ObjectId> (List(Of ObjectId) in VB) or an ObjectIdCollection.
    Secondly I think it is not a good practice to use the static (Shared in VB) modifier when there's no need too (whatever the modifier applies to: field or property). Mostly, in this case where dealing with ObjectId which are document resident.

    Try this little snippet, in a drawing run TEST1 and TEST2, in the same session, if you open a new drawing and run TEST2 (whatever you've run TEST1 or not in this session) an exception will occur.

    Code:
    using Autodesk.AutoCAD.ApplicationServices;
    using Autodesk.AutoCAD.DatabaseServices;
    using Autodesk.AutoCAD.EditorInput;
    using Autodesk.AutoCAD.Runtime;
    
    namespace StaticFieldTest
    {
        public class Commands
        {
            private static ObjectIdCollection staticIds = new ObjectIdCollection();
    
            [CommandMethod("Test1")]
            public void Test1()
            {
                Editor ed = Application.DocumentManager.MdiActiveDocument.Editor;
                PromptEntityResult per = ed.GetEntity("\nSelect an entity: ");
                if (per.Status == PromptStatus.OK)
                    staticIds.Add(per.ObjectId);
            }
    
            [CommandMethod("Test2")]
            public void Test2()
            {
                Database db = HostApplicationServices.WorkingDatabase;
                if (staticIds == null)
                    Application.ShowAlertDialog("Null");
                else
                    foreach (ObjectId id in staticIds)
                    using (Entity ent = (Entity)id.Open(OpenMode.ForWrite))
                    {
                        ent.Highlight();
                    }
            }
        }
    }

  9. #9
    Administrator BlackBox's Avatar
    Join Date
    2009-11
    Posts
    5,719
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    Quote Originally Posted by 'gile' View Post
    I'll try to explain my point.
    Thanks for clarifying, Gile... Great job (as always).
    "How we think determines what we do, and what we do determines what we get."

    Sincpac C3D ~ Autodesk Exchange Apps

    Computer Specs:
    Dell Precision 3660, Core i9-12900K 5.2GHz, 64GB DDR5 RAM, PCIe 4.0 M.2 SSD (RAID 0), 16GB NVIDIA RTX A4000

  10. #10
    Member
    Join Date
    2010-08
    Posts
    40
    Login to Give a bone
    0

    Default Re: Help with deleting multiple copies of blocks (not anon) with selection set

    Hrmm i think i missing something, i was unable to get this to work using either way. although i am thinking selection set my be the way to go afterall as i want to be able to delete these blocks even if they were already in teh drawing at the start of teh acad session (if i started placing, but then interrupted and had to come back later). so heres the insertion code as it stood before i attempted your suggestions. thoughts? and thanks again for the help, i am definetly learning things from this
    Code:
    Imports System
    Imports Autodesk.AutoCAD.Runtime
    Imports Autodesk.AutoCAD.ApplicationServices
    Imports Autodesk.AutoCAD.DatabaseServices
    Imports Autodesk.AutoCAD.Geometry
    Imports Autodesk.AutoCAD.EditorInput
    
    Public Class StallCounterInterface
        Private Sub StallCounterInterface_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Counter()
        End Sub
        Public Sub blocktest(ByVal BlockName As String)
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = doc.Database
            Dim ed As Editor = doc.Editor
            'test if block exists
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim bt As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
                'insert source file if block not found
                If Not bt.Has(BlockName) Then
                    Dim origin As New Point3d(0, 0, 0)
                    Dim filename As String = "C:\mkacadd_Hybrid\Civil3D\CAD data\Support\Blocks\StallCount.dwg"
                    ed.WriteMessage(vbLf & BlockName & " block does not exist, now inserting source file!")
                    Using dbdwg As New Database(False, True)
                        dbdwg.ReadDwgFile(filename, IO.FileShare.Read, True, "")
                        Dim blkid As ObjectId
                        blkid = db.Insert(filename, dbdwg, True)
                        Dim obr As New BlockReference(origin, blkid)
                        Dim obtr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                        obtr.AppendEntity(obr)
                        tr.AddNewlyCreatedDBObject(obr, True)
                        'erases source file
                        obr.Erase(True)
                        tr.Commit()
                    End Using
                End If
            End Using
            'initiate loop for cotninous block placement unitl user cancels
            Dim LoopControl As Boolean = True
            Do While LoopControl
                doc.LockDocument()
                Me.Hide()
                Using tr As Transaction = db.TransactionManager.StartTransaction()
                    Dim bt As BlockTable = tr.GetObject(db.BlockTableId, OpenMode.ForRead)
                    Dim id As ObjectId = bt(BlockName)
                    ' Get insertion point
                    Dim ppo As New PromptPointOptions(vbLf & "Specify insertion point, press [ESC] to return:")
                    Dim ppr As PromptPointResult = ed.GetPoint(ppo)
                    ' Exit if the user presses ESC or cancels the command
                    If ppr.Status = PromptStatus.Cancel Then Exit Do
                    If ppr.Status = PromptStatus.OK Then
                        Dim pts As Point3d = ppr.Value
                        Dim ptstr As New Point2d(ppr.Value.X, ppr.Value.Y)
                        Dim ppor As New PromptPointOptions(vbLf & "Specify Rotation point:")
                        'rubber band to show rotation
                        ppor.UseBasePoint = True
                        ppor.BasePoint = pts
                        Dim pprr As PromptPointResult = ed.GetPoint(ppor)
                        Dim ptend As New Point2d(pprr.Value.X, pprr.Value.Y)
                        ' Create a block reference
                        Dim br As New BlockReference(pts, id)
                        ' Get Model space
                        Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
                        ' Add the block reference to Model space
                        btr.AppendEntity(br)
                        tr.AddNewlyCreatedDBObject(br, True)
                        'Rotate block based on insertion and rotation points
                        Dim curucsmat As Matrix3d = ed.CurrentUserCoordinateSystem
                        Dim curUCS As CoordinateSystem3d = curucsmat.CoordinateSystem3d
                        Dim ang = ptstr.GetVectorTo(ptend).Angle.ToString()
                        Dim rot = Math.Truncate(ang * 10000) / 10000
                        br.TransformBy(Matrix3d.Rotation(rot, curUCS.Zaxis, New Point3d(ppr.Value.X, ppr.Value.Y, 0)))
                        tr.Commit()
                    End If
                End Using
            Loop
            Counter()
            Me.Show()
        End Sub
        Private Sub Counter()
            Dim doc As Document = Application.DocumentManager.MdiActiveDocument
            Dim ed As Editor = doc.Editor
            Dim numS As Integer = 0
            Dim numC As Integer = 0
            Dim numH As Integer = 0
            Dim numV As Integer = 0
            Dim numT As Integer = 0
            Using tr As Transaction = doc.TransactionManager.StartTransaction()
                Dim mytvs(0) As TypedValue
                mytvs(0) = New TypedValue(0, "Insert")
                Dim myfilter As New SelectionFilter(mytvs)
                Dim mypsr As PromptSelectionResult = ed.SelectAll(myfilter)
                If mypsr.Status = PromptStatus.OK Then
                    Dim sset As SelectionSet = mypsr.Value
                    For Each id As ObjectId In mypsr.Value.GetObjectIds
                        Dim br As BlockReference = id.GetObject(OpenMode.ForRead)
                        Select Case br.Name
                            Case "Standard"
                                numS = numS + 1
                            Case "Compact"
                                numC = numC + 1
                            Case "Handicap"
                                numH = numH + 1
                            Case "Van"
                                numV = numV + 1
                            Case Else
                        End Select
                        numT = numS + numC + numH + numV
                    Next
                End If
                tr.Commit()
            End Using
            StdCnt.Text = numS
            ComCnt.Text = numC
            HanCnt.Text = numH
            VanCnt.Text = numV
            TtlCnt.Text = numT
        End Sub
        Private Sub eraser()
           
        End Sub
    
        Private Sub StdBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StdBtn.Click
            Dim BlockName As String = "Standard"
            blocktest(BlockName)
        End Sub
    
        Private Sub CompBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CompBtn.Click
            Dim BlockName As String = "Compact"
            blocktest(BlockName)
        End Sub
    
        Private Sub VanBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles VanBtn.Click
            Dim BlockName As String = "Van"
            blocktest(BlockName)
        End Sub
    
        Private Sub HandBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles HandBtn.Click
            Dim BlockName As String = "Handicap"
            blocktest(BlockName)
        End Sub
    
        Private Sub ExitBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitBtn.Click
            Me.Close()
            'set current layer to layer before app was run.
            Application.SetSystemVariable("clayer", Laycurrent.laycur)
        End Sub
    
        Private Sub Erasebtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Erasebtn.Click
            eraser()
        End Sub
    End Class

Page 1 of 2 12 LastLast

Similar Threads

  1. Increment copies of Blocks
    By Wish List System in forum AutoCAD Wish List
    Replies: 3
    Last Post: 2014-01-17, 02:55 AM
  2. Multiple Copies of AutoCAD
    By neilcheshire in forum AutoCAD General
    Replies: 6
    Last Post: 2010-01-25, 08:19 PM
  3. PUBLISH MULTIPLE COPIES
    By mike.schemm in forum AutoCAD Plotting
    Replies: 1
    Last Post: 2008-07-22, 03:57 AM
  4. Multiple rotate copies
    By cadkiller in forum Revit Architecture - General
    Replies: 1
    Last Post: 2005-08-01, 02:26 PM
  5. Bat Files for Deleting Backup copies
    By Zig in forum Revit Architecture - General
    Replies: 2
    Last Post: 2003-09-11, 04:20 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •