.NET

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

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

245 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 (241 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,114
Registered: ‎04-29-2006
Message 3 of 6 (224 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: 394
Registered: ‎01-27-2010
Message 4 of 6 (196 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,114
Registered: ‎04-29-2006
Message 5 of 6 (185 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 (165 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

Post to the Community

Have questions about Autodesk products? Ask the community.

New Post
Announcements
Are You Going To Be @ AU 2014? Feel free to drop by our AU topic post and share your plans, plug a class that you're teaching, or simply check out who else from the community might be in attendance. Ohh and don't forgot to stop by the Autodesk Help | Learn | Collaborate booths in the Exhibit Hall and meet our community team if you get a chance!