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

find attribute by name

12 REPLIES 12
Reply
Message 1 of 13
wang890
533 Views, 12 Replies

find attribute by name

say i know the names of attribute definition already. is there a way to find it in the collection without going through each item and check the item name?

this will speed up the program greatly. thank you
Stantec
Dell Precision 5530, Prism M320PU, C3D 14/17/19
12 REPLIES 12
Message 2 of 13
DeathTiger
in reply to: wang890

By chance, do you know the blocks name or id in which these attributes reside?
Message 3 of 13
wang890
in reply to: wang890

yes and no

i have the name of the block since it's already created. i guess i can look through the blocks and then find attributes by the name since i know the attribute tagstring, but that's gonna take the same time as get each tag string name and looking into it.

i have the list of the tags in excel. just want to read the corresponding text string from the drawing layouts. would be nice to have a nice algorithm to speed up the process since there will be many drawings to process all the time.
Stantec
Dell Precision 5530, Prism M320PU, C3D 14/17/19
Message 4 of 13
DeathTiger
in reply to: wang890

Is there any more information that can be adopted to identify the required block, or are all the attribute tags unique? (i.e. not replicated in other blocks)

I've got a similar setup in one of my applications where I required the text from an attribute, but the text I need to find is found within a static block name on the current layout (there is never 2 of the same on the one sheet).
Message 5 of 13
wang890
in reply to: wang890

yeah, there is no repeat. it's title block for drawings, you know with "designed by" "checked by", "scale", "drawing title 1","drawing title 2". etc.

so i guess there is no way to target to the specific attribute without going through everything.

see pic.
Stantec
Dell Precision 5530, Prism M320PU, C3D 14/17/19
Message 6 of 13
DeathTiger
in reply to: wang890

The following code is what I have used in the past to obtain tag strings based on a Layout Id and BlockName.
You may be able to modify that to suit your needs, and it's on my todo list for re-writing.

{code}
///
/// Attribute pull connects to the current active drawing to 'pull'
/// attribute text based on specified layout, block and tag criteria
///

/// Current Drawing Layout to Search for Blocks in
/// Block name to search
/// Attribute tag to search
/// Attribute string text
/// 31st July 2009
public static string AttributePull(_ds.ObjectId cad_oiLayoutID, string sBlockName, string sAttributeTag)
{
//Create a new string to return our attribute text with
string sAttribute = string.Empty;
//Connect to the current active drawing
_as.Document cad_docDocument = _as.Application.DocumentManager.MdiActiveDocument;
//Connect to the current drawings database
_ds.Database cad_dDatabase = cad_docDocument.Database;

using (_ds.Transaction cad_tTransaction = cad_docDocument.TransactionManager.StartTransaction())
{
//Get a list of the blocks
_ds.BlockTable cad_btTable = (_ds.BlockTable)cad_tTransaction.GetObject(cad_dDatabase.BlockTableId, _ds.OpenMode.ForRead);
//create a record of blocks within the specified layout (Model or Paperspace)
_ds.BlockTableRecord cad_btrRecord = (_ds.BlockTableRecord)cad_tTransaction.GetObject(cad_oiLayoutID, _ds.OpenMode.ForRead);

//Search each block in the specified layout
foreach (_ds.ObjectId cad_oiBlockID in cad_btrRecord)
{
//Make the block an entity (easier to search)
_ds.Entity cad_eBlock = cad_tTransaction.GetObject(cad_oiBlockID, _ds.OpenMode.ForRead) as _ds.Entity;

//Conditional, make sure the entity exists before continuing
if (cad_eBlock != null)
{
//make a reference to the entity
_ds.BlockReference cad_brReference = cad_eBlock as _ds.BlockReference;

//Conditional, if the block reference exists
if (cad_brReference != null)
{
//Create a new table record for any block attributes
_ds.BlockTableRecord cad_btrAttributes = (_ds.BlockTableRecord)cad_tTransaction.GetObject(cad_brReference.BlockTableRecord, _ds.OpenMode.ForRead);

//If the block has attributes
if (cad_btrAttributes.HasAttributeDefinitions)
{
//Iterate through each of the attibutes
foreach (_ds.ObjectId cad_oiAttributeID in cad_brReference.AttributeCollection)
{
//Create new objects for the attributes
_ds.DBObject cad_dboAttribute = cad_tTransaction.GetObject(cad_oiAttributeID, _ds.OpenMode.ForRead);
//Create new references for the attibutes
_ds.AttributeReference cad_arAttribute = cad_dboAttribute as _ds.AttributeReference;

//If the found attribute tag matches that of our search criteria
if (cad_arAttribute.Tag.ToUpper() == sAttributeTag.ToUpper())
{
//set the return string to the attribute value
sAttribute = cad_arAttribute.TextString.ToString();
//commit the transaction
cad_tTransaction.Commit();
//close the transaction
cad_tTransaction.Dispose();
//end this god damned loop!
return sAttribute;
}
}
}
}
}
}
//commit the transaction
cad_tTransaction.Commit();
//close the transaction
cad_tTransaction.Dispose();
}
//return a null attribute (ie, tag not found)
return sAttribute;
}
{code}
Message 7 of 13
DeathTiger
in reply to: wang890

I had a spare minute or 2 and revised the previous (nasty) code. Below is simple, if you can identify the block ID which has the attributes, pass it through below and it should return the attribute string.

{code}
internal string GT_Attribute_Pull(ObjectId BlockID, string sTag)
{
//Create a new string to return
string sAttribute = string.Empty;
//Make a reference to the current drawing and database
Document acDWG = Application.DocumentManager.MdiActiveDocument;
Database acDB = acDWG.Database;

//Start a new transaction
using (Transaction acTrans = acDB.TransactionManager.StartTransaction())
{
//Make a BlockReference to that of the specified BlockID
BlockReference acBR = acTrans.GetObject(BlockID, OpenMode.ForRead) as BlockReference;

//If there is 1 or more attribute in the block reference
if (acBR.AttributeCollection.Count >= 1)
{
//Make reference to each object in the attribute collection
foreach (ObjectId acID in acBR.AttributeCollection)
{
//Get the Attribute Reference
AttributeReference acAR = acTrans.GetObject(acID, OpenMode.ForRead) as AttributeReference;

//Compare the Tags
if (acAR.Tag.ToUpper() == sTag.ToUpper())
{
//Grab the Attribute String
sAttribute = acAR.TextString;
}
}
}
//Dispose the Transaction
acTrans.Dispose();
}
//Return the Attribute
return sAttribute;
}
{code} Edited by: DeathTiger on Nov 6, 2009 9:50 AM
Message 8 of 13
Anonymous
in reply to: wang890

Try a few more edits.

The code you posted needlessly runs through the entire attribute collection,
continuing to open and look at attributes, even after it has found the one
being searched for.

It also aborts the transaction, which is a no-no.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

wrote in message news:6284528@discussion.autodesk.com...
I had a spare minute or 2 and revised the previous (nasty) code. Below is
simple, if you can identify the block ID which has the attributes, pass it
through below and it should return the attribute string.

{code}
internal string GT_Attribute_Pull(ObjectId BlockID, string sTag)
{
//Create a new string to return
string sAttribute = string.Empty;
//Make a reference to the current drawing and database
Document acDWG = Application.DocumentManager.MdiActiveDocument;
Database acDB = acDWG.Database;

//Start a new transaction
using (Transaction acTrans =
acDB.TransactionManager.StartTransaction())
{
//Make a BlockReference to that of the specified BlockID
BlockReference acBR = acTrans.GetObject(BlockID,
OpenMode.ForRead) as BlockReference;

//If there is 1 or more attribute in the block reference
if (acBR.AttributeCollection.Count >= 1)
{
//Make reference to each object in the attribute
collection
foreach (ObjectId acID in acBR.AttributeCollection)
{
//Get the Attribute Reference
AttributeReference acAR = acTrans.GetObject(acID,
OpenMode.ForRead) as AttributeReference;

//Compare the Tags
if (acAR.Tag.ToUpper() == sTag.ToUpper())
{
//Grab the Attribute String
sAttribute = acAR.TextString;
}
}
}
//Dispose the Transaction
acTrans.Dispose();
}
//Return the Attribute
return sAttribute;
}
{code}

Edited by: DeathTiger on Nov 6, 2009 9:50 AM
Message 9 of 13
DeathTiger
in reply to: wang890

Tony,

Thank-you for pointing this out. I recently noticed a significant delay in how long it took for my attributes to return in larger drawings.

As for the acTrans.Dispose(). I am presently under the impression that the "using" statement will automatically dispose of the transaction, however calling "Dispose" should produce the same results. Is this correct?

> {quote:title=Tony Tanzillo wrote:}{quote}
> Try a few more edits.
>
> The code you posted needlessly runs through the entire attribute collection,
> continuing to open and look at attributes, even after it has found the one
> being searched for.
>
> It also aborts the transaction, which is a no-no.
>
> --
> http://www.caddzone.com
>
> AcadXTabs: MDI Document Tabs for AutoCAD
> Supporting AutoCAD 2000 through 2010
>
> http://www.acadxtabs.com
>
> Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");
Message 10 of 13
chiefbraincloud
in reply to: wang890

The short answer is no.

I am at home and find myself without my current project files (plus no ACAD), otherwise I'd post a function, but it seems you already know how to do it by AttributeCollection using ObjectIDs, so my code probably wouldn't help you anyway.

I don't know of any way (in the Managed .NET API) to get an AttributeReference by Tag. Wether you go through the objects in the block reference or get the AttributeCollection, you are still working with ObjectIDs not Entities.

The only thing you can do to speed it up (if you didn't already) is to make sure as soon as you find your attref, you stop looping (as Tony mentioned). And to keep it clean, make sure that however you terminate your loop, you get all your open references disposed.

I guess there is one more thing, based on some of the posts here, you are looking for more than one attref in the same block, if so, you can find them all in one loop through the attref collection if you pass in a dictionary (of string, string) where the key is the Tag and the value is the new Textstring. I have a function for that (at work) if you want.
Dave O.                                                                  Sig-Logos32.png
Message 11 of 13
wang890
in reply to: wang890

it's ok folks. it's not that slow. process 2 drawings per second including open excel and write 14 attribute per drawing. here's my VB codes same as your c#
Stantec
Dell Precision 5530, Prism M320PU, C3D 14/17/19
Message 12 of 13
Anonymous
in reply to: wang890

Unless the layouts you're working with contain more than one title block
insertion, your code is going to run much slower than it could if you break
out of the outer loop when you find the title block, or return from the
function when you find the title block and the attribute you're looking for.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

wrote in message news:6284965@discussion.autodesk.com...
it's ok folks. it's not that slow. process 2 drawings per second including
open excel and write 14 attribute per drawing. here's my VB codes same as
your c#
Message 13 of 13
Anonymous
in reply to: wang890

{quote}

As for the acTrans.Dispose(). I am presently under the impression that the
"using" statement will automatically dispose of the transaction, however
calling "Dispose" should produce the same results. Is this correct?

{quote}

Yes, using(...) is just a way of calling Dispose() and ensuring that it
happens regardless of how the code terminates, but the problem is that
disposing an uncommitted transaction causes it to be aborted.

Aborting a transaction has overhead that is unnecessary when what you're
doing involves no changes to the database, so the general rule to follow is
to always call Commit() on a transaction even if you didn't modify the
database, to avoid that overhead.



--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD
Supporting AutoCAD 2000 through 2010

http://www.acadxtabs.com

Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

wrote in message news:6284588@discussion.autodesk.com...
Tony,

Thank-you for pointing this out. I recently noticed a significant delay in
how long it took for my attributes to return in larger drawings.

As for the acTrans.Dispose(). I am presently under the impression that the
"using" statement will automatically dispose of the transaction, however
calling "Dispose" should produce the same results. Is this correct?

> {quote:title=Tony Tanzillo wrote:}{quote}
> Try a few more edits.
>
> The code you posted needlessly runs through the entire attribute
> collection,
> continuing to open and look at attributes, even after it has found the one
> being searched for.
>
> It also aborts the transaction, which is a no-no.
>
> --
> http://www.caddzone.com
>
> AcadXTabs: MDI Document Tabs for AutoCAD
> Supporting AutoCAD 2000 through 2010
>
> http://www.acadxtabs.com
>
> Email: string.Format("{0}@{1}.com", "tonyt", "caddzone");

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