Author Topic: "Cleanest" Method For Selecting All Blocks in PaperSpace  (Read 13214 times)

0 Members and 2 Guests are viewing this topic.

wannabe

  • Guest
"Cleanest" Method For Selecting All Blocks in PaperSpace
« on: July 04, 2009, 02:41:53 PM »
Hi Everyone,

I'm trying to access blocks from other drawings for manipulation purposes, but I only want those that reside in paper space. Initially I looked at the DXFCodes, but I couldn't see one that was applicable for a typedValue filter. I then checked out PromptSelectionOptions() which only allows me to get all blocks from the active space. If the drawing isn't actually open, would paper space be the active space (I'm copying drawings into Database references via the ReadDWG() method to make global changes)?

Are there any DXF codes that can do this to save me from checking each selected block against the ObjectId for Model Space, which seems a "dirty" way of operating. The layoutName doesn't seem robust enough.

EDIT: Actually, I think the LayoutName DXF Code will be fine. I'll post up if I get any reported problems.


As always, comments are appreciated.
« Last Edit: July 04, 2009, 02:46:30 PM by wannabe »

wannabe

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #1 on: July 04, 2009, 04:00:25 PM »
When I tried it on the host drawing it worked. When I copied a selection of drawings into a Database reference it failed to recognise any blocks not in paper space with the filtering criteria in the post above.

Any suggestions?

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #2 on: July 04, 2009, 04:09:52 PM »
Hi,

Did you try (67, 1) ?

Another way should be iterating through each layout, and in each layout block table reference, through each object looking for a block references.
Speaking English as a French Frog

wannabe

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #3 on: July 04, 2009, 04:18:02 PM »
Yeah, I just realised that using a selection filter won't work when the Editor object is only going to work on open drawings.

So now it's a case of scanning each layout as you suggest. Not a problem, but could be cleaner.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #4 on: July 04, 2009, 04:49:52 PM »
Here's a quick and dirty.
Let me know if there's a cleaner way (I'm newby and learning...)

Code: [Select]
public ArrayList GetBlockRefInLayouts()
{
    Database db = Application.DocumentManager.MdiActiveDocument.Database;
    ArrayList result = new ArrayList();
    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        DBDictionary NOD = (DBDictionary)tr.GetObject(db.NamedObjectsDictionaryId, OpenMode.ForRead);
        DBDictionary layouts = (DBDictionary)tr.GetObject(NOD.GetAt("ACAD_LAYOUT"), OpenMode.ForRead);
        foreach (DBDictionaryEntry entry in layouts)
        {
            if (entry.Key != "Model")
            {
                Layout lay = (Layout)tr.GetObject(entry.Value, OpenMode.ForRead);
                BlockTableRecord layoutBtr = (BlockTableRecord)tr.GetObject(lay.BlockTableRecordId, OpenMode.ForRead);
                foreach (ObjectId id in layoutBtr)
                {
                    BlockReference blk = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
                    if (blk != null)
                        result.Add(blk);
                }
            }
        }
        tr.Commit();
    }
    return result;
}
Speaking English as a French Frog

wannabe

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #5 on: July 04, 2009, 05:07:14 PM »
Thats basically what I did, with slight differences that provide the same result.

Cheers for posting.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #6 on: July 04, 2009, 11:50:16 PM »
gile,
thats essentially how I'd do it as well.

except there is no necessity to tr.Commit() because you are not revising the database , so there is nothing to commit.
... at least that's my understanding

:)

/// kdub
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

sinc

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #7 on: July 05, 2009, 12:01:11 AM »
If you don't commit, then the transaction aborts, and a commit has less overhead than an abort.  At least, according to some of Kean's blog posts.  It might be an interesting thing to test.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #8 on: July 05, 2009, 12:18:36 AM »
Richard, yes, appears I was incorrect ..

I found that reference
http://through-the-interface.typepad.com/through_the_interface/2007/04/iterating_throu.html


Quote
There's a DevNote on the ADN site covering this topic:

http://adn.autodesk.com/adn/servlet/devnote?siteID=4814862&id=5546971&linkID=4900509

Here's an excerpt:

>>>
... there is a huge performance difference between Commit() and Abort(). So, when opening objects for read, you definitely want to explicitly call Commit() even though you didn't really change anything. As evidenced by a few test functions, Abort() should only be used under "duress" because of the performance hit.
<<<

A read-only transaction (even one that opens objects for write, but doesn't modify them) will not set the database modified flag (DBMOD) when committed. It's the individual "set" methods that call assertWriteEnabled(), forcing DBMOD to non-zero.
kdub, kdub_nz in other timelines.
Perfection is not optional.
Everything will work just as you expect it to, unless your expectations are incorrect.
Discipline: None at all.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #9 on: July 05, 2009, 03:05:23 AM »
Thanks all,

I was lucky if the 'commit' way is the right way.
The commit/dispose/abort stuff keeps difficult to undersand for me.
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #10 on: July 06, 2009, 11:20:58 AM »
I thought I was told by Tony T. that you didn't want to return an object, but rather an ObjectId.  I'm talking about this section of gile's code

Code: [Select]
                foreach (ObjectId id in layoutBtr)
                {
                    BlockReference blk = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
                    if (blk != null)
                        result.Add(blk);
                }

I would even think that one would want to return the handle, as the ObjectId is created upon opening the database ( drawing ), and would not be the same the next time you open the drawing, but the handle always would be, so the handle and the drawing name would be the best way to go.

That was my understanding at least.  If I'm wrong, carry on.   :-)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

sinc

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #11 on: July 06, 2009, 12:34:05 PM »
I thought I was told by Tony T. that you didn't want to return an object, but rather an ObjectId.  I'm talking about this section of gile's code

Yeah, good catch.  That piece of code is creating a transaction and getting objects, then trying to return the objects after closing the transaction.  That's the no-no.

You can return objects in a method, but the transaction should still be active when you do so.

I'm not sure why you would want the handle...  It depends on your code, and what it does.  But for most purposes, the ObjectId is preferable.

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #12 on: July 06, 2009, 01:15:40 PM »
and also, it will be much easier to return an ObjectIdCollection, since you can just call:

result layoutBtr.GetBlockReferenceIds();


maybe?

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #13 on: July 06, 2009, 02:02:19 PM »
Thanks for the confirmation Sinc.

Luis,

That would just get all the inserts of that specific block definition, not all the blocks that are inserted ( nested ) within the definition.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #14 on: July 06, 2009, 02:45:30 PM »
So, if I understand, it should have been :
Code: [Select]
foreach (ObjectId id in layoutBtr)
                {
                    BlockReference blk = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
                    if (blk != null)
                        result.Add(id); // or result.Add(id.Handle);
                }

Or is there another way to evaluate if the object is a BlockReference ?
Speaking English as a French Frog

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #15 on: July 06, 2009, 02:57:03 PM »
Thanks for the confirmation Sinc.

Luis,

That would just get all the inserts of that specific block definition, not all the blocks that are inserted ( nested ) within the definition.


dang!.... sorry

lately I'm way out of my miserable C# skills (== -0)

4 slaps on my face.   :oops:

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #16 on: July 06, 2009, 03:01:56 PM »
For most instances the Id will be fine to work with.  In rare cases the Handle will have to be used, but here I think you can stick with the Id.

As for testing if it's a BlockReference, what you have works, and would most likely be what I used ( take that for what it's worth ).  If you wanted another way, you could just cast it as an entity, then test it with the ' is ' keyword ( I think below is how it works ).  Just another option.

Code: [Select]
Entity Ent = tr.GetObject( id, OpenMode.ForRead ) as Entity
if ( Ent is BlockReference )
    result.Add( id );
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #17 on: July 06, 2009, 03:03:13 PM »
Thanks for the confirmation Sinc.

Luis,

That would just get all the inserts of that specific block definition, not all the blocks that are inserted ( nested ) within the definition.


dang!.... sorry

lately I'm way out of my miserable C# skills (== -0)

4 slaps on my face.   :oops:

Not a problem Luis.   :-)
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #18 on: July 06, 2009, 03:11:33 PM »
Thanks Tim.

My C# 'stuff' isn't much more than hacking some snippets here and there :-(
Speaking English as a French Frog

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #19 on: July 06, 2009, 03:46:46 PM »
Thanks Tim.

My C# 'stuff' isn't much more than hacking some snippets here and there :-(

You're welcome Gile.  I'm learning just like you, and I see you with some good stuff, and I'm sure you will keep at it and develop some good stuff.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

wannabe

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #20 on: July 07, 2009, 07:30:31 AM »
Thanks Tim.

My C# 'stuff' isn't much more than hacking some snippets here and there :-(

The guys on here recommended Pro C# 2008 and the .NET platform. It was a great read, but I already had a good foundation of C# by then. Headfirst C# is a great entry-level hands-on book, though (in my opinion).

What level are you currently at?

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #21 on: July 07, 2009, 10:52:17 AM »
Well, I have some time to play today with little c# and here it is Gile's function with some touch ups.... HTH-maybe :)

Code: [Select]
public ObjectIdCollection GetBlockRefInLayouts()
{
    ObjectIdCollection ids = new ObjectIdCollection();
    Database db = Application.DocumentManager.MdiActiveDocument.Database;
    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        DBDictionary layoutDict = (DBDictionary)tr.GetObject(db.LayoutDictionaryId, OpenMode.ForRead);
        foreach (DBDictionaryEntry entry in layoutDict)
        {
            if (entry.Key == "Model") continue;
            Layout layout = (Layout)tr.GetObject(entry.Value, OpenMode.ForRead);
            BlockTableRecord layoutBtr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead, false);
            if (!layoutBtr.IsAnonymous)
            {
                foreach (ObjectId id in layoutBtr)
                {
                    BlockReference blk = tr.GetObject(id, OpenMode.ForRead) as BlockReference;
                    if (blk != null) ids.Add(id);
                }
            }
        }
        tr.Commit();
    }
    return ids;
}

[CommandMethod("PSBLOCKS")]
public void psblocks()
{
    Document doc = acadApp.DocumentManager.MdiActiveDocument;
    Editor ed = doc.Editor;
    Database db = doc.Database;
    ObjectIdCollection ids = new ObjectIdCollection();
    ids = GetBlockRefInLayouts();
    ed.WriteMessage("\nBlocks on paper-space: {0}", ids.Count.ToString());
}

wannabe

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #22 on: July 07, 2009, 12:26:25 PM »
That's a touch closer to the methodology I used. Rather than going through the NOD I directly grabbed the LayoutDictionaryID from each database I readDWg()'ed.

The only part I would like to query is the .IsAnonyMous property. I think I've read somewhere, or deduced from someone else's  code that this means is not in an Xref? Close? :-)


gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #23 on: July 07, 2009, 12:29:03 PM »
Una vez más, muchas gracias Luis.

He apprendido el uso de ObjectIdCollection, db.LayoutDictionaryId y continue, pero nunca he visto de anonymous layout block.
¿Cuáles son esos objetos?

I learned the using of ObjectIdCollection, db.LayoutDictionaryId and continue but I never saw any anonymous layout block.
What kind of objects are there ?
Speaking English as a French Frog

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #24 on: July 07, 2009, 12:43:09 PM »
Una vez más, muchas gracias Luis.

He apprendido el uso de ObjectIdCollection, db.LayoutDictionaryId y continue, pero nunca he visto de anonymous layout block.
¿Cuáles son esos objetos?

I learned the using of ObjectIdCollection, db.LayoutDictionaryId and continue but I never saw any anonymous layout block.
What kind of objects are there ?

:)

For example, remove the IsAnonymous condition, and then in the drawing draw one dimension... it will count the anonymous block.

Also, on this line:

BlockTableRecord layoutBtr = (BlockTableRecord)tr.GetObject(layout.BlockTableRecordId, OpenMode.ForRead, false);

notice the false argument, this will ignore the recent erased blocks.

And also about the continue, we can use that here too:

 if (layoutBtr.IsAnonymous) continue;

To skip the anonymous blocks.

EDIT:.... --- I need to finish some work, and if someone can insert an anonymous block and tested... I'll be back.

« Last Edit: July 07, 2009, 12:56:17 PM by LE »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #25 on: July 07, 2009, 01:04:16 PM »
OK, I know anonymous blocks, but AFAIK, they're stored in the blocks collection, not in the layout block.

As far as I understand, layoutBtr refers to the layout block definition as the object got with the vlisp expression (I'm more comfortable with LISP):
(vla-get-Block (vla-item (vla-get-Layouts ...) "Layout1")).

If I'm true, the false parameter should have been here:

BlockReference blk = tr.GetObject(id, OpenMode.ForRead, false) as BlockReference;

EDIT: I tried both an exploded dimension and a dynamic bloc.
Only the dynamic bloc is founded whatever the IsAnonymous condition, even I found "*D2" and "*U4" in the block collection (BlockTable).
And it seems there's no need to the false parameter if a block reference have been erased.
« Last Edit: July 07, 2009, 01:11:52 PM by gile »
Speaking English as a French Frog

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #26 on: July 07, 2009, 01:07:42 PM »
OK, I know anonymous blocks, but AFAIK, they're stored in the blocks collection, not in the layout block.

As far as I understand, layoutBtr refers to the layout block definition as the object got with the vlisp expression (I'm more comfortable with LISP):
(vla-get-Block (vla-item (vla-get-Layouts ...) "Layout1")).

If I'm true, the false parameter should have been here:

BlockReference blk = tr.GetObject(id, OpenMode.ForRead, false) as BlockReference;

I need another coffee... and need to play a little more with C#.

Have been lately in the miserable ATL COM stuff... and that might be my excuse...

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #27 on: July 07, 2009, 01:24:15 PM »
I don't think you need to check if the block is anonymous, because I don't think a layout could have an anonymous block associated with it.

I'm not sure if you would need to check if the block has been erased either, as it might not be in the layout dictionary, but a quick test could be done.  Just create a layout, and run the code.  Then delete the layout, and run the code.  Then you should be able to tell if the layout information is still in the dictionary.
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #28 on: July 07, 2009, 01:25:03 PM »
OK, I know anonymous blocks, but AFAIK, they're stored in the blocks collection, not in the layout block.

As far as I understand, layoutBtr refers to the layout block definition as the object got with the vlisp expression (I'm more comfortable with LISP):
(vla-get-Block (vla-item (vla-get-Layouts ...) "Layout1")).

If I'm true, the false parameter should have been here:

BlockReference blk = tr.GetObject(id, OpenMode.ForRead, false) as BlockReference;

EDIT: I tried both an exploded dimension and a dynamic bloc.
Only the dynamic bloc is founded whatever the IsAnonymous condition, even I found "*D2" and "*U4" in the block collection (BlockTable).
And it seems there's no need to the false parameter if a block reference have been erased.

Yep... did that too.... I'm glad that I don't code in C# for a living....  :-P

Spike Wilbury

  • Guest
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #29 on: July 07, 2009, 01:26:47 PM »
I don't think you need to check if the block is anonymous, because I don't think a layout could have an anonymous block associated with it.

I'm not sure if you would need to check if the block has been erased either, as it might not be in the layout dictionary, but a quick test could be done.  Just create a layout, and run the code.  Then delete the layout, and run the code.  Then you should be able to tell if the layout information is still in the dictionary.

We (me) did that already Tim.... and you right.

thanks! to refresh my 3 brain cells... left

T.Willey

  • Needs a day job
  • Posts: 5251
Re: "Cleanest" Method For Selecting All Blocks in PaperSpace
« Reply #30 on: July 07, 2009, 01:52:31 PM »
I don't think you need to check if the block is anonymous, because I don't think a layout could have an anonymous block associated with it.

I'm not sure if you would need to check if the block has been erased either, as it might not be in the layout dictionary, but a quick test could be done.  Just create a layout, and run the code.  Then delete the layout, and run the code.  Then you should be able to tell if the layout information is still in the dictionary.

We (me) did that already Tim.... and you right.

thanks! to refresh my 3 brain cells... left

My pleasure Luis.  You probably forgot more about programming that I will ever know.  :wink:
Tim

I don't want to ' end-up ', I want to ' become '. - Me

Please think about donating if this post helped you.