Author Topic: Help with Attributes  (Read 2300 times)

0 Members and 1 Guest are viewing this topic.

Arizona

  • Guest
Help with Attributes
« on: November 07, 2011, 08:47:05 AM »
Hi All,

I think I have gotten to a point with this where I can ask this as an intelligent question and I may actually understand the answer. This is what I am trying to do:
1.   Search drawing for Title block reference.
a.   Get insert point, attributes
2.   Insert new title block at same location as old title block
a.   Get attributes
3.   Compare attribute tags, get the textstring values from the old title block and put them into the new title block. Note: The tags are identically named between the old and new blocks, both blocks contain 16 attributes, labeled CTB1, CTB2, etc..
4.   Delete the old titleblock.
This is my first attempt at writing a C# program for AutoCAD (at least one that is not in the tutorial) and the only reason I have gotten this far is because of folks like Kerry, Jeff and other Swampers. 
I’m pretty sure I have backed myself into a corner, so I need help (of any kind)!
I do recognize that my variables are going out of scope, so I believe this should be broken down into more procedures. Any assistance/guidance is most definitely appreciated!
This is what I have so far:

Code: [Select]
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.EditorInput;

namespace GetTitleBlkInfo
{
    public class GetTitleBlkInfo
    {
        [CommandMethod("GetTitleBlk")]
        public static void GetOldTitleBlk()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string[] oldBlkName = new string[] { "ctml0012", "ctml0011", "ctml0010" };
            String strBlkName = "J:\\acad\\ctml0013.dwg";
            Point3d InsPoint = new Point3d();
            //AttributeCollection oldAttCol;
            //AttributeCollection newAttCol;
            string newName = "ctml0013";
            string oldName = "";
            int i = 0;
            //Start Transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                //Get the block table and check for old titleblock
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                while (i < 3)
                {
                    if (bt.Has(oldBlkName[i]))
                    {
                        oldName = oldBlkName[i];
                        //Open BlkTable Record for modelspace
                        BlockTableRecord btr = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                        foreach (ObjectId blkid in btr)
                        {
                            BlockReference oldTBlkRef = tr.GetObject(blkid, OpenMode.ForRead) as BlockReference;
                            if (oldTBlkRef.Name == oldName)
                            {
                                ed.WriteMessage("\nblock name is: " + oldTBlkRef.Name);
                                InsPoint = oldTBlkRef.Position;
                                Scale3d scale = oldTBlkRef.ScaleFactors;
                                //oldAttCol = oldTBlkRef.AttributeCollection;
                            }//close if oldtblkref.name
                        }//close foreach ObjectId
                    }//close if oldBlkName
                    i = i + 1;
                }//close while i

                if (!bt.Has(newName))
                {
                    bt.UpgradeOpen();
                    Database tmpDb = new Database(false, true);
                    tmpDb.ReadDwgFile(strBlkName, System.IO.FileShare.Read, true, null);
                    //insert the block into the block table
                    ObjectId BlkId = db.Insert(strBlkName, tmpDb, true);
                    //Get the block Table record for the block
                    BlockTableRecord newBtr = (BlockTableRecord)tr.GetObject(BlkId, OpenMode.ForWrite);
                    //Name the block table record
                    newBtr.Name = newName;
                    //create the block reference and get modelspace Block table record
                    BlockReference br = new BlockReference(InsPoint, BlkId);
                    BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    br.Position = InsPoint;
                    ms.AppendEntity(br);
                    tr.AddNewlyCreatedDBObject(br, true);
                    //newAttCol = br.AttributeCollection;
                }//close if newName

                InsertAttributes(oldName);
                //commit the changes and dispose of the transaction
                tr.Commit();
            }//close using
        }//close public

        public static void InsertAttributes(string oldBName)
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            AttributeCollection oldAttCol;
            AttributeCollection newAttCol;
            BlockReference tblkNew;
            string newBName = "ctml0013";
            //Start Transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt2 = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                 //Open BlkTable Record for modelspace
                        BlockTableRecord btr2 = tr.GetObject(bt2[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord;
                        foreach (ObjectId blkid in btr2)
                        {
                            BlockReference TBlk = tr.GetObject(blkid , OpenMode.ForRead) as BlockReference;
                            if (TBlk.Name == oldBName)
                            {
                                BlockReference tblkOld = (BlockReference)tr.GetObject(blkid, OpenMode.ForRead);
                                oldAttCol = tblkOld.AttributeCollection;
                            }
                            if (TBlk.Name == newBName)
                            {
                                tblkNew = (BlockReference)tr.GetObject(blkid, OpenMode.ForWrite);
                                newAttCol = tblkNew.AttributeCollection;
                            }
                          }
                       
                        foreach (ObjectId attOldId in oldAttCol)
                        {
                            foreach (ObjectId attNewId in newAttCol)
                                {
                                    AttributeReference oldAtt = (AttributeReference)tr.GetObject(attOldId, OpenMode.ForRead);
                                    AttributeReference newAtt = (AttributeReference)tr.GetObject(attNewId, OpenMode.ForWrite);
                                    if (oldAtt.Tag == newAtt.Tag)
                                     {
                                        newAtt.TextString = oldAtt.TextString;
                                        tblkNew.AttributeCollection.AppendAttribute(newAtt);
                                        tr.AddNewlyCreatedDBObject(newAtt, true);
                                      }
                                }//close foreach attNewId
                           }//close foreach attOldId               
                tr.Commit();
            }//close second transaction
        } //close public
    }//close class
}//close namespace
       
     
   

       


Jeff H

  • Needs a day job
  • Posts: 6144
Re: Help with Attributes
« Reply #1 on: November 07, 2011, 10:55:54 AM »
If the attributes are the same and are in the same location then all you would need to do change the BlockReference.BlockTableRecord property
 
Example using OldTB and NewTB
 
Code: [Select]
         [CommandMethod("ReplaceTB")]
        public void ReplaceTB()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockTableRecord oldBtr = (BlockTableRecord)tr.GetObject(bt["OldTB"], OpenMode.ForRead);
                foreach (ObjectId id in oldBtr.GetBlockReferenceIds(true, false))
                {
                    BlockReference bref = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
                    bref.BlockTableRecord = bt["NewTB"];
                }
               
                tr.Commit();
               
     
            }
        }
 

Arizona

  • Guest
Re: Help with Attributes
« Reply #2 on: November 07, 2011, 12:42:06 PM »
Thanks for the response Jeff!

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Help with Attributes
« Reply #3 on: November 08, 2011, 11:49:22 AM »
I was looking for a way to do something similiar, but by selecting the first and second block.  This is what i have so far.
Code: [Select]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;

namespace EditTitleBlock
{
    public class EditTitleBlock
    {
        [CommandMethod("ReplaceTB")]
        public void ReplaceTB()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            PromptEntityOptions peo1 = new PromptEntityOptions("\n Select Old Titleblock: ");
            peo1.AllowNone = true;
           
            PromptEntityResult per1 = ed.GetEntity(peo1);
            if (per1.Status != PromptStatus.OK)
            {
                return;
            }
            else
            {
                ObjectId oldBlkId = per1.ObjectId;
                PromptEntityOptions peo2 = new PromptEntityOptions("\n Select New Titleblock: ");
                peo2.AllowNone = true;
                PromptEntityResult per2 = ed.GetEntity(peo2);
                if (per2.Status != PromptStatus.OK)
                {
                    return;
                }
                ObjectId newBlkId = per2.ObjectId;
                using (Transaction tr = db.TransactionManager.StartTransaction())
                {
                    BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord oldBtr = (BlockTableRecord)tr.GetObject(oldBlkId, OpenMode.ForRead);
                    BlockTableRecord newBtr = (BlockTableRecord)tr.GetObject(newBlkId, OpenMode.ForWrite);
                    foreach (ObjectId id in oldBtr.GetBlockReferenceIds(true, false))
                    {
                        BlockReference bref = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
                    }
                    tr.Commit();
                }
            }
        }
    }
}
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

David Hall

  • Automatic Duh Generator
  • King Gator
  • Posts: 4075
Re: Help with Attributes
« Reply #4 on: November 08, 2011, 11:51:07 AM »
Still working on processing the attributes
Everyone has a photographic memory, Some just don't have film.
They say money can't buy happiness, but it can buy Bacon and that's a close second.
Sometimes the question is more important than the answer. (Thanks Kerry for reminding me)

Arizona

  • Guest
Re: Help with Attributes
« Reply #5 on: November 08, 2011, 12:53:18 PM »
I did get this to work although it may not be in the best form. It does transfer all the attribute values from the old titleblock to the new title block.
Code: [Select]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Colors;
using Autodesk.AutoCAD.EditorInput;

namespace SwapTBlk
{
    public class GetTblk_Info
    {
        [CommandMethod("GetTitleBlk")]
        public static void GetOldTitleBlk()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;
            string[] oldBlkName = new string[] { "ctml0012", "ctml0011", "ctml0010" };
            String strBlkName = "J:\\acad\\ctml0013.dwg";
            Point3d InsPoint = new Point3d();
            AttributeCollection oldAttCol;
            AttributeCollection newAttCol;
            string newName = "ctml0013";
            string oldName = "";
            int i = 0;
            //Start Transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                //Get the block table and check for old titleblock
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
                while (i < 3)
                {
                    if (bt.Has(oldBlkName[i]))
                    {
                        oldName = oldBlkName[i];
                    }//close if
                    i = i + 1;
                }//close while i
                //Open BlkTable Record
                BlockTableRecord btr = tr.GetObject(bt[oldName], OpenMode.ForWrite) as BlockTableRecord;
                foreach (ObjectId id in btr.GetBlockReferenceIds(true, false))
                {
                    BlockReference oldTBlkRef = tr.GetObject(id, OpenMode.ForWrite) as BlockReference;
                    InsPoint = oldTBlkRef.Position;
                    Scale3d scale = oldTBlkRef.ScaleFactors;
                    oldAttCol = oldTBlkRef.AttributeCollection;
                    bt.UpgradeOpen();
                    Database tmpDb = new Database(false, true);
                    tmpDb.ReadDwgFile(strBlkName, System.IO.FileShare.Read, true, null);
                    //insert the block into the block table
                    ObjectId BlkId = db.Insert(strBlkName, tmpDb, true);
                    //Get the block Table record for the block
                    BlockTableRecord newBtr = (BlockTableRecord)tr.GetObject(BlkId, OpenMode.ForWrite);
                    //Name the block table record
                    newBtr.Name = newName;
                    //create the block reference and get modelspace Block table record
                    BlockReference br = new BlockReference(InsPoint, BlkId);
                    BlockTableRecord ms = (BlockTableRecord)tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    br.Position = InsPoint;
                    ms.AppendEntity(br);
                    tr.AddNewlyCreatedDBObject(br, true);
                    newAttCol = br.AttributeCollection;
                    foreach (ObjectId attNewId in newBtr)
                    {
                        Entity newEnt = (Entity)tr.GetObject(attNewId, OpenMode.ForRead);
                        if (newEnt is AttributeDefinition)
                        {
                            AttributeDefinition newAttDef = (AttributeDefinition)newEnt;
                            AttributeReference newRef = new AttributeReference();
                            newRef.SetAttributeFromBlock(newAttDef, br.BlockTransform);
                            br.AttributeCollection.AppendAttribute(newRef);
                            tr.AddNewlyCreatedDBObject(newRef, true);
                        }//if newent
                    }//close foreach attnewid
                        int counter = 1;
                        int newCounter = br.AttributeCollection.Count - 1;
                        while (newCounter >= 0)
                        {
                            counter = oldAttCol.Count - 1;
                           
                            while (counter >= 0)
                            {
                                ObjectId attOldId = oldAttCol[counter];
                                ObjectId attNewId = newAttCol[newCounter];
                                AttributeReference oldAtt = (AttributeReference)tr.GetObject(attOldId, OpenMode.ForRead);
                                AttributeReference newAtt = (AttributeReference)tr.GetObject(attNewId, OpenMode.ForWrite);
                               
                                if (oldAtt.Tag == newAtt.Tag)
                                {
                                    newAtt.TextString = oldAtt.TextString;
                                }//close if
                                counter = counter - 1;
                            }//close while
                            newCounter = newCounter - 1;
                        }//close newcounter               
                    }//close if
                BlockTableRecord oldbtr = tr.GetObject(bt[oldName], OpenMode.ForWrite) as BlockTableRecord;
                foreach (ObjectId id1 in oldbtr.GetBlockReferenceIds(true, false))
                {
                    BlockReference oldTBlk = tr.GetObject(id1, OpenMode.ForWrite) as BlockReference;
                    oldTBlk.Erase(true);
                }
                    //commit the changes and dispose of the transaction
                    tr.Commit();
            }//close using
        }//close public
    }//Close class
}//close namespace
« Last Edit: November 08, 2011, 01:40:02 PM by Arizona »