Почему не копируется лист из шаблона? 2016 autocad

Автор Тема: Почему не копируется лист из шаблона? 2016 autocad  (Прочитано 8998 раз)

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

Тема содержит сообщение с Решением. Нажмите здесь чтобы посмотреть его.

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Всем привет! Функция вставки листа из одно файла в другой почему-то не работает в 2016 autocad. В 2021 нормально отрабатывает. А в 2016, вроде, лист создает, но на него не зайти и после переключения между листами он вовсе пропадает. Что я не так делаю? Если что, то библиотеки я использую в соответствии с версией autocad. Параметры функции: "путь к файлу откуда копировать лист", "имя листа в файле откуда копировать", "имя для создаваемого листа в текущем файле". Собственно функция
Код - C# [Выбрать]
  1.        
  2. public static void CopyLayout(string fileName, string templateLayoutName, string newLayoutName)
  3.     {
  4.         using (Database templateDb = new Database(false, true) as Database)
  5.         {
  6.             templateDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, "");
  7.  
  8.             Document doc = Application.DocumentManager.MdiActiveDocument;
  9.             Editor ed = doc.Editor;
  10.             Database db = doc.Database;
  11.             LayoutManager layoutManager = LayoutManager.Current;
  12.  
  13.             using (Transaction trx = db.TransactionManager.StartTransaction())
  14.  
  15.             using (Transaction templateTrx = templateDb.TransactionManager.StartTransaction())
  16.             {
  17.                 DBDictionary layoutDictionary = trx.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  18.  
  19.                 DBDictionary templateLayoutDictionary = templateTrx.GetObject(templateDb.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  20.  
  21.                 if (!(templateLayoutDictionary.Contains(templateLayoutName)))
  22.                 {
  23.                     ed.WriteMessage("\nШаблон не содержит листов с данным именем.");
  24.                     return;
  25.                 }
  26.  
  27.                 while (LayoutExists(newLayoutName)) newLayoutName += "#";
  28.  
  29.                 ObjectId newLayoutId = layoutManager.CreateLayout(newLayoutName);
  30.  
  31.                 Layout  newLayout = trx.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;
  32.  
  33.                 Layout  templateLayout = templateLayoutDictionary.GetAt(templateLayoutName).GetObject(OpenMode.ForRead) as Layout;
  34.  
  35.                 newLayout.CopyFrom(templateLayout);
  36.  
  37.                 newLayout.Initialize();
  38.  
  39.                 PlotSettingsValidator psv = PlotSettingsValidator.Current;
  40.                 psv.SetZoomToPaperOnUpdate(newLayout, true);
  41.  
  42.                 templateTrx.Commit();
  43.                 trx.Commit();
  44.             }
  45.         }
  46.     }

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Всем привет! Функция вставки листа из одно файла в другой почему-то не работает в 2016 autocad. В 2021 нормально отрабатывает. А в 2016, вроде, лист создает, но на него не зайти и после переключения между листами он вовсе пропадает.

Не вижу, где ты копируешь Viewport. На каждом листе должен присутствовать главный Viewport. Он первый в списке. Если ты его не создашь, то по идее он создается когда заходишь на лист.
Но видимо в 2016 это не так. Сперва проверь все ли обновления установлены на 2016. Потом добавляй копирование Viewport.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Mirco,
Копировать из другого чертежа нужно при помощи метода Database.WblockCloneObjects. Попробуй такой код от Jeff H:
Код - C# [Выбрать]
  1. [CommandMethod("CopyLayout")]
  2. public void CopyLayout()
  3. {
  4.     string layoutName = "Test";
  5.     string fileName = @"C:\Testing\LayoutTest.dwt";
  6.  
  7.     using (Database templateDb = new Database(false, true) as Database)
  8.     {
  9.         templateDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, "");
  10.         Document doc = Application.DocumentManager.MdiActiveDocument;
  11.         Editor ed = doc.Editor;
  12.         Database db = doc.Database;
  13.         LayoutManager layoutManager = LayoutManager.Current;
  14.         using (Transaction trx = db.TransactionManager.StartTransaction())
  15.         using (Transaction templateTrx = templateDb.TransactionManager.StartTransaction())
  16.         {
  17.             DBDictionary layoutDictionary = trx.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  18.  
  19.             if (layoutDictionary.Contains(layoutName))
  20.             {
  21.                 ed.WriteMessage("\nThis Layout is already in drawing.");
  22.                 return;
  23.             }
  24.             DBDictionary templateLayoutDictionary = templateTrx.GetObject(templateDb.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  25.             if (!(templateLayoutDictionary.Contains(layoutName)))
  26.             {
  27.                 ed.WriteMessage("\nTemplate does not contain a Layout with that name.");
  28.                 return;
  29.             }
  30.             ObjectId newLayoutId = layoutManager.CreateLayout(layoutName);
  31.             Layout newLayout = trx.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;
  32.             Layout templateLayout = templateLayoutDictionary.GetAt(layoutName).GetObject(OpenMode.ForWrite) as Layout;
  33.             newLayout.CopyFrom(templateLayout);
  34.             BlockTableRecord templateLayoutBtr = templateTrx.GetObject(templateLayout.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord;
  35.             ObjectIdCollection objIdColl = new ObjectIdCollection();
  36.             foreach (ObjectId id in templateLayoutBtr)
  37.             {
  38.                 objIdColl.Add(id);
  39.             }
  40.             BlockTable extBt = templateDb.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
  41.             IdMapping map = new IdMapping();
  42.             db.WblockCloneObjects(objIdColl, newLayout.BlockTableRecordId, map, DuplicateRecordCloning.Replace, false);
  43.             newLayout.Initialize();
  44.             PlotSettingsValidator psv = PlotSettingsValidator.Current;
  45.             psv.SetZoomToPaperOnUpdate(newLayout, true);
  46.          
  47.             templateTrx.Commit();
  48.             trx.Commit();
  49.         }
  50.         layoutManager.CurrentLayout = layoutName;
  51.     }
  52.    
  53. }
  54.  

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

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Копировать из другого чертежа нужно при помощи метода Database.WblockCloneObjects. Попробуй такой код от Jeff H:
Хмм, боюсь, что это идентичный код, только нет копирования содержимого листа. Оно мне и не нужно. Я отдельно создал проект, даже с Вашим кодом, ничего не изменилось. Странно, на 2021 работает отлично, как и должно. Ни у кого нет возможности проверить у себя на 2016?

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
это идентичный код, только нет копирования содержимого листа. Оно мне и не нужно
1. главный Viewport как раз является содержимым листа. Он первый Viewport  и его не видно, когда заходишь на лист. Как минимум его стоит скопировать, остальное можешь пропустить.

2. Проверил обновления на 2016?
Если не ошибаюсь, там SP1 и еще хотфикс.
https://knowledge.autodesk.com/ru/support/autocad/downloads/caas/downloads/downloads/RUS/content/autocad-2016-service-pack-1.html
https://knowledge.autodesk.com/ru/download

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
1. главный Viewport как раз является содержимым листа. Он первый Viewport  и его не видно, когда заходишь на лист. Как минимум его стоит скопировать, остальное можешь пропустить.

2. Проверил обновления на 2016?
Если не ошибаюсь, там SP1 и еще хотфикс.
1. Я в курсе, я же написал, что попробовал и представленный Александром вариант.
2. Да, всё установлено. Проверил на двух разных компьютерах. Конкретно не работает правильно функция создания листа через менеджер листов. Он вроде создает, вкладка появляется. Но зайти на неё невозможно. Переключаясь между листами, он вовсе пропадает. Я в шоке. Я так понимаю, что вот эта функция не верно работает: "layoutManager.CreateLayout(layoutName);", либо у меня на двух разных компьютерах что-то не то.
А есть вариант, как создать лист без менеджера листов?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Проверь такой код (т.е. без копирования листа - просто его создание):

Код - C# [Выбрать]
  1. ObjectId newLayoutId = layoutManager.CreateLayout(layoutName);
  2. using (Transaction trx = db.TransactionManager.StartTransaction())
  3. {
  4.  Layout newLayout = trx.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;
  5.  newLayout.Initialize();
  6.  trx.Commit();
  7. }

Если этот код не сработает, то у тебя что-то с AutoCAD.

P.S.: layoutManager.CreateLayout(layoutName) должно быть вне транзакции.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
ObjectId newLayoutId = layoutManager.CreateLayout(layoutName);
using (Transaction trx = db.TransactionManager.StartTransaction())
{
 Layout newLayout = trx.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;
 newLayout.Initialize();
 trx.Commit();
}
Этот участок когда работает. Я из предыдущего уже удалил практически всё, и почему-то начинается не выполнение функций после получения словарей листов, насколько я понял. Может что-то с транзакциями?
Вот после этих строк:
Код - C# [Выбрать]
  1. DBDictionary layoutDictionary = trx.GetObject(db.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  2. DBDictionary templateLayoutDictionary = templateTrx.GetObject(templateDb.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  3.  
Даже
Код - C# [Выбрать]
  1. ed.Command("_LAYOUT", "Н", "point1", "\n");
не выполняется, а до этих двух строк выполняется.

Отмечено как Решение Mirco 21-06-2020, 13:11:00

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

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

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Этот участок когда работает.
Уже хорошо. Думаю, что проблема в том, что ты выполняешь layoutManager.CreateLayout(layoutName); внутри транзакции. Нужно разделить транзакции и вынести этот код вне транзакций.
Сейчас попробую это разделить и сообщу результат, просто странно, что это работало на 2021 автокаде без замечаний.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Mirco,
Почитай эту тему: https://adn-cis.org/forum/index.php?topic=2723.0
Там есть и код, который должен тебе помочь.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Mirco,
Почитай эту тему: https://adn-cis.org/forum/index.php?topic=2723.0
Там есть и код, который должен тебе помочь.

Спасибо, почитаю на днях. У меня в принципе рабочий код уже, просто под 2016 autocad, получается, LayoutManager лучше выносить из транзакций. В 2021 такого точно уже нету. Я вынес работу с менеджером листов из транзакций и всё работает. Спасибо. Просто я не понимаю, как транзакции действуют на работу таких объектов как менеджер листов.
П.С. Вспомнил слова знакомого программиста из Amazon про autodesk и то, что фирма серьезная. Но чем дальше я вникаю в их API, тем больше понимаю насколько он был не прав и, что их software инженерам нужно еще учиться и учиться. Столько боли я еще не испытывал ни от одних API. Я от Вас больше информации получаю, чем от всех источников в интернете и официальной документации. Это не правильно  :'(

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Вот после этих строк:
из предположений:
1. Database templateDb = new Database(false, true) as Database. Возможно в 2016 не создает LayoutDictionary, не записывает LayoutDictionaryId или еще что-нибудь не доделывает.

2. поврежден шаблон с листами.

По быстрому можешь копировать в открытый чертеж из другого шаблона, минуя new Database.

Если вникать, то можно проанализировать что возвращает templateDb.LayoutDictionaryId
Существует ли такой id, что за объект возвращается по данному id, не попорчены записи в Dictionary.

Оффлайн MircoАвтор темы

  • ADN OPEN
  • Сообщений: 10
  • Карма: 0
Вот после этих строк:
из предположений:
1. Database templateDb = new Database(false, true) as Database. Возможно в 2016 не создает LayoutDictionary, не записывает LayoutDictionaryId или еще что-нибудь не доделывает.

2. поврежден шаблон с листами.

По быстрому можешь копировать в открытый чертеж из другого шаблона, минуя new Database.

Если вникать, то можно проанализировать что возвращает templateDb.LayoutDictionaryId
Существует ли такой id, что за объект возвращается по данному id, не попорчены записи в Dictionary.
Дмитрий, мы уже всё решили. Александр указал, что работу с LayoutManager нужно вынести из транзакций.  ;) Вы всё на своей волне. Спасибо за помощь всем.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Mirco,
В 2015 и 2016-ом AutoCAD был такой баг: https://forums.autodesk.com/t5/net/need-help-programming-around-2015-api-createlayout-big/m-p/5484373

Цитировать
Another way to work around this is to inspect the layout dictionary in a separate transaction from the one in which you create the new layout. The problem only occurs if you have the layout dictionary open while you create the layout.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение