Сообщество программистов Autodesk в СНГ

ADN Club => AutoCAD .NET API => Тема начата: Serg34 от 21-09-2017, 15:09:41

Название: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 21-09-2017, 15:09:41
Всем доброго времени суток.
Мне достался файл с множеством динамических блоков с двумя линейными параметрами и 4-мя атрибутами.
Вобщем, блоки несложные, но что с ними не знаю:
при непрограммном (руками) изменении какого -либо динамического параметра AutoCAD тормозит ужасно и часто fatal error выскакивает даже если всего 50 блоков изменяешь.

Моя задача, грубо говоря, поменять все блоки с длиной  равной 500 на длину равную 400.
Мысль сделать это программно не открывая AutoCAD.
Это возможно?
Сам код, думаю, я смогу написать, но как получить документ?
то есть что написать вместо строчки:
Код - C# [Выбрать]
  1. Document doc = AcadApp.DocumentManager.MdiActiveDocument;
???
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 21-09-2017, 15:12:11
Мысль сделать это программно не открывая AutoCAD.
Это как? Вообще не запуская AutoCAD? Тогда или accoreconsole.exe (это бесплатно) или RealDWG (это платно и стоит очень прилично).
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 21-09-2017, 15:17:50
Или имеется в виду не загружая чертеж в редактор AutoCAD? Тогда можно через Database.ReadDwgFile(...)
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 21-09-2017, 15:23:08
Да, AutoCAD на компьютере установлен, если Вы об этом, но не нужно его запускать.
А Database.ReadDwgFile(...) - это
Код - C# [Выбрать]
  1. Document doc = Database.ReadDwgFile(filePath);
где filePath - путь к файлу?

Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 21-09-2017, 15:45:30
Да, AutoCAD на компьютере установлен, если Вы об этом, но не нужно его запускать.
Без запуска AutoCAD у тебя ничего не получится.
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 21-09-2017, 15:54:47
А Database.ReadDwgFile(...) - это
Код - C# [Выбрать]

    Document doc = Database.ReadDwgFile(filePath);

где filePath - путь к файлу?

Это бред. Пример использования Database.ReadDwgFile: http://adn-cis.org/izmenenie-putej-k-vneshnim-ssyilkam-iz-absolyutnyix-v-otnositelnyie.html
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 21-09-2017, 16:21:57
Спасибо, дома попробую!
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 22-09-2017, 11:05:33
Все работает, но тут следующая проблема:
при изменении длины блока штриховка не меняет габарита и вылезает за габариты блока
(https://s26.postimg.org/htyv9zb2d/image.png) (https://postimg.org/image/htyv9zb2d/)
При открытом файле все нормально проходит, хотя код, вроде, такой же за одним исключением:
Для закрытого файла я убрал строчку: ed.Regen();
Код могу привести, но он у меня по разным классам разнесен.
Может, без моего кода сможете подсказать в чем может быть дело?
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 22-09-2017, 11:24:52
1. Не все, что можно сделать с файлом в редакторе AutoCAD можно сделать без редактора (т.е. имея Document)
2. Попробуйте переключить рабочую базу на ту, что редактируете, а по окончании редактирования верните назад. Иногда такое помогает.
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 22-09-2017, 11:47:02
Не совсем пойму.
Вот код (на всякий случай поясню, это метод-итератор, который принимает метод-обработчик в качестве аргумента и при выполнении условий применяет этот метод-обработчик к блоку):
Код - C# [Выбрать]
  1. private static void AccessGlobalFromFile(
  2.         GlobalBlocksAccessor action, // метод обработки блока
  3.         string blockName = "",
  4.         string autoCADFilePath = "",
  5.         bool manyblocks = true,
  6.         bool dynamicOnly = false,
  7.         bool attributesAndParametrsMust = false)
  8. {
  9.         Document doc = Application.DocumentManager.MdiActiveDocument;
  10.         if (doc == null) return;
  11.  
  12.         Editor ed = doc.Editor;
  13.         using (Database db = new Database(false, true))
  14.         {
  15.                 db.ReadDwgFile(autoCADFilePath, FileOpenMode.OpenForReadAndWriteNoShare, false, "");
  16.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  17.                 {
  18.                         BlockTable blocktable = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead); // получаем таблицу блоков и проходим по всем записям таблицы блоков
  19.                         foreach (ObjectId btrId in blocktable)
  20.                         {
  21.                                 BlockTableRecord blockTableRecord = (BlockTableRecord)tr.GetObject(btrId, OpenMode.ForRead);// получаем запись таблицы блоков и смотрим анонимная ли она
  22.                                 if (!dynamicOnly || blockTableRecord.IsDynamicBlock)
  23.                                         if (string.IsNullOrWhiteSpace(blockName) || blockTableRecord.Name == blockName)
  24.                                         {
  25.                                                 ObjectIdCollection anonymousIds = blockTableRecord.GetAnonymousBlockIds();// получаем все анонимные блоки динамического блока
  26.                                                 foreach (ObjectId anonymousBtrId in anonymousIds)
  27.                                                 {
  28.                                                         BlockTableRecord anonymousBtr = (BlockTableRecord)tr.GetObject(anonymousBtrId, OpenMode.ForRead);// получаем анонимный блок
  29.                                                         ObjectIdCollection blocksCollection = anonymousBtr.GetBlockReferenceIds(true, true);// получаем все вставки этого блока
  30.  
  31.                                                         var attributeRefCollection = new List<AttributeReference>();
  32.                                                         DynamicBlockReferencePropertyCollection parametrsRefCollection = null;
  33.                                                         BlockReference blockReference = null;
  34.  
  35.                                                         if (attributesAndParametrsMust)
  36.                                                         {
  37.                                                                 foreach (ObjectId entId in blocksCollection)
  38.                                                                 {
  39.                                                                         if (tr.GetObject(entId, OpenMode.ForRead) is Entity ent)
  40.                                                                         {
  41.                                                                                 blockReference = ent as BlockReference;
  42.                                                                                 if (blockReference != null)
  43.                                                                                 {
  44.                                                                                         BlockTableRecord bd = (BlockTableRecord)tr.GetObject(blockReference.BlockTableRecord, OpenMode.ForRead);
  45.                                                                                         foreach (ObjectId arId in blockReference.AttributeCollection)// ... to see whether it's a block with the name we're after
  46.                                                                                         {
  47.                                                                                                 DBObject obj = tr.GetObject(arId, OpenMode.ForRead);
  48.                                                                                                 if (obj is AttributeReference ar)
  49.                                                                                                         attributeRefCollection.Add(ar);
  50.                                                                                         }
  51.                                                                                         parametrsRefCollection = blockReference.DynamicBlockReferencePropertyCollection;
  52.                                                                                         if (!manyblocks) break; // получили атрибуты и параметры. Если нужен только один блок, то выходим из перечисления вставок блока
  53.                                                                                 }
  54.                                                                         }
  55.                                                                 }
  56.                                                         }
  57.                                                         action(blockTableRecord, blocksCollection, blockReference, attributeRefCollection, parametrsRefCollection); // непосредственно обработка блока при помощи передаваемого метода
  58.                                                         if (!manyblocks) break;// получили все параметры. Если нужен только один блок, то выходим из перечисления типов блоков
  59.                                                 }
  60.                                         }
  61.                         }
  62.                         tr.Commit();
  63.                 }
  64.                 if (manyblocks) db.SaveAs(db.OriginalFileName, true, db.OriginalFileVersion, db.SecurityParameters);
  65.         }
  66. }

Где тут рабочая база?
И в какой строчке нужно менять базу?
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 22-09-2017, 11:53:24
Где тут рабочая база?
HostApplicationServices.WorkingDatabase - это рабочая база. Сразу после создания db переключаешься на неё, а перед удалением базы (после сохранения) переключаешься обратно.
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 22-09-2017, 12:04:05
Можно пример?
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 22-09-2017, 12:12:59
Со смартфона тяжело. Посмотри это: http://adn-cis.org/forum/index.php?topic=831.msg3438#msg3438
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 22-09-2017, 12:24:11
Спасибо большое.
По примеру сделал так:
Код - C# [Выбрать]
  1. private static void AccessGlobalFromFile(...)
  2. {
  3.         Document doc = Application.DocumentManager.MdiActiveDocument;
  4.         if (doc == null) return;
  5.  
  6.         Editor ed = doc.Editor;
  7.         using (Database db = new Database(false, true))
  8.         {
  9.                 db.ReadDwgFile(autoCADFilePath, FileOpenMode.OpenForReadAndWriteNoShare, false, "");
  10.                 Database prevDb = HostApplicationServices.WorkingDatabase;
  11.                 HostApplicationServices.WorkingDatabase = db;
  12.  
  13.                 using (Transaction tr = db.TransactionManager.StartTransaction())
  14.                 {
  15.                         ...
  16.                         tr.Commit();
  17.                 }
  18.                 HostApplicationServices.WorkingDatabase = prevDb;
  19.                 db.SaveAs(db.OriginalFileName, true, db.OriginalFileVersion, db.SecurityParameters);
  20.         }
  21. }
Эффект тот же(
Попробую еще с открытым файлом - может, если программно блоки редактировать, то не будет fatal error
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 22-09-2017, 22:18:18
Ну возможно еще в коде обновления что-то не то. Например, я обратил внимание, что BlockTable открыт для чтения, а изменение параметров динамического блока приводит к созданию нового анонимного блока, BlockTableRecord которого должен записаться в BlockTable.
Короче говоря поиграйся с заменой OpenMode.ForRead на OpenMode.ForWrite в разных местах у себя. А может стоит заменить обычную транзакцию на эмуляцию транзакции.
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Дмитрий Загорулькин от 22-09-2017, 23:21:46
Задачка явно выше уровнем, чем знания автора...
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 25-09-2017, 14:03:39
поиграйся с заменой OpenMode.ForRead на OpenMode.ForWrite
Мне это всегда казалось странным, что я для чтения открываю и редактирую, но запись до этого всегда проходила корректно.
Но в моем случае замена на ForWrite все равно не помогла(((

заменить обычную транзакцию на эмуляцию транзакции
Опять же прошу пример если можно.

Задачка явно выше уровнем, чем знания автора...
Так форум для этого и существует. Разве нет?

Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Александр Ривилис от 26-09-2017, 00:02:37
Опять же прошу пример если можно.
http://adn-cis.org/sozdanie-polyline3d-bez-ispolzovaniya-tranzakczii.html
Название: Re: Изменить файл не открывая AutoCAD
Отправлено: Serg34 от 26-09-2017, 11:44:35
Проблему решил установкой AutoCAD 2018 - с ним все непрограммно сделал (36часов машина работала, но задачу выполнила).
Но в любом случае спасибо Вам за помощь :)