Author Topic: adding/deleting block attributes  (Read 21582 times)

0 Members and 1 Guest are viewing this topic.

shsss1985

  • Guest
adding/deleting block attributes
« on: July 10, 2012, 10:24:03 PM »
Hello everyone!
I have block with attributes , which have some values.
I need to add one or more attributes in this block, but values of existing attributes must be saved.
The same for deleting.
i am using ACAD2012 (objectARX 2012).

Thanks.

MexicanCustard

  • Swamp Rat
  • Posts: 705
Re: adding/deleting block attributes
« Reply #1 on: July 11, 2012, 07:18:56 AM »
Code: [Select]
//To add a new AttributeDefintion to an existing block
Database db = Application.DocumentManager.MDIActiveDocument.Database;

using (Transaction tr = db.TransactionManager.StartTransaction())
{
    var ad = new AttributeDefinition();
    ad.SetDatabaseDefaults(db);
    ad.Tag = "YOUR_TAG";
    ad.Prompt = "Your Prompt";

    var bt = db.BlockTableId.GetObject(OpenMode:ForRead);
    var btr = bt["SOMEBLOCK"].GetObject(OpenMode:ForWrite);
    btr.AppendEntity(ad);
    tr.AddNewlyCreatedDBObject(ad, true);

    tr.Commit();
}

Revit 2019, AMEP 2019 64bit Win 10

fixo

  • Guest
Re: adding/deleting block attributes
« Reply #2 on: July 11, 2012, 03:49:18 PM »
Here is my 2 cents
Change the block name and attribute tag

Code - C#: [Select]
  1.        [CommandMethod("dewa")]
  2.         public static void DelAttribute()
  3.         {
  4.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  5.  
  6.             Database db = doc.Database;
  7.  
  8.             Editor ed = doc.Editor;
  9.  
  10.             using (Transaction tr = db.TransactionManager.StartTransaction())
  11.             {
  12.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
  13.  
  14.                 if (!bt.Has("IMP"))
  15.                 {
  16.                     ed.WriteMessage("\nBlock definition IMP does not  exist");
  17.                     return;
  18.                 }
  19.  
  20.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt["IMP"], OpenMode.ForRead, false);
  21.  
  22.                 AttributeDefinition foundDef = new AttributeDefinition();
  23.  
  24.                 foreach (ObjectId id in btr)
  25.                 {
  26.                     DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false);
  27.  
  28.                     AttributeDefinition attDef = obj as AttributeDefinition;
  29.  
  30.                     if ((attDef != null) && (!attDef.Constant))
  31.                     {
  32.  
  33.                         if (attDef.Tag == "METRIC")
  34.                         {
  35.                             foundDef = attDef;
  36.  
  37.                             //break;
  38.                         }
  39.  
  40.  
  41.                         bt.UpgradeOpen();
  42.  
  43.                         btr.UpgradeOpen();
  44.  
  45.                         foundDef.UpgradeOpen();
  46.  
  47.                         foundDef.Erase();
  48.  
  49.                         btr.DowngradeOpen();
  50.  
  51.                         bt.DowngradeOpen();
  52.  
  53.                     }
  54.  
  55.  
  56.                 }
  57.  
  58.                 tr.Commit();
  59.  
  60.                 ed.WriteMessage("\nPerform command \"ATTSYNC\" manually");
  61.             }
  62.         }
  63.  
  64.         [CommandMethod("newa")]
  65.         public static void AddNewAtt()
  66.         {
  67.  
  68.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  69.             Database db = doc.Database;
  70.             Editor ed = doc.Editor;
  71.             using (Transaction tr = db.TransactionManager.StartTransaction())
  72.             {
  73.                 BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
  74.  
  75.                 if (!bt.Has("PART"))
  76.                 {
  77.                     ed.WriteMessage("\nBlock definition PART does not  exist");
  78.                     return;
  79.                 }
  80.  
  81.                 BlockTableRecord btr = (BlockTableRecord)tr.GetObject(bt["PART"], OpenMode.ForRead, false);
  82.  
  83.                 // location of the AttributeDefinition in the
  84.  
  85.                 // block definition
  86.  
  87.                 Point3d ptloc = new Point3d(0, 2, 0);
  88.                 // create a AttributeDefinition
  89.                 // specify the text,tag and prompt
  90.  
  91.                 string strvalue = "NEW VALUE ADDED";
  92.  
  93.                 string strtag = "MYTAG";
  94.  
  95.                 string strprompt = "Enter a new value";
  96.                 // used current text style
  97.                 AttributeDefinition attDef = new AttributeDefinition(ptloc, strvalue, strtag, strprompt, db.Textstyle);
  98.                 attDef.Height = 0.12;
  99.                 attDef.Layer = "0";
  100.                 attDef.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(ColorMethod.ByAci, 0);
  101.                 attDef.LinetypeId = db.ContinuousLinetype;
  102.                 // append the AttributeDefinition to the definition
  103.                 btr.UpgradeOpen();
  104.                 btr.AppendEntity(attDef);
  105.                 tr.AddNewlyCreatedDBObject(attDef, true);
  106.                 btr.DowngradeOpen();
  107.                 tr.Commit();
  108.             }
  109.         }

edit->kdub code formatting
« Last Edit: July 13, 2012, 03:05:47 AM by Kerry »

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #3 on: July 12, 2012, 12:00:38 AM »
thx MexicanCustard it works!
Fixo, the adding procedure is working, thx! But delete attribute isnt working(
i make a little changes, but it show me an error.
Code - C#: [Select]
  1. public void delAttribute(string blockName, string delTagName)
  2.         {
  3.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.             Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
  5.             Editor ed = doc.Editor;
  6.             try
  7.             {
  8.                 using (doc.LockDocument())
  9.                 {
  10.                     using (Transaction tr = db.TransactionManager.StartTransaction())
  11.                     {
  12.                         BlockTable bt = (BlockTable)(tr.GetObject(db.BlockTableId, OpenMode.ForRead, false));
  13.                         BlockTableRecord btr = (BlockTableRecord)(tr.GetObject(bt[blockName], OpenMode.ForRead, false));
  14.                         AttributeDefinition foundedDef = new AttributeDefinition();
  15.                         foreach (ObjectId id in btr)
  16.                         {
  17.                             DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false);
  18.                             AttributeDefinition attDef = obj as AttributeDefinition;
  19.                             if ((attDef != null) && (!attDef.Constant))
  20.                             {
  21.                                 if (attDef.Tag == delTagName)
  22.                                     foundedDef = attDef;
  23.                             }
  24.                             ////bt.UpgradeOpen();
  25.                             ////btr.UpgradeOpen();
  26.                             //foundedDef.UpgradeOpen();
  27.                             foundedDef.Erase();
  28.                             //btr.DowngradeOpen();
  29.                             //bt.DowngradeOpen();
  30.                         }
  31.                         tr.Commit();
  32.                     }
  33.                 }
  34.             }
  35.             catch (System.Exception ex)
  36.             {
  37.                 MessageBox.Show("Error: "+ ex.Message);
  38.             }
  39.            
  40.         }
the error is:  eNoDatabase


edit->kdub code formatting code = csharp.
« Last Edit: July 13, 2012, 03:03:32 AM by Kerry »

fixo

  • Guest
Re: adding/deleting block attributes
« Reply #4 on: July 12, 2012, 01:06:32 AM »
Sorry but I've deleted an attribute from block with no problems on my machine,
I'm using A2010,

~'J'~

Delegate

  • Guest
Re: adding/deleting block attributes
« Reply #5 on: July 12, 2012, 04:52:42 AM »
Is it because you have commented out the foundedref.upgradeopen()?

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #6 on: July 13, 2012, 02:14:11 AM »
No, i dont think so. If i uncomment this command there is another error: eWasOpenForWrite.
i really dont understand why this happened.

Kerry

  • Mesozoic relic
  • Seagull
  • Posts: 11654
  • class keyThumper<T>:ILazy<T>
Re: adding/deleting block attributes
« Reply #7 on: July 13, 2012, 03:01:24 AM »

I can't test the code at the moment but it may help if you are a bit more explicit about where the exception is and the actual exception bessage ...

Regards
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.

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #8 on: July 13, 2012, 04:30:23 AM »
Thx, Kerry, i'll try to explain.
Code - C#: [Select]
  1. public void delAttribute(string blockName, string delTagName)
  2.         {
  3.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  4.             Autodesk.AutoCAD.DatabaseServices.Database db = doc.Database;
  5.             Editor ed = doc.Editor;
  6.             try
  7.             {
  8.                 using (doc.LockDocument())
  9.                 {
  10.                     using (Transaction tr = db.TransactionManager.StartTransaction())
  11.                     {
  12.                         BlockTable bt = (BlockTable)(tr.GetObject(db.BlockTableId, OpenMode.ForRead, false));
  13.                         BlockTableRecord btr = (BlockTableRecord)(tr.GetObject(bt[blockName], OpenMode.ForRead, false));
  14.                         AttributeDefinition foundedDef = new AttributeDefinition();
  15.                         foreach (ObjectId id in btr)
  16.                         {
  17.                             DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false);
  18.                             AttributeDefinition attDef = obj as AttributeDefinition;
  19.                             if ((attDef != null) && (!attDef.Constant))
  20.                             {
  21.                                 if (attDef.Tag == delTagName)
  22.                                     foundedDef = attDef;
  23.                             }
  24.                             bt.UpgradeOpen();
  25.                             btr.UpgradeOpen();
  26.                             foundedDef.UpgradeOpen();
  27.                             foundedDef.Erase();
  28.                            
  29.                         }
  30.                         tr.Commit();
  31.                     }
  32.                 }
  33.             }
  34.             catch (Autodesk.AutoCAD.Runtime.Exception ex)
  35.             {
  36.                 MessageBox.Show("Error: " + ex.ErrorStatus);
  37.             }
  38.            
  39.         }
  40.  
if debug this code, everything works. Except on step
 
Code: [Select]

...
foundedDef.UpgradeOpen();
foundedDef.Erase();
...
 

after that i have error : eWasOpenForWrite

if i am commenting foundedDef.UpgradeOpen();
then i have an error: eNoDatabase, it is really strange because i connect to db = doc.Database


edit->kdub code formatting code = csharp.
« Last Edit: July 13, 2012, 04:35:46 AM by Kerry »

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Re: adding/deleting block attributes
« Reply #9 on: July 13, 2012, 04:42:23 AM »
Hi,

You're trying to upgrade and erase founDef at each loop (even when founDef didn't change)
Try with :

Code - C#: [Select]
  1. foreach (ObjectId id in btr)
  2. {
  3.     DBObject obj = (DBObject)tr.GetObject(id, OpenMode.ForRead, false) as AttributeDefinition;
  4.     if (attDef != null && !attDef.Constant && attDef.Tag == delTagName)
  5.     {
  6.         attDef.UpgradeOpen();
  7.         attDef.Erase();
  8.         break; // break the loop as the attribute is found
  9.     }
  10.  }
« Last Edit: July 13, 2012, 04:47:02 AM by gile »
Speaking English as a French Frog

shsss1985

  • Guest
Re: adding/deleting block attributes
« Reply #10 on: July 13, 2012, 04:52:54 AM »
oh yes it works! it really my bad!!!
Thx, gile, that pointed out an error!

cadplayer

  • Bull Frog
  • Posts: 390
  • Autocad Civil3d, OpenDCL.Runtime, LISP, .NET (C#)
Re: adding/deleting block attributes
« Reply #11 on: January 30, 2013, 06:18:32 AM »
Maybe it´s for a beginner a lot of stuff but I´m really intressting how the hole code looks like and works Can you show them ?
The thing is I try it to do with Lisp without _attsync. But without sucsess. So is it possible with c#.NET add Attributes without regenerate the block /Dirk
« Last Edit: January 30, 2013, 06:37:28 AM by cadplayer »

WILL HATCH

  • Bull Frog
  • Posts: 450
Re: adding/deleting block attributes
« Reply #12 on: January 30, 2013, 11:30:26 AM »
I took a slightly different approach to dealing with this issue.  To use this routine create an attribute definition in the drawing and position it relative to the block reference you wish to append it to.  Select the attribute definition, then the block reference and it will add the attribute definition to the block definition and then add an attribute reference to every instance of the block. The key to not requiring ATTSYNC is the foreach statement (line 31) where the attribute reference is added to each block reference.  Let me know if you need this extended to work with dynamic blocks.

Code - C#: [Select]
  1. [CommandMethod("AppendAttribute")]
  2.         public void AppendAttribute()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptEntityOptions peo = new PromptEntityOptions("\nSelect attribute to add");
  8.             peo.SetRejectMessage("\nNot an AttributeDefinition");
  9.             peo.AddAllowedClass(typeof(AttributeDefinition), true);
  10.             PromptEntityResult per = ed.GetEntity(peo);
  11.             if (per.Status != PromptStatus.OK) return;
  12.             ObjectId adId = per.ObjectId;
  13.             peo = new PromptEntityOptions("\nSelect block to append attribute");
  14.             peo.SetRejectMessage("\nNot a BlockReference");
  15.             peo.AddAllowedClass(typeof(BlockReference), true);
  16.             per = ed.GetEntity(peo);
  17.             if (per.Status != PromptStatus.OK) return;
  18.             ObjectId brId = per.ObjectId;
  19.             using (Transaction tr = db.TransactionManager.StartTransaction())
  20.             {
  21.                 try
  22.                 {
  23.                     AttributeDefinition ad = (AttributeDefinition)tr.GetObject(adId, OpenMode.ForWrite);
  24.                     BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForRead);
  25.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  26.                     AttributeDefinition NEWad = (AttributeDefinition)ad.Clone();
  27.                     NEWad.TransformBy(br.BlockTransform.Inverse()); //to set the AD to the BTR coordinate system
  28.                     ObjectId NEWadId = btr.AppendEntity(NEWad);
  29.                     tr.AddNewlyCreatedDBObject(NEWad, true);
  30.                     ObjectIdCollection blockIds = btr.GetBlockReferenceIds(true, true);
  31.                     foreach (ObjectId id in blockIds) //add attribute reference to all blocks
  32.                     {
  33.                         br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  34.                         AttributeReference ar = new AttributeReference();
  35.                         ar.SetAttributeFromBlock(NEWad, br.BlockTransform);
  36.                         ar.TextString = ad.TextString;
  37.                         br.AttributeCollection.AppendAttribute(ar);
  38.                         tr.AddNewlyCreatedDBObject(ar, true);
  39.                     }
  40.                     ad.Erase();
  41.                     tr.Commit();
  42.  
  43.                 }
  44.                 catch (System.Exception e)
  45.                 {
  46.                     ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  47.                 }
  48.             }
  49.            
  50.         }
  51.  

Below is similar, deletes an attribute reference from a block definition and all associated block references without going into the block editor.

Code - C#: [Select]
  1.         [CommandMethod("EraseAttribute")]
  2.         public void EraseAttribute()
  3.         {
  4.             Document doc = Application.DocumentManager.MdiActiveDocument;
  5.             Editor ed = doc.Editor;
  6.             Database db = doc.Database;
  7.             PromptNestedEntityOptions pneo = new PromptNestedEntityOptions("\nSelect attribute to erase");
  8.             using (Transaction tr = db.TransactionManager.StartTransaction())
  9.             {
  10.                 try
  11.                 {
  12.                     ObjectId arId;
  13.                     while (true)
  14.                     {
  15.                         PromptEntityResult per = ed.GetNestedEntity(pneo);
  16.                         if (per.Status != PromptStatus.OK) return;
  17.                         arId = per.ObjectId;
  18.                         if (tr.GetObject(arId, OpenMode.ForRead).GetType() == typeof(AttributeReference))
  19.                             break;
  20.                         ed.WriteMessage("\nNot an AttributeReference");
  21.                     }
  22.                     AttributeReference ar = (AttributeReference)tr.GetObject(arId, OpenMode.ForWrite);
  23.                     BlockReference br = (BlockReference)tr.GetObject(ar.OwnerId, OpenMode.ForRead);
  24.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(br.BlockTableRecord, OpenMode.ForWrite);
  25.                     foreach (ObjectId id in btr)
  26.                     {
  27.                         AttributeDefinition ad = tr.GetObject(id, OpenMode.ForRead) as AttributeDefinition;
  28.                         if (ad == null)
  29.                             continue;
  30.                         if (ad.Tag != ar.Tag)
  31.                             continue;
  32.                         ad.UpgradeOpen();
  33.                         ad.Erase();
  34.                     }
  35.                     foreach (ObjectId id in btr.GetBlockReferenceIds(true, true))
  36.                     {
  37.                         br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  38.                         foreach (ObjectId attId in br.AttributeCollection)
  39.                         {
  40.                             AttributeReference att = (AttributeReference)tr.GetObject(attId, OpenMode.ForWrite);
  41.                             if (att.Tag == ar.Tag)
  42.                             {
  43.                                 att.Erase();
  44.                             }
  45.                         }
  46.                     }
  47.                     tr.Commit();
  48.                 }
  49.                 catch (System.Exception e)
  50.                 {
  51.                     ed.WriteMessage("\nError: {0}\n{1}", e.Message, e.StackTrace);
  52.                 }
  53.             }
  54.         }
  55.  
« Last Edit: January 30, 2013, 11:59:30 AM by WILL HATCH »

kaefer

  • Guest
Re: adding/deleting block attributes
« Reply #13 on: January 30, 2013, 01:32:35 PM »
Let me know if you need this extended to work with dynamic blocks.

Dynamic blocks aside, you'll need probably a call to AttributeReference.AdjustAlignment(Database) somewhere to take care of alignments other than AttachmentPoint.BaseLeft. Then there should be a special case to support multi-line attributes, by testing for IsMTextAttribute/IsMTextAttributeDefinition and calling UpdateMTextAttribute().

Andrey did a recursive Attsync for .Net, with source code here.

Jeff H

  • Needs a day job
  • Posts: 6150
Re: adding/deleting block attributes
« Reply #14 on: January 30, 2013, 01:39:17 PM »
Here is another way Tony shows using AcDbMatchProperties protocol extension.