Getting Block Name from Associative Array

Getting Block Name from Associative Array

odoshi
Collaborator Collaborator
1,877 Views
12 Replies
Message 1 of 13

Getting Block Name from Associative Array

odoshi
Collaborator
Collaborator

Hi,

 

I have an associative array made form a block reference.

 

Is there a route to getting the original block name from the array? It looks like the source objects of an array become anonymous blocks.

 

Thanks!

Mike Caruso
Autodesk Certified Instructor 2014
AutoCAD/Civil 3D Autodesk Certified Professional 2014, 2015, 2018
www.whitemountaincad.com
0 Likes
Accepted solutions (2)
1,878 Views
12 Replies
Replies (12)
Message 2 of 13

fieldguy
Advisor
Advisor

you don't say what data type and content is in the array

you can get the block name from the blocktablerecord

something like:

BlockReference myblk = (BlockReference)tr.GetObject(blkid, acdb.OpenMode.ForRead);
BlockTableRecord blkbtr = null;
if (myblk.IsDynamicBlock)
blkbtr = (BlockTableRecord)tr.GetObject(myblk.DynamicBlockTableRecord, OpenMode.ForRead);
else
blkbtr = (BlockTableRecord)tr.GetObject(myblk.BlockTableRecord, OpenMode.ForRead);
string bname = blkbtr.Name;

0 Likes
Message 3 of 13

Wittekamp
Contributor
Contributor

I've exactly the same problem.

In my case I need the blocknames of the blocks in the array, to check against a database containing all valid blocknames.

 

The IsAnonymous property of the blocks in the array is set to true, so yes they are Anonymous I think. Unfortunately DynamicBlockTableRecord doesn't work on anonymous blocks. I also tried to set the description of the block in the blockeditor and then use the comments property of the blocktablerecord, but that also doesn't work. The comments property remains empty.

 

I'll keep working on this. I can't believe this isn't possible....

0 Likes
Message 4 of 13

Alexander.Rivilis
Mentor
Mentor

@odoshi @Wittekamp

Please attach dwg-file with such array for testing.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 5 of 13

Wittekamp
Contributor
Contributor

I've attached the file "Test Array.dwg" to my post.

It's a small array using a dynamic block as source.  

0 Likes
Message 6 of 13

Alexander.Rivilis
Mentor
Mentor
Accepted solution

Try this code:

using System;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(Rivilis.CheckAssocArray))]

namespace Rivilis
{

  public class CheckAssocArray
  {
    [CommandMethod("CAR")]
    public void MyCommand()
    {
      // Put your command code here
      Document doc = Application.DocumentManager.MdiActiveDocument;
      if (doc == null) return;
      Editor ed = doc.Editor;
      PromptEntityOptions prOpt = new PromptEntityOptions("Select Assoc Array: ");
      prOpt.SetRejectMessage("Not a Assoc Array");
      prOpt.AddAllowedClass(typeof(BlockReference), true);
      PromptEntityResult prRes = ed.GetEntity(prOpt);
      if (prRes.Status == PromptStatus.OK)
      {
        AssocArray asArr = AssocArray.GetAssociativeArray(prRes.ObjectId);
        if (asArr == null)
        {
          ed.WriteMessage("\nNot a Assoc Array");
          return;
        }
        ObjectIdCollection ids = asArr.SourceEntities;
        if (ids.Count >= 1)
        {
          ObjectId id = ids[0]; // Check only first entity in Array
          if (id.ObjectClass.IsDerivedFrom(RXClass.GetClass(typeof(BlockReference))))
          {
            using (BlockReference br = id.Open(OpenMode.ForRead) as BlockReference)
            {
              using (BlockTableRecord btr = br.DynamicBlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord)
              {
                ed.WriteMessage("\nBlockName = {0}", btr.Name);
              }
            }
          } else
          {
            ed.WriteMessage("\nAssoc Array has not BlockReference");
          }
        }
      }
    }
  }
}

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 7 of 13

Wittekamp
Contributor
Contributor

That seems to work yes. Thanks for the effort!!!

 

One more question now we are at it (if you don't mind):

If you would replace the block with the orange text saying "KTL" by another dynamic block (with a different name) then this new block won't be part of the sourceEntities collection of the array. How to get the blockname of this "replaced" block?  

 

Our engineers often use the replace function for array items, but we can't figure out how to extract the blockname of replaced items in an array.

 

Again, thanks for the fast responses and your effort!

0 Likes
Message 8 of 13

Alexander.Rivilis
Mentor
Mentor

@Wittekamp

Post such dwg sample.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 9 of 13

Wittekamp
Contributor
Contributor

See the attached example.

My block with the orange text "KTL" from the previous example is now replaced with a different block (the block with the text H on both sides). How to get the name of this block?

0 Likes
Message 10 of 13

Alexander.Rivilis
Mentor
Mentor

@Wittekamp wrote:

See the attached example.

My block with the orange text "KTL" from the previous example is now replaced with a different block (the block with the text H on both sides). How to get the name of this block?


Easiest way is using AssocArray.Explode and checking all exploded block references. But you have to undo this operation because array was erased after  AssocArray.Explode.

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 11 of 13

Alexander.Rivilis
Mentor
Mentor

@Wittekamp

This code maybe useful in your case:

using System;
using System.Linq;
using System.Collections.Generic;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.EditorInput;

#pragma warning disable 0618

// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(Rivilis.CheckAssocArray))]

namespace Rivilis
{
  public class CheckAssocArray
  {
    public string GetBlockNameInBlock(BlockReference br)
    {
      string name = null;
      using (BlockTableRecord btr =
        br.DynamicBlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord)
      {
        name = btr.Name;
        // If block has only one entity == BlockReference
        // then getting name of this block
        if (btr.Cast<ObjectId>().Count() == 1)
        {
          ObjectId id = btr.Cast<ObjectId>().ElementAt(0);
          if (id.ObjectClass == RXClass.GetClass(typeof(BlockReference)))
          {
            using (BlockReference brInt = 
              id.Open(OpenMode.ForRead) as BlockReference)
            using (BlockTableRecord btrInt =
              brInt.DynamicBlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord)
            {
              name = btrInt.Name;
            }
          }
        }
      }
      return name;
    }
    [CommandMethod("CAR")]
    public void MyCommand()
    {
      // Put your command code here
      Document doc = Application.DocumentManager.MdiActiveDocument;
      if (doc == null) return;
      Editor ed = doc.Editor;
      PromptEntityOptions prOpt = new PromptEntityOptions("Select Assoc Array: ");
      prOpt.SetRejectMessage("Not a Assoc Array");
      prOpt.AddAllowedClass(typeof(BlockReference), true);
      PromptEntityResult prRes = ed.GetEntity(prOpt);
      if (prRes.Status != PromptStatus.OK)
        return;
      if (!AssocArray.IsAssociativeArray(prRes.ObjectId))
      {
        ed.WriteMessage("\nNot a Assoc Array");
        return;
      }
      using (BlockReference br = prRes.ObjectId.Open(OpenMode.ForRead) as BlockReference)
      {
        using (DBObjectCollection brs = new DBObjectCollection())
        {
          br.Explode(brs);
          if (brs != null && brs.Count > 0)
          {
            for (int i = 0; i < brs.Count; i++)
            {
              using (DBObject obj = brs[i])
              {
                ed.WriteMessage("\n{0} - ", i);
                if (obj is BlockReference)
                {
                  ed.WriteMessage(GetBlockNameInBlock(obj as BlockReference));
                }
              }
            }
          }
        }
      }
    }
  }
}

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 12 of 13

Alexander.Rivilis
Mentor
Mentor
Accepted solution

The previous code does not take into account hidden block references that are on the *ADSK_ASSOC_ENTITY_BACKUPS layer.

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System.Linq;

#pragma warning disable 0618

// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(Rivilis.CheckAssocArray))]

namespace Rivilis
{
  public class CheckAssocArray
  {
    public string GetBlockNameInBlock(BlockReference br)
    {
      string name = null;
      using (BlockTableRecord btr =
        br.DynamicBlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord)
      {
        name = btr.Name;
        // If block has only one entity == BlockReference
        // then getting name of this block
        if (btr.Cast<ObjectId>().Count() == 1)
        {
          ObjectId id = btr.Cast<ObjectId>().ElementAt(0);
          if (id.ObjectClass == RXClass.GetClass(typeof(BlockReference)))
          {
            using (BlockReference brInt =
              id.Open(OpenMode.ForRead) as BlockReference)
            using (BlockTableRecord btrInt =
              brInt.DynamicBlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord)
            {
              name = btrInt.Name;
            }
          }
        }
      }
      return name;
    }
    [CommandMethod("CAR")]
    public void MyCommand()
    {
      // Put your command code here
      Document doc = Application.DocumentManager.MdiActiveDocument;
      if (doc == null) return;
      Editor ed = doc.Editor;
      PromptEntityOptions prOpt = new PromptEntityOptions("Select Assoc Array: ");
      prOpt.SetRejectMessage("Not a Assoc Array");
      prOpt.AddAllowedClass(typeof(BlockReference), true);
      PromptEntityResult prRes = ed.GetEntity(prOpt);
      if (prRes.Status != PromptStatus.OK)
        return;
      if (!AssocArray.IsAssociativeArray(prRes.ObjectId))
      {
        ed.WriteMessage("\nNot a Assoc Array");
        return;
      }
      using (BlockReference br = prRes.ObjectId.Open(OpenMode.ForRead) as BlockReference)
      {
        using (DBObjectCollection brs = new DBObjectCollection())
        {
          br.Explode(brs);
          if (brs != null && brs.Count > 0)
          {
            int i = 0;
            foreach (DBObject obj in brs)
            {
              if (obj is BlockReference &&
                (obj as BlockReference).Layer != "*ADSK_ASSOC_ENTITY_BACKUPS")
              {
                ed.WriteMessage("\n{0} - {1}", i++, GetBlockNameInBlock(obj as BlockReference));
              }
              obj.Dispose();
            }
          }
        }
      }
    }
  }
}

Відповідь корисна? Клікніть на "ВПОДОБАЙКУ" цім повідомленням! | Do you find the posts helpful? "LIKE" these posts!
Находите сообщения полезными? Поставьте "НРАВИТСЯ" этим сообщениям!
На ваше запитання відповіли? Натисніть кнопку "ПРИЙНЯТИ РІШЕННЯ" | Have your question been answered successfully? Click "ACCEPT SOLUTION" button.
На ваш вопрос успешно ответили? Нажмите кнопку "УТВЕРДИТЬ РЕШЕНИЕ"


Alexander Rivilis / Александр Ривилис / Олександр Рівіліс
Programmer & Teacher & Helper / Программист - Учитель - Помощник / Програміст - вчитель - помічник
Facebook | Twitter | LinkedIn
Expert Elite Member

0 Likes
Message 13 of 13

Wittekamp
Contributor
Contributor

Thanx a lot!

This works like a charm. Smiley Happy

0 Likes