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

ADN Club => Inventor API => Тема начата: R.I.Chernov от 06-09-2016, 16:59:03

Название: Удаление всех размеров на чертеже.
Отправлено: R.I.Chernov от 06-09-2016, 16:59:03
Доброго времени суток, уважаемые форумчане. Помогите пожалуйста найти ошибку в коде. У меня есть куб, на чертеже с него начерчен вид спереди и вид сверху. И все четыре стороны куба образмерены на обоих видах (8 размеров). Решил написать код, чтобы удалял эти линейные размеры. Но он не работает - удаляет пару размеров - выдает ошибку. Если остановить и снова запустит - снова удаляет часть оставшихся размеров и выдает ошибку. После нескольких запусков все размеры удаляются:
Код - Visual Basic [Выбрать]
  1.      Private Sub test_dwg_7()
  2.         Dim oDoc_dwg As DrawingDocument
  3.         Set oDoc_dwg = ThisApplication.ActiveDocument
  4.         Dim oSheet As Sheet
  5.         Set oSheet = oDoc_dwg.ActiveSheet
  6.         Dim i As Integer
  7.             For i = 1 To oSheet.DrawingDimensions.GeneralDimensions.Count
  8.             oSheet.DrawingDimensions.GeneralDimensions(i).Delete
  9.             Next
  10.      End Sub
Название: Re: Удаление всех рахмеров на чертеже.
Отправлено: R.I.Chernov от 06-09-2016, 17:08:05
Судя по всему, после удаления первого же размера индексы остальных в коллекции уменьшаются на 1, потом еще на один. Нет идеи, как удалить размеры из коллекции " задом на перед" : т.е начать с последнего и закончить первым? Ну иди мб есть способ удалить всю коллекцию целиком?
Название: Re: Удаление всех рахмеров на чертеже.
Отправлено: R.I.Chernov от 06-09-2016, 17:12:58
Сам спросил, сам ответил - как это на меня похоже! :)
Код - Visual Basic [Выбрать]
  1.      Private Sub test_dwg_7()
  2.         Dim oDoc_dwg As DrawingDocument
  3.         Set oDoc_dwg = ThisApplication.ActiveDocument
  4.         Dim oSheet As Sheet
  5.         Set oSheet = oDoc_dwg.ActiveSheet
  6.         Dim i As Integer
  7.         Dim i2 As Integer
  8.         i2 = oSheet.DrawingDimensions.GeneralDimensions.Count
  9.             For i = 1 To oSheet.DrawingDimensions.GeneralDimensions.Count
  10.             oSheet.DrawingDimensions.GeneralDimensions(i2).Delete
  11.             i2 = i2 - 1
  12.             Next
  13.      End Sub

П.С. Вопрос насчет удаления всей коллекции без перебора остается открытым, если кто знает. прошу поделиться.
Название: Re: Удаление всех рахмеров на чертеже.
Отправлено: Александр Ривилис от 06-09-2016, 17:19:35
Нет идеи, как удалить размеры из коллекции " задом на перед" : т.е начать с последнего и закончить первым?
А кто тебе мешает записать цикл в обратном направлении? Если мне не изменяет память, то в VBA нужно написать как-то так:
Код - Visual Basic [Выбрать]
  1. For i = oSheet.DrawingDimensions.GeneralDimensions.Count To 1 step -1
  2.        oSheet.DrawingDimensions.GeneralDimensions(i).Delete
  3. Next
Название: Re: Удаление всех рахмеров на чертеже.
Отправлено: R.I.Chernov от 06-09-2016, 17:43:33
А кто тебе мешает записать цикл в обратном направлении?
Отсутствие должных знаний в этой области! :) Поэтому решил по-простому. Спасибо, Александр, за совет. Сейчас еще поковыряюсь.
Название: Re: Удаление всех рахмеров на чертеже.
Отправлено: R.I.Chernov от 06-09-2016, 17:46:45
Ларчик просто открывается, когда мудрый человек на форуме подскажет, что так вообще можно :)
Код - Visual Basic [Выбрать]
  1. Private Sub test_dwg_8()
  2.    Dim oDoc_dwg As DrawingDocument
  3.    Set oDoc_dwg = ThisApplication.ActiveDocument
  4.    Dim oSheet As Sheet
  5.    Set oSheet = oDoc_dwg.ActiveSheet
  6.    Dim i As Integer
  7.        For i = oSheet.DrawingDimensions.GeneralDimensions.Count To 1 Step -1
  8.        oSheet.DrawingDimensions.GeneralDimensions(i).Delete
  9.        Next
  10. End Sub
Название: Re: Удаление всех размеров на чертеже.
Отправлено: mikazakov от 06-09-2016, 19:55:26
     For i = 1 To oSheet.DrawingDimensions.GeneralDimensions.Count
            oSheet.DrawingDimensions.GeneralDimensions(i).Delete
     Next

Ну это вы, батенька, конечно повеселили.
В C#, кстати, будет работать следующий, более простой синтаксис:

Код - C# [Выбрать]
  1.   static Application InvApp;
  2.     static void Main(string[] args)
  3.     {
  4.         InvApp = System.Runtime.InteropServices.Marshal.GetActiveObject("Inventor.Application") as Application;
  5.         DrawingDocument drawDoc = InvApp.ActiveDocument as DrawingDocument;
  6.         Sheet sheet = drawDoc.ActiveSheet;
  7.  
  8.         foreach (GeneralDimension i in sheet.DrawingDimensions.GeneralDimensions)  i.Delete();
  9.        
  10.  
  11.     }
  12.  

Название: Re: Удаление всех размеров на чертеже.
Отправлено: R.I.Chernov от 06-09-2016, 20:56:41
Ну это вы, батенька, конечно повеселили.
Век живи - век учись! Я рад, что поднял вам настроение! :) Никогда до этого не приходилось коллекцию обнулять, потому и не задумывался о "поведении индексов"! Пару раз споткнулся - но задачу таки решил!:)
Название: Re: Удаление всех размеров на чертеже.
Отправлено: mikazakov от 07-09-2016, 06:03:05
коллекцию обнулять
Еще пару слов, при удалении размеров (и не только размеров) каждое действие записывается в транзакции (undo/redo), на это тратятся ресурсы производительности. Как минимум, лучше создать свою транзакцию, что бы инвентор определял удаление как одно действие, когда пользователь жмет на кнопку "отката". Но при большом количестве удалений инвентор может даже подвисать, потому как инвентор не отключает создание своих транзакций при каждом акте удаления объекта. Можно заставить инвентор использовать глобальную транзакцицию: это запретит инвентору создавать свои промежуточные транзакции и процесс удаления ускорится почти на порядок.

Есть альтернатива пообъектному удалению удалению:сначала нужно выделить все размеры через:
SelectSet.Select( Entity As Object )

или выделить оптом, что быстрее:
SelectSet.SelectMultiple( Entities As ObjectCollection )

И потом вызвать команду удаления выделенного:
CommandManager.ControlDefinitions.Item("AppDeleteCmd").Execute

Получится все очень шустро и за счет самого инвентора будет завернуто в одну транзакциию. ;)
Название: Re: Удаление всех размеров на чертеже.
Отправлено: R.I.Chernov от 07-09-2016, 09:22:04
Спасибо, Михаил. Очень полезная инфа. Мне правда не доводилось ещё ею пользоваться, так как необходимости не было. Тьфу тьфу, но компьютеры справлялись до сих пор. С другой стороны -это оптимизация кода.
Название: Re: Удаление всех размеров на чертеже.
Отправлено: R.I.Chernov от 07-09-2016, 17:27:44
Решил попробовать ваш способом, Михаил. Не могу разобраться, как подставить коллекцию размеров. Не подскажете, где ошибка?
Код - Visual Basic [Выбрать]
  1. Private Sub test_dwg_9()
  2.    Dim oDoc_dwg As DrawingDocument
  3.    Set oDoc_dwg = ThisApplication.ActiveDocument
  4.    Dim oSheet As Sheet
  5.    Set oSheet = oDoc_dwg.ActiveSheet
  6.    Call oDoc_dwg.SelectSet.SelectMultiple (oSheet.DrawingDimensions.GeneralDimensions)
  7. End Sub
Название: Re: Удаление всех размеров на чертеже.
Отправлено: mikazakov от 07-09-2016, 18:15:54
Не могу разобраться, как подставить коллекцию размеров.

Сначала нужно создать коллекция типа ObjectCollection.
Инициализируется объект этого типа через функцию:
ThisApplication.TransientObjects.CreateObjectCollection
Потом через соответствующий метод добавить члены в коллекцию ObjectCollection.Add( Object As Object )
И потом уже наполненную коллекцию можно  вставлять как аргумент в SelectSet.SelectMultiple

Вот пример из хэлпа на добавление элементов эскиза в коллекцию:
Код - Visual Basic [Выбрать]
  1. Dim oSketchEnts As ObjectCollection
  2.     Set oSketchEnts = ThisApplication.TransientObjects.CreateObjectCollection
  3.    
  4.     Dim oSketchEnt As SketchEntity
  5.     For Each oSketchEnt In oNewSketch.SketchEntities
  6.         Call oSketchEnts.Add(oSketchEnt)
  7.     Next
  8.  
Думаю, что перевести его на размеры с чертежей труда не составит.
Название: Re: Удаление всех размеров на чертеже.
Отправлено: R.I.Chernov от 07-09-2016, 18:27:56
Спасибо, Михаил.
Потом через соответствующий метод добавить члены в коллекцию
Правильно ли я понимаю, что запихнуть всю коллекцию размеров в пользовательскую разом нельзя, только перебором почленно?
Название: Re: Удаление всех размеров на чертеже.
Отправлено: mikazakov от 07-09-2016, 18:29:39
что запихнуть всю коллекцию размеров в пользовательскую разом нельзя, только перебором почленно?
Да, только по одному. ObjectCollection очень шустрый объект.
Название: Re: Удаление всех размеров на чертеже.
Отправлено: R.I.Chernov от 07-09-2016, 18:54:19
Да, только по одному. ObjectCollection очень шустрый объект.
Ок, спасибо еще раз.
В общем, кому интересно, код удаления размеров с помощью выделения получился такой:
Код - Visual Basic [Выбрать]
  1. Private Sub test_dwg_9()
  2.     Dim oDoc_dwg As DrawingDocument
  3.     Set oDoc_dwg = ThisApplication.ActiveDocument
  4.     Dim oSheet As Sheet
  5.     Set oSheet = oDoc_dwg.ActiveSheet
  6.    
  7.     Dim MyColl As ObjectCollection
  8.     Dim oDem As GeneralDimension
  9.     Set MyColl = ThisApplication.TransientObjects.CreateObjectCollection
  10.         For Each oDem In oSheet.DrawingDimensions.GeneralDimensions
  11.         Call MyColl.Add(oDem)
  12.         Next
  13.     Call oDoc_dwg.SelectSet.SelectMultiple(MyColl)
  14.     ThisApplication.CommandManager.ControlDefinitions.Item("AppDeleteCmd").Execute
  15. End Sub

Для себя я решил, что если стоит такая задача - объединить все действия в одно, то проще создать свою собственную транзакцию. Ведь даже если программа выделяет все размеры всего на долю секунды - она все же их выделяет. Если размеров будет несколько сотен, а видеокарта и процессор слабые, мне кажется, на операции выделения компьютер может подвиснуть.