.NET

.NET

Reply
Valued Mentor
AubelecBE
Posts: 383
Registered: ‎01-27-2010
Message 1 of 6 (234 Views)

How to selec all block only on no frozen and active layer

234 Views, 5 Replies
07-12-2012 05:01 AM

hi all. my code :

Dim editor As Editor = Application.DocumentManager.MdiActiveDocument.Editor
        Dim db As Database = HostApplicationServices.WorkingDatabase
        Dim tr As Transaction = db.TransactionManager.StartTransaction()
        Try

            Dim values(0) As TypedValue
            values(0) = New TypedValue(DxfCode.Start, "INSERT")
            Dim selFilter As New SelectionFilter(values)
            Dim prompSelRes As PromptSelectionResult = editor.SelectAll(selFilter)
            If prompSelRes.Status = PromptStatus.OK Then
                Dim objSelectSet As SelectionSet = prompSelRes.Value
......

 

 

the only prob is : I want selec all block but not the block on layer frozen, off or not visible...

How i can do that ?

 

I can check all layer stat on each block.. (i do that already for check each block (name) but i want a solution more easy.)

 

thanks

*Expert Elite*
Hallex
Posts: 1,569
Registered: ‎10-08-2008
Message 2 of 6 (230 Views)

Re: How to selec all block only on no frozen and active layer

07-12-2012 05:28 AM in reply to: AubelecBE

Try this filter

 

  Dim curlay As String = Autodesk.AutoCAD.ApplicationServices.Application.GetSystemVariable("clayer").ToString()
                Dim values(3) As TypedValue
                values(0) = New TypedValue(DxfCode.Operator, "<and")
                values(1) = New TypedValue(DxfCode.Start, "insert")
                values(2) = New TypedValue(DxfCode.LayerName, curlay)
                values(3) = New TypedValue(DxfCode.Operator, "and>")

                Dim selFilter As New SelectionFilter(values)
                Dim prompSelRes As PromptSelectionResult = ed.SelectAll(selFilter)
                If prompSelRes.Status <> PromptStatus.OK Then Return
                Dim objSelectSet As SelectionSet = prompSelRes.Value
                ed.WriteMessage(vbLf + "{0}", objSelectSet.Count)

 

~'J'~

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
*Expert Elite*
_gile
Posts: 2,082
Registered: ‎04-29-2006
Message 3 of 6 (213 Views)

Re : How to selec all block only on no frozen and active layer

07-12-2012 11:24 AM in reply to: AubelecBE

Hi,

 

If you really want to use a selection set, you can handle the Editor.SelectionAdded event to filter the blocks:

 

        public PromptSelectionResult SelectAllVisible(TypedValue[] filter)
        {
            Editor ed = AcAp.DocumentManager.MdiActiveDocument.Editor;
            PromptSelectionResult psr = null;
            try
            {
                ed.SelectionAdded += new SelectionAddedEventHandler(onSelectionAdded);
                psr = ed.SelectAll(new SelectionFilter(filter));
            }
            finally
            {
                ed.SelectionAdded -= new SelectionAddedEventHandler(onSelectionAdded);
            }
            return psr;
        }

        void onSelectionAdded(object sender, SelectionAddedEventArgs e)
        {
            Database db = HostApplicationServices.WorkingDatabase;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
                List<string> layers = new List<string>();
                foreach (ObjectId ltrId in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(ltrId, OpenMode.ForRead);
                    if (ltr.IsFrozen || ltr.IsHidden || ltr.IsOff)
                        layers.Add(ltr.Name);
                }
                List<int> toRemove = new List<int>();
                SelectionSet ss = e.AddedObjects;
                for (int i = 0; i < ss.Count; i++)
                {
                    BlockReference br = (BlockReference)ss[i].ObjectId.GetObject(OpenMode.ForRead);
                    if (layers.Contains(br.Layer))
                        toRemove.Add(i);
                }
                foreach (int i in toRemove) e.Remove(i);
                tr.Commit();
            }
        }

 Using example:

 

            TypedValue[] filter = new TypedValue[] { new TypedValue(0, "INSERT") };
            PromptSelectionResult psr = SelectAllVisible(filter);

 

Anyway, the EditorSelectAll does iterate all the layouts. IMO it's more simple to do it by yourself.

Here's an example using Linq which must be launch from within a transaction and returns an IEnumerable<BlockReference> (lazy sequence):

 

        public IEnumerable<BlockReference> GetAllVisibleBlocks(Database db)
        {
            LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
            List<string> layers = lt
                .Cast<ObjectId>()
                .Select(id => (LayerTableRecord)id.GetObject(OpenMode.ForRead))
                .Where(ltr => ltr.IsFrozen || ltr.IsHidden || ltr.IsOff)
                .Select(ltr => ltr.Name)
                .ToList();
 
            BlockTable bt = (BlockTable)db.BlockTableId.GetObject(OpenMode.ForRead);
            return bt.Cast<ObjectId>()
                .Select(id => (BlockTableRecord)id.GetObject(OpenMode.ForRead))
                .Where(btr => btr.IsLayout)
                .SelectMany(btr => btr.Cast<ObjectId>())
                .Where(id => id.ObjectClass.DxfName == "INSERT")
                .Select(id => (BlockReference)id.GetObject(OpenMode.ForRead))
                .Where(br => !layers.Contains(br.Layer));
        }

 

Gilles Chanteau
Valued Mentor
AubelecBE
Posts: 383
Registered: ‎01-27-2010
Message 4 of 6 (185 Views)

Re : How to selec all block only on no frozen and active layer

07-16-2012 12:17 PM in reply to: _gile

thx.

but can you use vb.net.

i dont like C+.

 

:smileyhappy:

I dont know this methode for iterate.

 

*Expert Elite*
_gile
Posts: 2,082
Registered: ‎04-29-2006
Message 5 of 6 (174 Views)

Re : How to selec all block only on no frozen and active layer

07-16-2012 02:43 PM in reply to: AubelecBE

I don't like VB :smileywink:

There're free code converters:

http://www.google.fr/#hl=fr&gs_nf=1&cp=10&gs_id=16&xhr=t&q=convert+C%23+to+vb.net&pf=p&output=search...

 

Using SelectionAdded event handler

        Public Function SelectAllVisible(filter As TypedValue()) As PromptSelectionResult
            Dim ed As Editor = Application.DocumentManager.MdiActiveDocument.Editor
            Dim psr As PromptSelectionResult = Nothing
            Try
                AddHandler ed.SelectionAdded, AddressOf Me.onSelectionAdded
                psr = ed.SelectAll(New SelectionFilter(filter))
            Finally
                RemoveHandler ed.SelectionAdded, AddressOf Me.onSelectionAdded
            End Try
            Return psr
        End Function

        Private Sub onSelectionAdded(sender As Object, e As SelectionAddedEventArgs)
            Dim db As Database = HostApplicationServices.WorkingDatabase
            Using tr As Transaction = db.TransactionManager.StartTransaction()
                Dim lt As LayerTable = DirectCast(db.LayerTableId.GetObject(OpenMode.ForRead), LayerTable)
                Dim layers As New List(Of String)()
                For Each ltrId As ObjectId In lt
                    Dim ltr As LayerTableRecord = DirectCast(tr.GetObject(ltrId, OpenMode.ForRead), LayerTableRecord)
                    If ltr.IsFrozen OrElse ltr.IsHidden OrElse ltr.IsOff Then
                        layers.Add(ltr.Name)
                    End If
                Next
                Dim toRemove As New List(Of Integer)()
                Dim ss As SelectionSet = e.AddedObjects
                For i As Integer = 0 To ss.Count - 1
                    Dim br As BlockReference = DirectCast(ss(i).ObjectId.GetObject(OpenMode.ForRead), BlockReference)
                    If layers.Contains(br.Layer) Then
                        toRemove.Add(i)
                    End If
                Next
                For Each i As Integer In toRemove
                    e.Remove(i)
                Next
                tr.Commit()
            End Using
        End Sub

 Using example:

            Dim filter As TypedValue() = New TypedValue() {New TypedValue(0, "INSERT")}
            Dim psr As PromptSelectionResult = SelectAllVisible(filter)

 

Using Linq extension methods (must be launched from within a transaction).

        Public Function GetAllVisibleBlocks(db As Database) As IEnumerable(Of BlockReference)
            Dim lt As LayerTable = DirectCast(db.LayerTableId.GetObject(OpenMode.ForRead), LayerTable)
            Dim layers As List(Of String) =
                lt.Cast(Of ObjectId)() _
                .Select(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), LayerTableRecord)) _
                .Where(Function(ltr) ltr.IsFrozen OrElse ltr.IsHidden OrElse ltr.IsOff) _
                .Select(Function(ltr) ltr.Name).ToList()

            Dim bt As BlockTable = DirectCast(db.BlockTableId.GetObject(OpenMode.ForRead), BlockTable)
            Return bt.Cast(Of ObjectId) _
                .Select(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), BlockTableRecord)) _
                .Where(Function(btr) btr.IsLayout) _
                .SelectMany(Function(btr) btr.Cast(Of ObjectId)) _
                .Where(Function(id) id.ObjectClass.DxfName = "INSERT") _
                .Select(Function(id) DirectCast(id.GetObject(OpenMode.ForRead), BlockReference)) _
                .Where(Function(br) Not layers.Contains(br.Layer))
        End Function

 

Gilles Chanteau
Member
xsfhlzh1
Posts: 5
Registered: ‎07-19-2012
Message 6 of 6 (154 Views)

Re: How to selec all block only on no frozen and active layer

07-19-2012 06:29 PM in reply to: AubelecBE
        [CommandMethod("t1")]
        public static void Test1()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            var db = doc.Database;
            var ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                LayerTable lt = (LayerTable)db.LayerTableId.GetObject(OpenMode.ForRead);
                List<string> layers = new List<string>();
                foreach (ObjectId ltrId in lt)
                {
                    LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(ltrId, OpenMode.ForRead);
                    if (ltr.IsFrozen || ltr.IsHidden || ltr.IsOff)
                        layers.Add(ltr.Name);
                }

                SelectionFilter sf =
                    new SelectionFilter
                    (
                        new TypedValue[]
                        {
                            new TypedValue(0, "insert"),
                            new TypedValue(8, string.Join(",", layers.ToArray()))
                        }
                    );
                //ResultList rl =
                //    new ResultList
                //    {
                //        {0, "insert"},
                //        {8, string.Join(",", layers.ToArray())}
                //    };
                var res = ed.SelectAll(sf);
            }

        }

 test this code

Announcements
Are you familiar with the Autodesk Expert Elites? The Expert Elite program is made up of customers that help other customers by sharing knowledge and exemplifying an engaging style of collaboration. To learn more, please visit our Expert Elite website.
Need installation help?

Start with some of our most frequented solutions or visit the Installation and Licensing Forum to get help installing your software.