Тема: При вставке блока теряются атрибуты

Привет, коллеги! Помогите разобраться в чем может быть дело.
В некоем файле есть блок, в котором задан атрибут с тагом
"LIST_NUMBER". При вставке этого блока в текущий документ, этот аттрибут пропадает. Вот код:

using System;
using System.Collections.Generic;
using System.Text;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using AcadApplic = Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;
namespace Sapr
{
    class Class1
    {
        static void addFormat()
        {
            AcadApplic.Document doc = AcadApplic.Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            string fname = @"C:\A3.dwg";
            if (!System.IO.File.Exists(fname))
                fname = HostApplicationServices.Current.FindFile(fname, doc.Database, FindFileHint.Default);
            using (Database db = new Database(false, false))
            {
                //читаем файл форматки
                db.ReadDwgFile(fname, System.IO.FileShare.Read, true, null);
                using (Transaction t = doc.TransactionManager.StartTransaction())
                {
                    //вставляем в базу
                    ObjectId idBTR = doc.Database.Insert("FormatA3", db, true);
                    BlockTable bt = (BlockTable)t.GetObject(doc.Database.BlockTableId, OpenMode.ForRead);
                    BlockTableRecord btr = (BlockTableRecord)t.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite);
                    try
                    {
                        using (BlockReference bref = new BlockReference(new Point3d(0, 0, 0), idBTR))
                        {
                            btr.AppendEntity(bref);
                            t.AddNewlyCreatedDBObject(bref, true);
                            foreach (ObjectId id in bref.AttributeCollection) //коллекция всегда пуста!!!
                            {
                                Entity ent = (Entity)t.GetObject(id, OpenMode.ForWrite);
                                if (ent is AttributeReference)
                                {
                                    AttributeReference attRef = (AttributeReference)ent;
                                    if (attRef.Tag.ToUpper() == "LIST_NUMBER")
                                    {
                                        attRef.TextString = "some number";
                                    }
                                }
                            }
                        }
                    }
                    catch (System.Exception ex)
                    {
                        Helper.Message(ex);
                    }
                    t.Commit();
                }
            }
        }
    }
}

Re: При вставке блока теряются атрибуты

Набор функций от Tony Tanzillo:

#region Insert
/// <summary>
/// Inserts all attributreferences
/// </summary>
/// <param name="blkRef">Blockreference to append the attributes</param>
public static void InsertBlockAttibuteRef(BlockReference blkRef)
{
  Database dbCurrent = HostApplicationServices.WorkingDatabase;
  Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = dbCurrent.TransactionManager;
  using (Transaction tr = tm.StartTransaction())
  {
    BlockTableRecord btAttRec = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
    foreach (ObjectId idAtt in btAttRec)
    {
      Entity ent = (Entity)tr.GetObject(idAtt, OpenMode.ForRead);
      if (ent is AttributeDefinition)
      {
        AttributeDefinition attDef = (AttributeDefinition)ent;
        AttributeReference attRef = new AttributeReference();
        attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
        ObjectId idTemp = blkRef.AttributeCollection.AppendAttribute(attRef);
        tr.AddNewlyCreatedDBObject(attRef, true);
      }
    }
    tr.Commit();
  }
}
/// <summary>
/// Inserts all attributreferences
/// </summary>
/// <param name="blkRef">Blockreference to append the attributes</param>
/// <param name="tr">Transaction</param>
public static void InsertBlockAttibuteRef(BlockReference blkRef, Transaction tr)
{
  BlockTableRecord btAttRec = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  foreach (ObjectId idAtt in btAttRec)
  {
    Entity ent = (Entity)tr.GetObject(idAtt, OpenMode.ForRead);
    if (ent is AttributeDefinition)
    {
      AttributeDefinition attDef = (AttributeDefinition)ent;
      AttributeReference attRef = new AttributeReference();
      attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
      ObjectId idTemp = blkRef.AttributeCollection.AppendAttribute(attRef);
      tr.AddNewlyCreatedDBObject(attRef, true);
    }
  }
}
/// <summary>
/// Inserts all attributreferences
/// </summary>
/// <param name="blkRef">Blockreference to append the attributes</param>
/// <param name="strAttributeText">The textstring for all attributes</param>
public static void InsertBlockAttibuteRef(BlockReference blkRef, string strAttributeText)
{
  Database dbCurrent = HostApplicationServices.WorkingDatabase;
  Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = dbCurrent.TransactionManager;
  using (Transaction tr = tm.StartTransaction())
  {
    BlockTableRecord btAttRec = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
    foreach (ObjectId idAtt in btAttRec)
    {
      Entity ent = (Entity)tr.GetObject(idAtt, OpenMode.ForRead);
      if (ent is AttributeDefinition)
      {
        AttributeDefinition attDef = (AttributeDefinition)ent;
        AttributeReference attRef = new AttributeReference();
        attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
        attRef.TextString = strAttributeText;
        ObjectId idTemp = blkRef.AttributeCollection.AppendAttribute(attRef);
        tr.AddNewlyCreatedDBObject(attRef, true);
      }
    }
    tr.Commit();
  }
}
/// <summary>
/// Inserts all attributreferences
/// </summary>
/// <param name="blkRef">Blockreference to append the attributes</param>
/// <param name="strAttributeText">The textstring for all attributes</param>
/// <param name="tr">Transaction</param>
public static void InsertBlockAttibuteRef(BlockReference blkRef, string strAttributeText, Transaction tr)
{
  BlockTableRecord btAttRec = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  foreach (ObjectId idAtt in btAttRec)
  {
    Entity ent = (Entity)tr.GetObject(idAtt, OpenMode.ForRead);
    if (ent is AttributeDefinition)
    {
      AttributeDefinition attDef = (AttributeDefinition)ent;
      AttributeReference attRef = new AttributeReference();
      attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
      attRef.TextString = strAttributeText;
      ObjectId idTemp = blkRef.AttributeCollection.AppendAttribute(attRef);
      tr.AddNewlyCreatedDBObject(attRef, true);
    }
  }
}
/// <summary>
/// Inserts all attributreferences
/// </summary>
/// <param name="blkRef">Blockreference to append the attributes</param>
/// <param name="strAttributeTag">The tag to insert the <paramref name="strAttributeText"/></param>
/// <param name="strAttributeText">The textstring for <paramref name="strAttributeTag"/></param>
public static void InsertBlockAttibuteRef(BlockReference blkRef, string strAttributeTag, string strAttributeText)
{
  Database dbCurrent = HostApplicationServices.WorkingDatabase;
  Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = dbCurrent.TransactionManager;
  using (Transaction tr = tm.StartTransaction())
  {
    BlockTableRecord btAttRec = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
    foreach (ObjectId idAtt in btAttRec)
    {
      Entity ent = (Entity)tr.GetObject(idAtt, OpenMode.ForRead);
      if (ent is AttributeDefinition)
      {
        AttributeDefinition attDef = (AttributeDefinition)ent;
        AttributeReference attRef = new AttributeReference();
        attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
        if (attRef.Tag == strAttributeTag)
          attRef.TextString = strAttributeText;
        ObjectId idTemp = blkRef.AttributeCollection.AppendAttribute(attRef);
        tr.AddNewlyCreatedDBObject(attRef, true);
      }
    }
    tr.Commit();
  }
}
/// <summary>
/// Inserts all attributreferences
/// </summary>
/// <param name="blkRef">Blockreference to append the attributes</param>
/// <param name="strAttributeTag">The tag to insert the <paramref name="strAttributeText"/></param>
/// <param name="strAttributeText">The textstring for <paramref name="strAttributeTag"/></param>
/// <param name="tr">Transacton</param>
public static void InsertBlockAttibuteRef(BlockReference blkRef, string strAttributeTag, string strAttributeText, Transaction tr)
{
  BlockTableRecord btAttRec = (BlockTableRecord)tr.GetObject(blkRef.BlockTableRecord, OpenMode.ForRead);
  foreach (ObjectId idAtt in btAttRec)
  {
    Entity ent = (Entity)tr.GetObject(idAtt, OpenMode.ForRead);
    if (ent is AttributeDefinition)
    {
      AttributeDefinition attDef = (AttributeDefinition)ent;
      AttributeReference attRef = new AttributeReference();
      attRef.SetAttributeFromBlock(attDef, blkRef.BlockTransform);
      if (attRef.Tag == strAttributeTag)
        attRef.TextString = strAttributeText;
      ObjectId idTemp = blkRef.AttributeCollection.AppendAttribute(attRef);
      tr.AddNewlyCreatedDBObject(attRef, true);
    }
  }
}
#endregion

Re: При вставке блока теряются атрибуты

P.S.: Чтобы было понятно создание вставки блока (BlockReference) не приводит к автоматическому созданию атрибутов (AttribAttributeReference) в отличие от команды AutoCAD INSERT. Поэтому атрибуты нужно создать программно, при помощи функции InsertBlockAttibuteRef или аналогично ей.

Re: При вставке блока теряются атрибуты

При вставке блока с атрибутами с помощью указанных выше функций вставка происходит хорошо, но параметры у вставленных атрибутов все нулевые (точка вставки, высота текста, ширина текста и т.д.) и их не видно совсем (но в редакторе аттрибутов они видны)

Программирую для AutoCAD 2005 на C# в SharpDevelop 2.2.1 (.NET 1.1)

                    if (bOld)
                    {
                        string sNewName = "title" + VERSION + (blkName.StartsWith("г") ? "land" : "port");
                        string sNewFile = "";

                        using (Transaction tr1 = db.TransactionManager.StartTransaction())
                        {
                            BlockReference brefOld = (BlockReference)blk.Open(OpenMode.ForWrite, false);
                            ptLocation = brefOld.Position;
                            brefOld.Erase(true);
                            brefOld.Dispose();
                            db.Purge(new ObjectIdCollection(new ObjectId[] { blk }));
                            tr1.Commit();
                        }

                        BlockTable bt = (BlockTable)db.BlockTableId.Open(OpenMode.ForRead, false);
                        if (bt.Has(sNewName))
                        {
                            blkId = bt[sNewName];
                        }
                        else
                        {
                            RegistryKey rk = Registry.CurrentUser.OpenSubKey(atbAreas.MY_REGKEY, false);
                            if (rk != null)
                            {
                                sNewFile = (string)rk.GetValue("BASES", "");
                                rk.Close();
                            }
                            if (sNewFile == "")
                            {
                                MessageBox.Show("Не могу найти путь к новому блоку!", "Ошибка замены рамки", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                return;
                            }
                            if (!sNewFile.EndsWith("\\")) sNewFile += "\\";
                            sNewFile += "Insert\\" + sNewName + ".dwg";
                            if (!File.Exists(sNewFile))
                            {
                                MessageBox.Show("Не могу найти новую рамку!", "Ошибка замены рамки", MessageBoxButtons.OK, MessageBoxIcon.Error);
                                return;
                            }
                            using (Database dbFile = new Database(false, true))
                            {
                                dbFile.ReadDwgFile(sNewFile, FileShare.Read, true, "");
                                blkId = db.Insert(sNewName, dbFile, false);
                            }
                        }
                        bt.Close();
                        using (Transaction tr2 = db.TransactionManager.StartTransaction())
                        {
                            BlockReference brefNew = new BlockReference(ptLocation, blkId);
                            brefNew.ScaleFactors.Set(1, 1, 1);
                            brefNew.Layer = "Border";
                            //brefNew.Linetype = "";
                            BlockTableRecord btr = (BlockTableRecord)db.CurrentSpaceId.Open(OpenMode.ForWrite, false);
                            if (btr != null)
                            {
                                btr.AppendEntity(brefNew);
                                blk = brefNew.Id;
                                tr2.TransactionManager.AddNewlyCreatedDBObject(brefNew, true);
                                btr.Close();
                            }
                            brefNew.Close();
                            tr2.Commit();
                        }
                        using (Transaction tr3 = db.TransactionManager.StartTransaction())
                        {
                            BlockReference brefNew = (BlockReference)tr3.GetObject(blk, OpenMode.ForWrite);
                            BlockTableRecord btrA = (BlockTableRecord)tr3.GetObject(brefNew.BlockTableRecord, OpenMode.ForRead);
                            foreach (ObjectId idAtt in btrA)
                            {
                                Entity ent = (Entity)tr3.GetObject(idAtt, OpenMode.ForRead);
                                if (ent is AttributeDefinition)
                                {
                                    AttributeDefinition attDef = (AttributeDefinition)ent;
                                    AttributeReference att = new AttributeReference();
                                    att.SetAttributeFromBlock(attDef, brefNew.BlockTransform);
                                    FillAttribute(ref att);
                                    att.TextStyle = attDef.TextStyle;
                                    att.Position = attDef.Position;
                                    att.Position.TransformBy(brefNew.BlockTransform);
                                    ObjectId idTemp = brefNew.AppendAttribute(att);
                                    tr3.TransactionManager.AddNewlyCreatedDBObject(att, true);
                                }
                            }
                            btrA.Close();
                            brefNew.Close();
                            tr3.Commit();
                        }
                    }

Данный кусок кода должен заменять рамку(штамп) старого формата, на новую, из внешнего файла, который весь целиком нужно преобразовать в блок.
Фунция FillAttribute(ref att) - подставляет значения в att.TextString в зависимости от att.Tаg
из параметров класса

Re: При вставке блока теряются атрибуты

Здравствйте уважаемые формумчане. Помогите пожалуйста мне с одним вопросом.
Есть код на С# вставки блока. Принцип работы такой. При наборе команды проверяется наличие блока в чертеже, если нет то, просит файл с блоками и копирует его блоки в текущий чертеж. При повторном выполнении команды блок есть в базе и создается на его основе (создается его екземпляр) и всавляется в чертеж. Однако если очистить чертеж т.е. сделать purge, повторно загрузить блоки из файла, то при вставке блока в чертеж выдает ошибку о том, что объект удален, хотя он есть в чертеже. Возникает такое ошущение что база чертежа не обновилась после purge и копировании блоков из другово чертежа и использует старую базу до удаления. В чем может быть ошибка? Устал уже голову ломать, а проблема требет решения.

 

 [CommandMethod("q1")]
        public void test1()
         {
            Point3d nt;
            GetPoint(out nt, "\nВведите точку: ");
            AddBlock("BLOCKNAME", nt, 1, 0);
        }

public static void AddBlock(string block_name, Point3d base_point, 
            double scale_XYZ, double angle)
        {
            //String dir = Environment.CurrentDirectory;
            DocumentCollection dm = Application.DocumentManager;
            Editor ed = dm.MdiActiveDocument.Editor;
            Database db = dm.MdiActiveDocument.Database;

            using (Transaction tx = db.TransactionManager.StartTransaction())
            {
                BlockTable blockTable = (BlockTable)tx.GetObject(db.BlockTableId, OpenMode.ForRead);
                BlockReference RefBlock;
                if (blockTable.Has(block_name))
                {
                    RefBlock = new BlockReference(base_point, blockTable[block_name]);
                    BlockTableRecord btr = (BlockTableRecord)tx.GetObject(db.CurrentSpaceId, OpenMode.ForWrite);
                    RefBlock.ScaleFactors = new Scale3d(scale_XYZ);
                    RefBlock.Rotation = angle;
                    btr.AppendEntity(RefBlock);
                    tx.AddNewlyCreatedDBObject(RefBlock, true);
                    
                    //InsertBlockAttibuteRef(RefBlock);
                    tx.Commit();
                    return;
                }
                tx.Commit();
            }


            Database sourceDb = new Database(false, true);
            //PromptResult sourceFileName;
            try
            {
                // Get name of DWG from which to copy blocks
                //sourceFileName = ed.GetString("\nEnter the name of the source drawing: ");

                System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
                ofd.Filter = "DWG файлы|*.dwg*";
                if (ofd.ShowDialog() != System.Windows.Forms.DialogResult.OK)
                    return;
                string file = ofd.FileName;


                // Read the DWG into a side database
                sourceDb.ReadDwgFile(file, System.IO.FileShare.Read, true, "");
                // Create a variable to store the list of block identifiers
                ObjectIdCollection blockIds = new ObjectIdCollection();
                Autodesk.AutoCAD.DatabaseServices.TransactionManager tm = sourceDb.TransactionManager;
                using (Transaction myT = tm.StartTransaction())
                {
                    // Open the block table
                    BlockTable bt = (BlockTable)tm.GetObject(sourceDb.BlockTableId, OpenMode.ForRead, false);
                    // Check each block in the block table
                    foreach (ObjectId btrId in bt)
                    {
                        BlockTableRecord btr = (BlockTableRecord)tm.GetObject(btrId, OpenMode.ForRead, false);
                        // Only add named & non-layout blocks to the copy list
                        if (!btr.IsAnonymous && !btr.IsLayout)
                            blockIds.Add(btrId);
                        btr.Dispose();
                    }
                }

                // Copy blocks from source to destination database

                IdMapping mapping = new IdMapping();
                sourceDb.WblockCloneObjects(blockIds, db.BlockTableId, mapping,
                    DuplicateRecordCloning.Replace, false);
                ed.WriteMessage("\nCopied " + blockIds.Count.ToString()
                    + " block definitions from " + file + " to the current drawing.");
            }

            catch (Autodesk.AutoCAD.Runtime.Exception ex)
            {
                ed.WriteMessage("\nError during copy: " + ex.Message);
            }
            sourceDb.Dispose();
        }