Обновление всех атрибутов блока (Программно заменить команду АТРОБНОВИТЬ)

Автор Тема: Обновление всех атрибутов блока (Программно заменить команду АТРОБНОВИТЬ)  (Прочитано 11079 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Суть такова, я пытаюсь заменить блоки на чертеже. Готовый блок с атрибутами лежит в другом файле (и в проекте и в шаблоне у блоков одинаковые названия). Я успешно вынимаю его оттуда и помещаю в свою модель. После чего делаю UpdateAnonymousBlocks.

На чертеже изменяется вид блоков, но атрибуты остаются исходными, при этом, если зайти в "диспетчер атрибутов блока" и посмотреть на добавленный, все его атрибуты изменены.

Для замены мне необходимо нажать кнопку "обновить" в   "диспетчер атрибутов блока". Как можно программно реализовать переназначение, чтобы не нажимать эту клавишу?

Код метода:

Код - C# [Выбрать]
  1. [CommandMethod("LoadingData")]
  2. public void LoadingDataInProjeсt()
  3. {
  4.  
  5.     Document doc = acadApp.DocumentManager.MdiActiveDocument;
  6.     Database db = doc.Database;
  7.     Editor ed = doc.Editor;
  8.  
  9.     string blockName = "BearingBlock";
  10.  
  11.     using (Database sourceDb = new Database(false, true))
  12.     {
  13.  
  14.         var fileContent = string.Empty;
  15.         var filePath = string.Empty;
  16.  
  17.         using (OpenFileDialog openFileDialog = new OpenFileDialog())
  18.         {
  19.  
  20.             openFileDialog.InitialDirectory = "c:\\";
  21.             openFileDialog.Filter = "dwg files (*.dwg)|*.dwg|All files (*.*)|*.*";
  22.             openFileDialog.FilterIndex = 2;
  23.             openFileDialog.RestoreDirectory = true;
  24.  
  25.             if (openFileDialog.ShowDialog() == DialogResult.OK)
  26.             {
  27.                 filePath = openFileDialog.FileName;
  28.             }
  29.         }
  30.  
  31.         sourceDb.ReadDwgFile(filePath, System.IO.FileShare.ReadWrite, true, "");
  32.         ObjectIdCollection ids = new ObjectIdCollection();
  33.         using (Transaction tr = sourceDb.TransactionManager.StartTransaction())
  34.         {
  35.             BlockTable bt = (BlockTable)tr.GetObject(sourceDb.BlockTableId, OpenMode.ForRead);
  36.             if (bt.Has(blockName))
  37.             {
  38.                 ids.Add(bt[blockName]);
  39.             }
  40.             tr.Commit();
  41.         }
  42.  
  43.         if (ids.Count != 0)
  44.         {
  45.             IdMapping iMap = new IdMapping();
  46.             db.WblockCloneObjects(ids, db.BlockTableId, iMap, DuplicateRecordCloning.Replace, false);
  47.         }
  48.         else return;
  49.     }
  50.  
  51.     using (Transaction tr = db.TransactionManager.StartTransaction())
  52.     {
  53.  
  54.         BlockTable bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  55.         bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable;
  56.  
  57.         foreach (ObjectId objId in bt)
  58.         {
  59.             var btr = objId.GetObject(OpenMode.ForRead) as BlockTableRecord;
  60.             if (btr.Name == blockName)
  61.             {
  62.                 btr.UpdateAnonymousBlocks();
  63.                        
  64.                 //АТРОБНОВИТЬ !!!
  65.  
  66.             }
  67.         }
  68.         tr.Commit();
  69.     }
  70. }

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Приветствую на форуме!
Есть известные два варианта кода, которые на C# эмулируют команду _ATTSYNC (АТРОБНОВИТЬ в русской локализации)
Первый от Андрея Бушмана: https://sites.google.com/site/bushmansnetlaboratory/moi-zametki/attsynch (к сожалению сайт сейчас недоступен, но есть в https://web.archive.org/web/20190211224901/https://sites.google.com/site/bushmansnetlaboratory/moi-zametki/attsynch )

С разрешения Андрея Бушмана выкладываю здесь:

Код - C# [Выбрать]
  1. using System;
  2.  
  3. using Autodesk.AutoCAD.DatabaseServices;
  4.  
  5.  
  6.  
  7. namespace Bushman.AutoCAD.DatabaseServices {
  8.  
  9.  
  10.  
  11.     /// <summary>
  12.  
  13.     /// Изменяя базу данных чертежей, очень важно контролировать то, какая база данных является текущей.
  14.  
  15.     /// Класс <c>WorkingDatabaseSwitcher</c>
  16.  
  17.     /// берёт на себя контроль над тем, чтобы текущей была именно та база данных, которая нужна.
  18.  
  19.     /// </summary>
  20.  
  21.     /// <example>
  22.  
  23.     /// Пример использования класса:
  24.  
  25.     /// <code>
  26.  
  27.     /// //db - объект Database
  28.  
  29.     /// using (WorkingDatabaseSwitcher hlp = new WorkingDatabaseSwitcher(db)) {
  30.  
  31.     ///     // тут наш код</code>
  32.  
  33.     /// }</example>
  34.  
  35.     public sealed class WorkingDatabaseSwitcher : IDisposable {
  36.  
  37.         private Database prevDb = null;
  38.  
  39.  
  40.  
  41.         /// <summary>
  42.  
  43.         /// База данных, в контексте которой должна производиться работа. Эта база данных на время становится текущей.
  44.  
  45.         /// По завершению работы текущей станет та база, которая была ею до этого.
  46.  
  47.         /// </summary>
  48.  
  49.         /// <param name="db">База данных, которая должна быть установлена текущей</param>
  50.  
  51.         public WorkingDatabaseSwitcher(Database db) {
  52.  
  53.             prevDb = HostApplicationServices.WorkingDatabase;
  54.  
  55.             HostApplicationServices.WorkingDatabase = db;
  56.  
  57.         }
  58.  
  59.  
  60.  
  61.         /// <summary>
  62.  
  63.         /// Возвращаем свойству <c>HostApplicationServices.WorkingDatabase</c> прежнее значение
  64.  
  65.         /// </summary>
  66.  
  67.         public void Dispose() {
  68.  
  69.             HostApplicationServices.WorkingDatabase = prevDb;
  70.  
  71.         }
  72.  
  73.     }
  74.  
  75. }

Код - C# [Выбрать]
  1. //Microsoft
  2.  
  3. using System;
  4.  
  5. using System.Collections.Generic;
  6.  
  7. using System.Collections;
  8.  
  9. using System.Linq;
  10.  
  11. using System.Text;
  12.  
  13. using System.ComponentModel;
  14.  
  15. using System.Globalization;
  16.  
  17. //AutoCAD
  18.  
  19. using acad = Autodesk.AutoCAD.ApplicationServices.Application;
  20.  
  21. using Autodesk.AutoCAD.ApplicationServices;
  22.  
  23. using Autodesk.AutoCAD.DatabaseServices;
  24.  
  25. using Autodesk.AutoCAD.EditorInput;
  26.  
  27. using Autodesk.AutoCAD.Runtime;
  28.  
  29. using Autodesk.AutoCAD.Geometry;
  30.  
  31.  
  32.  
  33. namespace Bushman.AutoCAD.DatabaseServices {
  34.  
  35.     /// <summary>
  36.  
  37.     /// Методы расширений для объектов класса Autodesk.AutoCAD.DatabaseServices.BlockTableRecord
  38.  
  39.     /// </summary>
  40.  
  41.     public static class BlockTableRecordExtensionMethods {
  42.  
  43.         /// <summary>
  44.  
  45.         /// Синхронизация вхождений блоков с их определением
  46.  
  47.         /// </summary>
  48.  
  49.         /// <param name="btr">Запись таблицы блоков, принятая за определение блока</param>
  50.  
  51.         /// <param name="directOnly">Следует ли искать только на верхнем уровне, или же нужно
  52.  
  53.         /// анализировать и вложенные вхождения, т.е. следует ли рекурсивно обрабатывать блок в блоке:
  54.  
  55.         /// true - только верхний; false - рекурсивно проверять вложенные блоки.</param>
  56.  
  57.         /// <param name="removeSuperfluous">
  58.  
  59.         /// Следует ли во вхождениях блока удалять лишние атрибуты (те, которых нет в определении блока).</param>
  60.  
  61.         /// <param name="setAttDefValues">
  62.  
  63.         /// Следует ли всем атрибутам, во вхождениях блока, назначить текущим значением значение по умолчанию.</param>
  64.  
  65.         public static void AttSync(this BlockTableRecord btr, bool directOnly, bool removeSuperfluous, bool setAttDefValues) {
  66.  
  67.             Database db = btr.Database;
  68.  
  69.             using (WorkingDatabaseSwitcher wdb = new WorkingDatabaseSwitcher(db)) {
  70.  
  71.                 using (Transaction t = db.TransactionManager.StartTransaction()) {
  72.  
  73.                     BlockTable bt = (BlockTable) t.GetObject(db.BlockTableId, OpenMode.ForRead);
  74.  
  75.  
  76.  
  77.                     //Получаем все определения атрибутов из определения блока
  78.  
  79.                     IEnumerable<AttributeDefinition> attdefs = btr.Cast<ObjectId>()
  80.  
  81.                         .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition")
  82.  
  83.                         .Select(n => (AttributeDefinition) t.GetObject(n, OpenMode.ForRead))
  84.  
  85.                         .Where(n => !n.Constant);//Исключаем константные атрибуты, т.к. для них AttributeReference не создаются.
  86.  
  87.  
  88.  
  89.                     //В цикле перебираем все вхождения искомого определения блока
  90.  
  91.                     foreach (ObjectId brId in btr.GetBlockReferenceIds(directOnly, false)) {
  92.  
  93.                         BlockReference br = (BlockReference) t.GetObject(brId, OpenMode.ForWrite);
  94.  
  95.  
  96.  
  97.                         //Проверяем имена на соответствие. В том случае, если вхождение блока "A" вложено в определение блока "B",
  98.  
  99.                         //то вхождения блока "B" тоже попадут в выборку. Нам нужно их исключить из набора обрабатываемых объектов
  100.  
  101.                         //- именно поэтому проверяем имена.
  102.  
  103.                         if (br.Name != btr.Name)
  104.  
  105.                             continue;
  106.  
  107.  
  108.  
  109.                         //Получаем все атрибуты вхождения блока
  110.  
  111.                         IEnumerable<AttributeReference> attrefs = br.AttributeCollection.Cast<ObjectId>()
  112.  
  113.                             .Select(n => (AttributeReference) t.GetObject(n, OpenMode.ForWrite));
  114.  
  115.  
  116.  
  117.                         //Тэги существующих определений атрибутов
  118.  
  119.                         IEnumerable<string> dtags = attdefs.Select(n => n.Tag);
  120.  
  121.                         //Тэги существующих атрибутов во вхождении
  122.  
  123.                         IEnumerable<string> rtags = attrefs.Select(n => n.Tag);
  124.  
  125.  
  126.  
  127.                         //Если требуется - удаляем те атрибуты, для которых нет определения
  128.  
  129.                         //в составе определения блока
  130.  
  131.                         if (removeSuperfluous)
  132.  
  133.                             foreach (AttributeReference attref in attrefs.Where(n => rtags
  134.  
  135.                                 .Except(dtags).Contains(n.Tag)))
  136.  
  137.                                 attref.Erase(true);
  138.  
  139.  
  140.  
  141.                         //Свойства существующих атрибутов синхронизируем со свойствами их определений
  142.  
  143.                         foreach (AttributeReference attref in attrefs.Where(n => dtags
  144.  
  145.                             .Join(rtags, a => a, b => b, (a, b) => a).Contains(n.Tag))) {
  146.  
  147.                             AttributeDefinition ad = attdefs.First(n => n.Tag == attref.Tag);
  148.  
  149.  
  150.  
  151.                             //Метод SetAttributeFromBlock, используемый нами далее в коде, сбрасывает
  152.  
  153.                             //текущее значение многострочного атрибута. Поэтому запоминаем это значение,
  154.  
  155.                             //чтобы восстановить его сразу после вызова SetAttributeFromBlock.
  156.  
  157.                             string value = attref.TextString;
  158.  
  159.                             attref.SetAttributeFromBlock(ad, br.BlockTransform);
  160.  
  161.                             //Восстанавливаем значение атрибута
  162.  
  163.                             attref.TextString = value;
  164.  
  165.  
  166.  
  167.                             if (attref.IsMTextAttribute) {
  168.  
  169.  
  170.  
  171.                             }
  172.  
  173.  
  174.  
  175.                             //Если требуется - устанавливаем для атрибута значение по умолчанию
  176.  
  177.                             if (setAttDefValues)
  178.  
  179.                                 attref.TextString = ad.TextString;
  180.  
  181.  
  182.  
  183.                             attref.AdjustAlignment(db);
  184.  
  185.                         }
  186.  
  187.  
  188.  
  189.                         //Если во вхождении блока отсутствуют нужные атрибуты - создаём их
  190.  
  191.                         IEnumerable<AttributeDefinition> attdefsNew = attdefs.Where(n => dtags
  192.  
  193.                             .Except(rtags).Contains(n.Tag));
  194.  
  195.  
  196.  
  197.                         foreach (AttributeDefinition ad in attdefsNew) {
  198.  
  199.                             AttributeReference attref = new AttributeReference();
  200.  
  201.                             attref.SetAttributeFromBlock(ad, br.BlockTransform);
  202.  
  203.                             attref.AdjustAlignment(db);
  204.  
  205.                             br.AttributeCollection.AppendAttribute(attref);
  206.  
  207.                             t.AddNewlyCreatedDBObject(attref, true);
  208.  
  209.                         }
  210.  
  211.                     }
  212.  
  213.                     btr.UpdateAnonymousBlocks();
  214.  
  215.                     t.Commit();
  216.  
  217.                 }
  218.  
  219.                 //Если это динамический блок
  220.  
  221.                 if (btr.IsDynamicBlock) {
  222.  
  223.                     using (Transaction t = db.TransactionManager.StartTransaction()) {
  224.  
  225.                         foreach (ObjectId id in btr.GetAnonymousBlockIds()) {
  226.  
  227.                             BlockTableRecord _btr = (BlockTableRecord) t.GetObject(id, OpenMode.ForWrite);
  228.  
  229.  
  230.  
  231.                             //Получаем все определения атрибутов из оригинального определения блока
  232.  
  233.                             IEnumerable<AttributeDefinition> attdefs = btr.Cast<ObjectId>()
  234.  
  235.                                 .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition")
  236.  
  237.                                 .Select(n => (AttributeDefinition) t.GetObject(n, OpenMode.ForRead));
  238.  
  239.  
  240.  
  241.                             //Получаем все определения атрибутов из определения анонимного блока
  242.  
  243.                             IEnumerable<AttributeDefinition> attdefs2 = _btr.Cast<ObjectId>()
  244.  
  245.                                 .Where(n => n.ObjectClass.Name == "AcDbAttributeDefinition")
  246.  
  247.                                 .Select(n => (AttributeDefinition) t.GetObject(n, OpenMode.ForWrite));
  248.  
  249.  
  250.  
  251.                             //Определения атрибутов анонимных блоков следует синхронизировать
  252.  
  253.                             //с определениями атрибутов основного блока
  254.  
  255.  
  256.  
  257.                             //Тэги существующих определений атрибутов
  258.  
  259.                             IEnumerable<string> dtags = attdefs.Select(n => n.Tag);
  260.  
  261.                             IEnumerable<string> dtags2 = attdefs2.Select(n => n.Tag);
  262.  
  263.  
  264.  
  265.                             //1. Удаляем лишние
  266.  
  267.                             foreach (AttributeDefinition attdef in attdefs2.Where(n => !dtags.Contains(n.Tag))) {
  268.  
  269.                                 attdef.Erase(true);
  270.  
  271.                             }
  272.  
  273.  
  274.  
  275.                             //2. Синхронизируем существующие
  276.  
  277.                             foreach (AttributeDefinition attdef in attdefs.Where(n => dtags
  278.  
  279.                                 .Join(dtags2, a => a, b => b, (a, b) => a).Contains(n.Tag))) {
  280.  
  281.                                 AttributeDefinition ad = attdefs2.First(n => n.Tag == attdef.Tag);
  282.  
  283.                                 ad.Position = attdef.Position;
  284.  
  285.                                 ad.TextStyle = attdef.TextStyle;
  286.  
  287.                                 //Если требуется - устанавливаем для атрибута значение по умолчанию
  288.  
  289.                                 if (setAttDefValues)
  290.  
  291.                                     ad.TextString = attdef.TextString;
  292.  
  293.  
  294.  
  295.                                 ad.Tag = attdef.Tag;
  296.  
  297.                                 ad.Prompt = attdef.Prompt;
  298.  
  299.  
  300.  
  301.                                 ad.LayerId = attdef.LayerId;
  302.  
  303.                                 ad.Rotation = attdef.Rotation;
  304.  
  305.                                 ad.LinetypeId = attdef.LinetypeId;
  306.  
  307.                                 ad.LineWeight = attdef.LineWeight;
  308.  
  309.                                 ad.LinetypeScale = attdef.LinetypeScale;
  310.  
  311.                                 ad.Annotative = attdef.Annotative;
  312.  
  313.                                 ad.Color = attdef.Color;
  314.  
  315.                                 ad.Height = attdef.Height;
  316.  
  317.                                 ad.HorizontalMode = attdef.HorizontalMode;
  318.  
  319.                                 ad.Invisible = attdef.Invisible;
  320.  
  321.                                 ad.IsMirroredInX = attdef.IsMirroredInX;
  322.  
  323.                                 ad.IsMirroredInY = attdef.IsMirroredInY;
  324.  
  325.                                 ad.Justify = attdef.Justify;
  326.  
  327.                                 ad.LockPositionInBlock = attdef.LockPositionInBlock;
  328.  
  329.                                 ad.MaterialId = attdef.MaterialId;
  330.  
  331.                                 ad.Oblique = attdef.Oblique;
  332.  
  333.                                 ad.Thickness = attdef.Thickness;
  334.  
  335.                                 ad.Transparency = attdef.Transparency;
  336.  
  337.                                 ad.VerticalMode = attdef.VerticalMode;
  338.  
  339.                                 ad.Visible = attdef.Visible;
  340.  
  341.                                 ad.WidthFactor = attdef.WidthFactor;
  342.  
  343.  
  344.  
  345.                                 ad.CastShadows = attdef.CastShadows;
  346.  
  347.                                 ad.Constant = attdef.Constant;
  348.  
  349.                                 ad.FieldLength = attdef.FieldLength;
  350.  
  351.                                 ad.ForceAnnoAllVisible = attdef.ForceAnnoAllVisible;
  352.  
  353.                                 ad.Preset = attdef.Preset;
  354.  
  355.                                 ad.Prompt = attdef.Prompt;
  356.  
  357.                                 ad.Verifiable = attdef.Verifiable;
  358.  
  359.  
  360.  
  361.                                 ad.AdjustAlignment(db);
  362.  
  363.                             }
  364.  
  365.  
  366.  
  367.                             //3. Добавляем недостающие
  368.  
  369.                             foreach (AttributeDefinition attdef in attdefs.Where(n => !dtags2.Contains(n.Tag))) {
  370.  
  371.                                 AttributeDefinition ad = new AttributeDefinition();
  372.  
  373.                                 ad.SetDatabaseDefaults();
  374.  
  375.                                 ad.Position = attdef.Position;
  376.  
  377.                                 ad.TextStyle = attdef.TextStyle;
  378.  
  379.                                 ad.TextString = attdef.TextString;
  380.  
  381.                                 ad.Tag = attdef.Tag;
  382.  
  383.                                 ad.Prompt = attdef.Prompt;
  384.  
  385.  
  386.  
  387.                                 ad.LayerId = attdef.LayerId;
  388.  
  389.                                 ad.Rotation = attdef.Rotation;
  390.  
  391.                                 ad.LinetypeId = attdef.LinetypeId;
  392.  
  393.                                 ad.LineWeight = attdef.LineWeight;
  394.  
  395.                                 ad.LinetypeScale = attdef.LinetypeScale;
  396.  
  397.                                 ad.Annotative = attdef.Annotative;
  398.  
  399.                                 ad.Color = attdef.Color;
  400.  
  401.                                 ad.Height = attdef.Height;
  402.  
  403.                                 ad.HorizontalMode = attdef.HorizontalMode;
  404.  
  405.                                 ad.Invisible = attdef.Invisible;
  406.  
  407.                                 ad.IsMirroredInX = attdef.IsMirroredInX;
  408.  
  409.                                 ad.IsMirroredInY = attdef.IsMirroredInY;
  410.  
  411.                                 ad.Justify = attdef.Justify;
  412.  
  413.                                 ad.LockPositionInBlock = attdef.LockPositionInBlock;
  414.  
  415.                                 ad.MaterialId = attdef.MaterialId;
  416.  
  417.                                 ad.Oblique = attdef.Oblique;
  418.  
  419.                                 ad.Thickness = attdef.Thickness;
  420.  
  421.                                 ad.Transparency = attdef.Transparency;
  422.  
  423.                                 ad.VerticalMode = attdef.VerticalMode;
  424.  
  425.                                 ad.Visible = attdef.Visible;
  426.  
  427.                                 ad.WidthFactor = attdef.WidthFactor;
  428.  
  429.  
  430.  
  431.                                 ad.CastShadows = attdef.CastShadows;
  432.  
  433.                                 ad.Constant = attdef.Constant;
  434.  
  435.                                 ad.FieldLength = attdef.FieldLength;
  436.  
  437.                                 ad.ForceAnnoAllVisible = attdef.ForceAnnoAllVisible;
  438.  
  439.                                 ad.Preset = attdef.Preset;
  440.  
  441.                                 ad.Prompt = attdef.Prompt;
  442.  
  443.                                 ad.Verifiable = attdef.Verifiable;
  444.  
  445.  
  446.  
  447.                                 _btr.AppendEntity(ad);
  448.  
  449.                                 t.AddNewlyCreatedDBObject(ad, true);
  450.  
  451.                                 ad.AdjustAlignment(db);
  452.  
  453.                             }
  454.  
  455.                             //Синхронизируем все вхождения данного анонимного определения блока
  456.  
  457.                             _btr.AttSync(directOnly, removeSuperfluous, setAttDefValues);
  458.  
  459.                         }
  460.  
  461.                         //Обновляем геометрию определений анонимных блоков, полученных на основе
  462.  
  463.                         //этого динамического блока
  464.  
  465.                         btr.UpdateAnonymousBlocks();
  466.  
  467.                         t.Commit();
  468.  
  469.                     }
  470.  
  471.                 }
  472.  
  473.             }
  474.  
  475.         }
  476.  
  477.     }
  478.  
  479. }

Код - C# [Выбрать]
  1. // Метод для тестов:
  2.  
  3. [CommandMethod("MySynch", CommandFlags.Modal)]
  4.  
  5. public void MySynch() {
  6.  
  7.     Document dwg = acad.DocumentManager.MdiActiveDocument;
  8.  
  9.     Editor ed = dwg.Editor;
  10.  
  11.     Database db = dwg.Database;
  12.  
  13.     TypedValue[] types = new TypedValue[] { new TypedValue((int) DxfCode.Start, "INSERT") };
  14.  
  15.     SelectionFilter sf = new SelectionFilter(types);
  16.  
  17.     PromptSelectionOptions pso = new PromptSelectionOptions();
  18.  
  19.     pso.MessageForAdding = "Select block reference";
  20.  
  21.     pso.SingleOnly = true;
  22.  
  23.     pso.AllowDuplicates = false;
  24.  
  25.    
  26.  
  27.     PromptSelectionResult psr = ed.GetSelection(pso, sf);
  28.  
  29.     //*******************************
  30.  
  31.     if (psr.Status == PromptStatus.OK) {
  32.  
  33.         using (Transaction t = db.TransactionManager.StartTransaction()) {
  34.  
  35.             BlockTable bt = (BlockTable) t.GetObject(db.BlockTableId, OpenMode.ForRead);
  36.  
  37.             BlockReference br = (BlockReference) t.GetObject(psr.Value[0].ObjectId, OpenMode.ForRead);
  38.  
  39.             BlockTableRecord btr = (BlockTableRecord) t.GetObject(bt[br.Name], OpenMode.ForRead);
  40.  
  41.             btr.AttSync(false, true, false);
  42.  
  43.             t.Commit();
  44.  
  45.         }
  46.  
  47.     }
  48.  
  49.     else
  50.  
  51.         ed.WriteMessage("Bad selectionа.\n");
  52.  
  53.     //********************************
  54.  
  55. }


Второй от Gilles Chanteau ( http://www.theswamp.org/index.php?topic=31859.msg508802#msg508802 ):
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.Runtime;
  5. using AcRx = Autodesk.AutoCAD.Runtime;
  6.  
  7. namespace Autodesk.AutoCAD.DatabaseServices
  8. {
  9.     public static class ExtensionMethods
  10.     {
  11.         static RXClass attDefClass = RXClass.GetClass(typeof(AttributeDefinition));
  12.  
  13.         public static void SynchronizeAttributes(this BlockTableRecord target)
  14.         {
  15.             if (target == null)
  16.                 throw new ArgumentNullException("target");
  17.  
  18.             Transaction tr = target.Database.TransactionManager.TopTransaction;
  19.             if (tr == null)
  20.                 throw new AcRx.Exception(ErrorStatus.NoActiveTransactions);
  21.             List<AttributeDefinition> attDefs = target.GetAttributes(tr);
  22.             foreach (ObjectId id in target.GetBlockReferenceIds(true, false))
  23.             {
  24.                 BlockReference br = (BlockReference)tr.GetObject(id, OpenMode.ForWrite);
  25.                 br.ResetAttributes(attDefs, tr);
  26.             }
  27.             if (target.IsDynamicBlock)
  28.             {
  29.                 target.UpdateAnonymousBlocks();
  30.                 foreach (ObjectId id in target.GetAnonymousBlockIds())
  31.                 {
  32.                     BlockTableRecord btr = (BlockTableRecord)tr.GetObject(id, OpenMode.ForRead);
  33.                     attDefs = btr.GetAttributes(tr);
  34.                     foreach (ObjectId brId in btr.GetBlockReferenceIds(true, false))
  35.                     {
  36.                         BlockReference br = (BlockReference)tr.GetObject(brId, OpenMode.ForWrite);
  37.                         br.ResetAttributes(attDefs, tr);
  38.                     }
  39.                 }
  40.             }
  41.         }
  42.  
  43.         private static List<AttributeDefinition> GetAttributes(this BlockTableRecord target, Transaction tr)
  44.         {
  45.             List<AttributeDefinition> attDefs = new List<AttributeDefinition>();
  46.             foreach (ObjectId id in target)
  47.             {
  48.                 if (id.ObjectClass == attDefClass)
  49.                 {
  50.                     AttributeDefinition attDef = (AttributeDefinition)tr.GetObject(id, OpenMode.ForRead);
  51.                     attDefs.Add(attDef);
  52.                 }
  53.             }
  54.             return attDefs;
  55.         }
  56.  
  57.         private static void ResetAttributes(this BlockReference br, List<AttributeDefinition> attDefs, Transaction tr)
  58.         {
  59.             Dictionary<string, string> attValues = new Dictionary<string, string>();
  60.             foreach (ObjectId id in br.AttributeCollection)
  61.             {
  62.                 if (!id.IsErased)
  63.                 {
  64.                     AttributeReference attRef = (AttributeReference)tr.GetObject(id, OpenMode.ForWrite);
  65.                     attValues.Add(attRef.Tag,
  66.                         attRef.IsMTextAttribute ? attRef.MTextAttribute.Contents : attRef.TextString);
  67.                     attRef.Erase();
  68.                 }
  69.             }
  70.             foreach (AttributeDefinition attDef in attDefs)
  71.             {
  72.                 AttributeReference attRef = new AttributeReference();
  73.                 attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
  74.                 if (attDef.Constant)
  75.                 {
  76.                     attRef.TextString = attDef.IsMTextAttributeDefinition ?
  77.                         attDef.MTextAttributeDefinition.Contents :
  78.                         attDef.TextString;
  79.                 }
  80.                 else if (attValues.ContainsKey(attRef.Tag))
  81.                 {
  82.                     attRef.TextString = attValues[attRef.Tag];
  83.                 }
  84.                 br.AttributeCollection.AppendAttribute(attRef);
  85.                 tr.AddNewlyCreatedDBObject(attRef, true);
  86.             }
  87.         }
  88.     }
  89. }


« Последнее редактирование: 30-09-2020, 22:24:53 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Спасибо огромное! Приведенный выше пример работает (от Gilles Chanteau). Атрибуты обновляются (перезаписываются/дублируются) в BlockReferences - ах, но почему-то не все. В блоке появляются первые 47 атрибутов (тегов), а оставшиеся 12 тегов не записываются (при просмотре из AutoCAD, в атрибутах последних 12 не видно).

В момент отладки, в attRef значение появляется, также увеличивается "Count" у параметра "AttributeCollections" объекта "br". Но последних атрибутов просто нет.

Код - C# [Выбрать]
  1. foreach (AttributeDefinition attDef in attDefs)
  2. {
  3.       AttributeReference attRef = new AttributeReference();                    
  4.       attRef.SetAttributeFromBlock(attDef, br.BlockTransform);
  5.       if (attDef.Constant)
  6.       {
  7.             attRef.TextString = attDef.IsMTextAttributeDefinition ?
  8.             attDef.MTextAttributeDefinition.Contents :
  9.             attDef.TextString;
  10.       }
  11.       else if (attValues.ContainsKey(attRef.Tag))
  12.       {
  13.             attRef.TextString = attValues[attRef.Tag];
  14.       }
  15.       br.AttributeCollection.AppendAttribute(attRef);
  16.       tr.AddNewlyCreatedDBObject(attRef, true);                  
  17. }

Подскажите пожалуйста, с чем это может быть связано?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Подскажите пожалуйста, с чем это может быть связано?
А tr.Commit() выполняется?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Да, выполняется. Но атрибуты переносятся не все

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Да, выполняется. Но атрибуты переносятся не все
Тогда буду ждать код и блок для проверки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Да, выполняется. Но атрибуты переносятся не все
Тогда буду ждать код и блок для проверки.

Библиотеку пишу для AutoCAD 2014
В архиве "Блок" - содержится основной документ (Блок) и шаблон (BearingBlock(блок в чертеже)), который необходимо вставить.
В архиве "AutoCADLibrary" - сам проект.
Инструкция прописана в коде (комментарии написаны подробно)

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Михаил Лахин,
Два вопроса:
1) Чтобы не разбираться с добавлением кнопок на Ленту. Команда которую нужно проверить: LoadingData ?
2) Перед запуском команды какой из чертежей должен быть открыт в редакторе AutoCAD: "Блок.dwg" или "BearingBlock(блок в чертеже).dwg" ?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Михаил Лахин,
Два вопроса:
1) Чтобы не разбираться с добавлением кнопок на Ленту. Команда которую нужно проверить: LoadingData ?
2) Перед запуском команды какой из чертежей должен быть открыт в редакторе AutoCAD: "Блок.dwg" или "BearingBlock(блок в чертеже).dwg" ?

1) Да
2) Блок.dwg

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Михаил Лахин,
Хм. Интересный факт. Команда редактирования атрибутов _eattedit показывает 47 атрибутов, хотя их в действительности 59 (это видно если смотреть при помощи утилиты MGDDBG).
Нужно разобраться какие атрибуты не показываются и в чем их особенность.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Хм. Хм. Хм. А код Андрея Бушмана работает правильно. Во всяком случае количество атрибутов в редакторе атрибутов 59. Тестировал в AutoCAD 2021, но надеюсь, что и в 2014 всё будет нормально.
Я добавил архивированный проект. Посмотри и протестируй. На досуге постараюсь разобраться в чем разница.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Протестировал код, который Вы скинули.
В строке 375, класса ATTSYNCH.cs, возникает шибка "eInvalidContext".
С ней же столкнулся и в прошлый раз, но, к сожалению, причину выяснить не удалось.
Подскажите, Вы сталкивались с подобным?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Протестировал код, который Вы скинули.
В строке 375, класса ATTSYNCH.cs, возникает шибка "eInvalidContext".
С ней же столкнулся и в прошлый раз, но, к сожалению, причину выяснить не удалось.
Подскажите, Вы сталкивались с подобным?

Это происходит у вас на том чертеже, который вы передали для тестирования? Если нет, то нужен чертеж на котором это происходит. У меня это не происходит.
В принципе, можно просто вместо
Код - C# [Выбрать]
  1. ad.AdjustAlignment(db);
записать
Код - C# [Выбрать]
  1. try { ad.AdjustAlignment(db); } catch { }
Мест, где используется метод AdjustAlignment несколько в коде. Советую его везде обернуть в try/catch.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Михаил ЛахинАвтор темы

  • ADN OPEN
  • Сообщений: 9
  • Карма: 0
Цитировать
Это происходит у вас на том чертеже, который вы передали для тестирования? Если нет, то нужен чертеж на котором это происходит. У меня это не происходит.
В принципе, можно просто вместо
Код - C# [Выбрать]
  1. ad.AdjustAlignment(db);
записать
Код - C# [Выбрать]
  1. try { ad.AdjustAlignment(db); } catch { }
Мест, где используется метод AdjustAlignment несколько в коде. Советую его везде обернуть в try/catch.

Да, тестирование провожу на тех же чертежах.

Обертывание не дает результата. Если поставить точку останова на этой строке, дальше отладчик не выполняет команду и остается на ней же.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Да, тестирование провожу на тех же чертежах.
Установлены все обновления для AutoCAD?
Обертывание не дает результата. Если поставить точку останова на этой строке, дальше отладчик не выполняет команду и остается на ней же.
Это мягко говоря странно. Так быть не должно. В крайнем случае закомментируй эту строку.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн doctorRAZ

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
  • Skype: doctorraz
С разрешения Андрея Бушмана выкладываю здесь
Могу ли сослаться на архив сайта на другом форуме?
Atsync
Весьма вариативный метод получился.. к версии Бушмана, добавил "не изменять положение существующих атрибутов" вот далеко еще до этого((((
« Последнее редактирование: 09-08-2021, 20:28:41 от doctorRAZ »

Оффлайн doctorRAZ

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
  • Skype: doctorraz
вопрос по коду Бушмана
я правильно понял, что если мы выбрали измененный дин блок, то его  btr (описание) это btr анонимного блока
BlockTableRecord btr = (BlockTableRecord) t.GetObject(bt[br.Name], OpenMode.ForRead);
соответственно условие
if (btr.IsDynamicBlock) {
выполнено никогда не будет
и код Бушмана выполнится только для анонимного btr и его вхождений?
---------
Есть ли возможность из вхождения анонимного блока получить btr динамического блока "прародителя"?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
соответственно условие
Цитата: Александр Ривилис от 30-09-2020, 17:27:33

    if (btr.IsDynamicBlock) {

выполнено никогда не будет
Будет. Анонимный блок, полученный из динамического - тоже динамический.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Могу ли сослаться на архив сайта на другом форуме?
Этот вопрос задавай Андрею.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть ли возможность из вхождения анонимного блока получить btr динамического блока "прародителя"?
Да. BlockReference.DynamicBlockTableRecord возвращает BlockTableRecord "прародителя".
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн doctorRAZ

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
  • Skype: doctorraz
Анонимный блок, полученный из динамического - тоже динамический.
этот код
Код - C# [Выбрать]
  1.  
  2.   //https://adn-cis.org/forum/index.php?topic=10047.msg45331#msg45331
  3.         [CommandMethod("MySynch", Trtm.CommandFlags.Modal)]
  4.         public void MySynch()
  5.         {
  6.             Document dwg = acad.DocumentManager.MdiActiveDocument;
  7.             Editor ed = dwg.Editor;
  8.             Database db = dwg.Database;
  9.             TypedValue[] types = new TypedValue[] { new TypedValue((int)DxfCode.Start, "INSERT") };
  10.             SelectionFilter sf = new SelectionFilter(types);
  11.             PromptSelectionOptions pso = new PromptSelectionOptions();
  12.             pso.MessageForAdding = "Select block reference";
  13.             pso.SingleOnly = true;
  14.             pso.AllowDuplicates = false;
  15.             PromptSelectionResult psr = ed.GetSelection(pso, sf);
  16.             //*******************************
  17.             if (psr.Status == PromptStatus.OK)
  18.             {
  19.                 using (Transaction t = db.TransactionManager.StartTransaction())
  20.                 {
  21.                     BlockTable bt = (BlockTable)t.GetObject(db.BlockTableId, OpenMode.ForRead);
  22.                     BlockReference br = (BlockReference)t.GetObject(psr.Value[0].ObjectId, OpenMode.ForRead);
  23.                     BlockTableRecord btr = (BlockTableRecord)t.GetObject(bt[br.Name], OpenMode.ForRead);
  24.                     BlockTableRecord btrx = t.GetObject(br.BlockTableRecord, OpenMode.ForRead) as BlockTableRecord;
  25.                     btr.AttSync(false, true, false);
  26.                     //btr.UpdateAnonymousBlocks();
  27.                     t.Commit();
  28.                 }
  29.             }
  30.             else
  31.                 ed.WriteMessage("Bad selectionа.\n");
  32.             //********************************
  33.         }
  34.  
на примере из вложения
дает такой результат


не пойму, что я упускаю(((
AutoCAD2021x64

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Так. Я неправильно написал выше. Каюсь. BlockReference.IsDynamicBlock возвращает true даже если BlockReference.BlockTableRecord анонимный блок, но BlockReference.DynamicBlockTableRecord возвращает истинно динамический блок. Но BlockTableRecord.IsDynamicBlock возвращает true только для истинно динамического блока (неанонимного).

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Есть одна особенность у вставки динамического блока. Если его масштабы по X,Y,Z не одинаковы, то BlockReference.IsDynamicBlock возвращает false, даже если это динамический блок.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн doctorRAZ

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
  • Skype: doctorraz
Если его масштабы по X,Y,Z не одинаковы, то BlockReference.IsDynamicBlock возвращает false, даже если это динамический блок
Спасибо, об этом я прочитал..
Но блок в сообщении выше... он динамический, в равных масштабах, динамика применена и он возвращает false
-----------
возможно btr получаю неправильно? как
// Метод для тестов:
https://adn-cis.org/forum/index.php?topic=10047.msg45331#msg45331
или блок кривой?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
doctorRAZ,
Посмотри внимательно на эту картинку, полученную с твоего блока:


Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн doctorRAZ

  • ADN OPEN
  • Сообщений: 42
  • Карма: 0
  • Skype: doctorraz
Посмотри внимательно на эту картинку, полученную с твоего блока
Возможно в первом ответе этой темы.... некорректный вызов
Код - C# [Выбрать]
  1.         //https://adn-cis.org/forum/index.php?topic=10047.msg45331#msg45331
  2.         [CommandMethod("MySynch", Trtm.CommandFlags.Modal)]
  3.         public void MySynch()
  4.         {
  5.             Document dwg = acad.DocumentManager.MdiActiveDocument;
  6.             Editor ed = dwg.Editor;
  7.             Database db = dwg.Database;
  8.             TypedValue[] types = new TypedValue[] { new TypedValue((int)DxfCode.Start, "INSERT") };
  9.             SelectionFilter sf = new SelectionFilter(types);
  10.             PromptSelectionOptions pso = new PromptSelectionOptions();
  11.             pso.MessageForAdding = "Select block reference";
  12.             pso.SingleOnly = true;
  13.             pso.AllowDuplicates = false;
  14.             PromptSelectionResult psr = ed.GetSelection(pso, sf);
  15.             //*******************************
  16.             if (psr.Status == PromptStatus.OK)
  17.             {
  18.                 using (Transaction t = db.TransactionManager.StartTransaction())
  19.                 {
  20.                     BlockTable bt = (BlockTable)t.GetObject(db.BlockTableId, OpenMode.ForRead);
  21.                     BlockReference br = (BlockReference)t.GetObject(psr.Value[0].ObjectId, OpenMode.ForRead);
  22.           //было          //BlockTableRecord btr = (BlockTableRecord)t.GetObject(bt[br.Name], OpenMode.ForRead);
  23.                     BlockTableRecord btr = t.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead) as BlockTableRecord;// стало
  24.                     btr.AttSync(false, true, false);
  25.                     //btr.UpdateAnonymousBlocks();
  26.                     //BlockReference.DynamicBlockTableRecord
  27.                     t.Commit();
  28.                 }
  29.             }
  30.             else
  31.                 ed.WriteMessage("Bad selectionа.\n");
  32.             //********************************
  33.         }
  34.  
так будет верно
Код - C# [Выбрать]
  1.           //было          //BlockTableRecord btr = (BlockTableRecord)t.GetObject(bt[br.Name], OpenMode.ForRead);
  2.                     BlockTableRecord btr = t.GetObject(br.DynamicBlockTableRecord, OpenMode.ForRead) as BlockTableRecord;// стало
  3.  
вроде работает и теперь передаем в метод btr дин блока, а не анонимного
-----------------
да теперь работает, обновляет все вхождения