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

ADN Club => AutoCAD .NET API => Тема начата: Николай Коломоец от 02-08-2013, 15:31:39

Название: Создание нового листа по шаблону
Отправлено: Николай Коломоец от 02-08-2013, 15:31:39
Имеется функция разбивки выделенного фрагмента на листы. Создание новых листов на основе шаблона делает следующая функция:

Код - C# [Выбрать]
  1. private ObjectId CopyLayout(String fileName, ref String layName, ref String paperName, ref ObjectId newViewPortId, int paperNo)
  2.         {
  3.             Database templateDb = new Database(false, true);
  4.             templateDb.ReadDwgFile(fileName, FileOpenMode.OpenForReadAndAllShare, true, "");
  5.             int pageWidth = 0;
  6.             Document doc = Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument;
  7.             Editor ed = doc.Editor;
  8.             Database db = doc.Database;
  9.  
  10.             Layout newLayout;
  11.             LayoutManager layManager = 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.                     while (layoutDictionary.Contains(paperName + paperNo.ToString()))
  19.                     {
  20.                         ed.WriteMessage("\nЭтот чертеж уже содержит лист с именем {0}. ", paperName + paperNo.ToString());
  21.                         PromptStringOptions strOpt = new PromptStringOptions("Укажите имя листа: ");
  22.                         PromptResult strRes = ed.GetString(strOpt);
  23.                         if (strRes.Status != PromptStatus.OK)
  24.                         {
  25.                             MessageBox.Show("Ввод данных отменен");
  26.                             return new ObjectId();
  27.                         }
  28.                         paperName = strRes.StringResult;
  29.                     }
  30.  
  31.                     DBDictionary templateLayoutDictionary = templateTrx.GetObject(templateDb.LayoutDictionaryId, OpenMode.ForRead) as DBDictionary;
  32.                     if (!(templateLayoutDictionary.Contains(layName)))
  33.                     {
  34.                         ed.WriteMessage("\nTemplate does not contain a Layout with that name.");
  35.                         return new ObjectId();
  36.                     }
  37.  
  38.                     ObjectId newLayoutId = layManager.CreateLayout(paperName+paperNo.ToString());
  39.                     newLayout = trx.GetObject(newLayoutId, OpenMode.ForWrite) as Layout;
  40.                     newLayout.LayoutName = paperName + paperNo.ToString();
  41.  
  42.                     Layout templateLayout = templateLayoutDictionary.GetAt(layName).GetObject(OpenMode.ForWrite) as Layout;
  43.                     newLayout.CopyFrom(templateLayout);
  44.  
  45.                     BlockTableRecord templateLayoutBtr = templateTrx.GetObject(templateLayout.BlockTableRecordId, OpenMode.ForRead) as BlockTableRecord;
  46.  
  47.                     ObjectIdCollection objIdColl = new ObjectIdCollection();
  48.                     foreach (ObjectId id in templateLayoutBtr)
  49.                         objIdColl.Add(id);
  50.                     BlockTable extBt = templateDb.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
  51.                     IdMapping map = new IdMapping();
  52.                     db.WblockCloneObjects(objIdColl, newLayout.BlockTableRecordId, map, DuplicateRecordCloning.Replace, false);
  53.  
  54.                     newViewPortId = newLayout.Initialize();
  55.  
  56.                     templateTrx.Commit();
  57.                     trx.Commit();
  58.                 }
  59.             }
  60.             return newLayout.Id;
  61.             //return newViewPortId;
  62.         }

Метод работает, но "через раз", периодически валит AutoCAD фатальной ошибкой, причем явной закономерности найти так и не удалось - часто просто пробую несколько раз ее выполнить, получается со второй или третьей попытки, при тех же начальных условиях.
В чем может быть причина? Подозрение у меня на WblockCloneObjects, не совсем понятно, как он работает.

И второй вопрос тут же в тему - создаю видовой экран на листе после создания листа. Все работает нормально, если после работы программы физически перейти на этот лист. Если этого не сделать, после повторного открытия чертежа видовой экран "исчезает". Выкрутился добавлением команды
Код - C# [Выбрать]
  1. newLayout.Initialize();
, теперь программа "перелистывает" листы при работе. Не критично, но при очень многостраничных документах (рекорд - 192 листа  :-[) замедление работы сильно ощутимо.
Название: Re: Создание нового листа по шаблону
Отправлено: Александр Ривилис от 02-08-2013, 16:47:16
Мне кажется, что нужно начать с изучения готовых примеров. Например, Create a copy of a layout from a drawing template (http://adndevblog.typepad.com/autocad/2013/01/create-a-copy-of-a-layout-from-a-drawing-template.html)
Название: Re: Создание нового листа по шаблону
Отправлено: Алексей (IdeaSoft) от 04-12-2018, 17:05:55
Я выкинул из кода содержимое внутри блоков using
Получается, так что trx.Commit(); вызывается во внутреннем блоке using

Код - C# [Выбрать]
  1. using (Transaction trx = db.TransactionManager.StartTransaction())
  2. {
  3. using (Transaction templateTrx = templateDb.TransactionManager.StartTransaction())
  4. {
  5.  
  6. // Опустим содержимое кода
  7.  
  8. templateTrx.Commit();
  9. trx.Commit();
  10. }
  11. }

Наверное нужно так сделать

Код - C# [Выбрать]
  1. using (Transaction trx = db.TransactionManager.StartTransaction())
  2. {
  3. using (Transaction templateTrx = templateDb.TransactionManager.StartTransaction())
  4. {
  5.  
  6. // Опустим содержимое кода
  7.  
  8. templateTrx.Commit();
  9. }
  10. trx.Commit();
  11. }


Название: Re: Создание нового листа по шаблону
Отправлено: Александр Ривилис от 04-12-2018, 17:09:19
Получается, так что trx.Commit(); вызывается во внутреннем блоке using
В данном случае никакой разницы нет. Точнее она совершенно несущественна.
Название: Re: Создание нового листа по шаблону
Отправлено: Дмитрий Загорулькин от 05-12-2018, 13:14:03
Наверное нужно так сделать
Можно их вообще в один блок объединить:
Код - C# [Выбрать]
  1. using (Transaction trx = db.TransactionManager.StartTransaction())
  2. using (Transaction templateTrx = templateDb.TransactionManager.StartTransaction())
  3. {
  4.  
  5. // Опустим содержимое кода
  6.  
  7. templateTrx.Commit();
  8. trx.Commit();
  9. }