.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Remove object ids from an ObjectIdCollection object

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
Rob.O
1782 Views, 9 Replies

Remove object ids from an ObjectIdCollection object

Can someone explain to me how to remove object ids from the ObjectIDCollection?  I understand you must use the .Remove or .Removeat methods, but I need some more direction.  I am spefically looking to remove block names (originally gathered from a selection set).

 

TIA!

 

Rob

9 REPLIES 9
Message 2 of 10
cadMeUp
in reply to: Rob.O

You're better off stuffing the id's, that you want to keep, into a new collection:

 

ObjectIdCollection filterIdCol = new ObjectIdCollection();

string blockNameToFilterOut = "BLOCKNAME";
foreach (ObjectId id in selSet.GetObjectIds())
{
 BlockReference blockRef = (BlockReference)id.GetObject(OpenMode.ForRead);
 if (blockRef.Name == blockNameToFilterOut)
  filterIdCol.Add(id);
}

 

You'll get unexpected results when you start removing items from a collection that you are looping thru.

See the attached file for a more complete example...

 

Message 3 of 10
cadMeUp
in reply to: cadMeUp

Sorry, this line:

if (blockRef.Name == blockNameToFilterOut)


 should say:

if (blockRef.Name != blockNameToFilterOut)

Message 4 of 10
Rob.O
in reply to: cadMeUp

Thanks cadMe!

 

What if I don't want to hardcode the blockname in the code?

 

I am trying to iterate through the selected blocks and write each one out to a separate file.  It works well with one exception: The first block from the selection set writes to its own file with no problems, the second writes to its own file and appends the first to it; the third writes to its own file and appends the first and second, etc...  I have tried to use the .clear method on the ObjectIDCollecion and it appears to work, but for some reason, the successive blocks are still written to the file.

 

Any ideas?

Message 5 of 10
Rob.O
in reply to: Rob.O

Code is attached!  Any help would be greatly appreciated!

Message 6 of 10
cadMeUp
in reply to: Rob.O

It looks to me, you are looping thru the selection set of blockreferences, each iteration you create a new ObjectIdCollection:
Dim acObjIdColl As New ObjectIdCollection

 

and then add the current object's id in the loop to the collection:
acObjIdColl.Add(acBlkRef.ObjectId)

 

at the end of the loop acObjIdColl goes out of scope, only one objectid is being added to the collection each time you loop thru the set so if you were to remove any objects from the collection you would only be able to remove one objectid. You can verify it by printing the collection count at the command line after you add the blockref id to the collection.

 

When each loop ends 'acObjIdColl' would be set for garbage collection anyway so these lines are not needed:
acObjIdColl.Clear() 'calling this removes only one objectid from the collection
acObjIdColl.Dispose()

 

It looks to me like you don't have to worry about removing any object id's. If you want to remove any previously added blocks to the acNewDB, that's a different story.

 

If you want to skip certain blocks by name, in your foreach loop:
Dim acBlkRef As BlockReference
acBlkRef = acEnt

Dim blockNameToFilterOut As String = "BLOCKNAME"
If acBlkRef.Name = blockNameToFilterOut Then
 Continue For
End If

 

Or you can check the name against a collection of names:
Dim blkNameFilter As List(Of String) = New List(Of String)
blkNameFilter.Add("BLOCKNAME1")
blkNameFilter.Add("BLOCKNAME2")
blkNameFilter.Add("BLOCKNAME3")
If blkNameFilter.Contains(acBlkRef.Name) Then
 Continue For
End If

 

Are you getting unexpected behavior?

Message 7 of 10
Rob.O
in reply to: cadMeUp

cadMe Wrote:

"It looks to me, you are looping thru the selection set of blockreferences, each iteration you create a new ObjectIdCollection:"

 

  Yes... I am not sure if there is a better way to accomplish this, but if the user selects 100 blocks, I want each written to a sperate file.

 

cadMe Wrote:

"It looks to me like you don't have to worry about removing any object id's. If you want to remove any previously added blocks to the acNewDB, that's a different story."

 

I think you hit the nail on the head.  This whole time I was thinking the extra blocks were stuck in the ObjectIDCollection, but as you pointed out, I think they are being appended to the database during each loop.  So, is there a way to get them out of the database or clear the database after each loop? The .Dispose methd does not seem to be working for me.

 

acTempDB.dispose() 'Does not seem to remove the existing temporary database

 

cadMe Wrote:

"Are you getting unexpected behavior?"

 

Everything works with one minor exception... if the user selects 3 blocks, the first file created only contains the first block selected. The next file created contains the first block and the second block selected and the third file created contains the first second and third blocks selected and so on.

 

It really does seem like the database is the problem.

 

Thanks for your help!

Message 8 of 10
cadMeUp
in reply to: Rob.O

I hope you don't mind, I re-wrote your code a little bit, see the attached file. I think it will give you what you want, but you may want to rethink what the output will be. I think you want the user to select only block reference objects correct? You need to check each object in the selection set to make sure it is a block reference. Now, each block reference gets written to it's own file with the same name as the block reference, and inside that file exists, in model space, a block reference with the same name as the file it's in (without the .dwg ext of course), now if you want to insert that new block file into another dwg somewhere you will probably get this message at the command line:

 

Block *** references itself
*Invalid*

 

So depending on what you want to do with the output files later on you may run into problems. Seems like you may want to wblock the entities that are within the block reference (the entities that make up the block def table record)? In that case you would get the BlockTableRecord of the block ref, get the object id's that are within the BlockTableRecord and add those to the ObjectIdCollection. See the FastBlock2.txt file attached for something like that. But it's not fullproof, you may run into problems as well with:

 

Block *** references itself
*Invalid*

 

Most likely not though. Best thing to do is after each block file is written check each one for insertion errors. That could get difficult if you have a large amount of files, but you could always automate that process too.

 

Anyway, hope this helps, hope it makes sense.

Message 9 of 10
Rob.O
in reply to: Rob.O

Wow... you made that look easy! 🙂

 

As this was my first program in .net, I just wanted to get the program running before applying filters, etc...  but, I definately appreciate you throwing some in there!

 

Thanks for pointing out the potential nested block issue.  I didn't even think about that!  FastBlock2 is EXACTLY what I was trying to accomplish!

 

Looking at the FastBlock.txt file you re-wrote, it looks as if I had my transaction and my for loop in the wrong places?  Other than those differences and the removal of the temp database, it looks pretty similar.  I assume the loop in the wrong place was throwing off the number of blocks being written to the temp databse?

 

Thanks again for the help!

Message 10 of 10
cadMeUp
in reply to: Rob.O

I think your transaction looked fine. Essentially you just needed to create a new database within the for loop to create each block, save it, and dispose of it at the end of the for loop. The thing that was dangerous, your selection set wasn't doing any filtering and while you were looping thru the set each entity was being cast to a BlockReference without checking to see if it was an actual BlockReference. You would get an exception for sure if you came across an entity that wasn't a BlockReference. Even for testing purposes it's good to include error checking, and use try...catch...blocks.

 

Oh, and also, since selecting objects doesn't need a transaction, it's best to put your selecting before you start a transaction, if you can. If the user cancels the selection then you don't have to worry about killing a transaction, you just return. If the user makes an OK selection, then procede to start the transaction and get your objects.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost