Копирование и переименования даталей сборок и подсборок с помощью VBA

Автор Тема: Копирование и переименования даталей сборок и подсборок с помощью VBA  (Прочитано 10439 раз)

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

Оффлайн ШашлыкАвтор темы

  • ADN OPEN
  • Сообщений: 8
  • Карма: 0
Всем привет!
Для работы с Inventor использую python и библиотеку pywin32.

У меня есть сборка состоящая только из деталей. Эта шаблонная сборка, то есть когда в каком-то из проекте нужна данная сборка, то она копируется и каждый файл переименовывается в соответствии с проектом. Заменяю компоненты в сборке таким образом:

inventor = wc.GetActiveObject('Inventor.Application')
doc = inventor.ActiveDocument

for ref_file in doc.File.ReferencedFileDescriptors:
    ...
    ref_file .ReplaceReference(...)

В таком подходе у меня не возникает проблем и копируются все свойства сборки.
Сейчас у меня появилась аналогичная задача, только копировать более сложную сборку, в которую входят другие сборки и уже не получается просто взять и поменять компоненты сборки, так как надо менять компоненты подсборок и т.д.
Если бы не приходилось переименовывать файлы, то можно было бы просто копировать через Ctrl + C.
Копировать хочу полностью автоматически, без использования Disign Assistent и т.п.

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


Вот и возникает вопрос можно ли как-то это автоматизировать? Ведь бывают большие сборки где десятки деталей




Оффлайн filat

  • ADN Club
  • ****
  • Сообщений: 265
  • Карма: 2
Обход подсборок выполняется через вызов подпрограммы, по условию.
Вот пример подобного цикла, думаю разберешься.  ;)
https://adn-cis.org/forum/index.php?topic=9999.msg44879#msg44879

Оффлайн R.I.Chernov

  • ADN Club
  • *****
  • Сообщений: 568
  • Карма: 18
Добрый день!

Возможно я немного оффтопик скажу, но для вашей операции есть встроенный функционал инвертора. Как подключиться к нему программно ( если это вобще возможно) я не знаю, но вот от «замены руками» он вам точно спасёт. В волте тоже есть копирование, но оно глючное, некорректно работает, если используете наследование. В целом вопрос наследования - главная проблема при копировании. Потому как, если его не используете, то просто рекурсивно открываете все подсборки, делаете в них замену и закрываете - точно также, ее вы это делали для главной сборки.
П.С. Если правильно работать с проектами инвертора, то от переименовывания деталей в целом можно отказаться, вы можете копировать сборку целиком в папку проекта ( и, например, переименовать только ее). По умолчанию сборка ищет детали в своей подпапке и папке проекта, детали из других проектов тащить не будет, даже если они одноименные. Другое дело, что если вы хотите с имён деталей номера брать, но тут опять же вопрос решаемый.  Хотя, на мой вкус, переименовывать детали все же лучше, чем не переименовывать ))
В программировании я новичок...но ненадолго! ;)

Оффлайн R.I.Chernov

  • ADN Club
  • *****
  • Сообщений: 568
  • Карма: 18
Ну и ещё одна ремарка, опять скорее не про программирование, а про использование инвертора. Если у вас узел типовой и не меняется, в чем необходимость тащить его сборку  из проекта в проект и копировать по сто раз? Можно же сделать отдельный проект-библиотеку с типовыми узлами, подключать его к проектам и использовать.
В программировании я новичок...но ненадолго! ;)

Оффлайн ШашлыкАвтор темы

  • ADN OPEN
  • Сообщений: 8
  • Карма: 0
Ну и ещё одна ремарка, опять скорее не про программирование, а про использование инвертора. Если у вас узел типовой и не меняется, в чем необходимость тащить его сборку  из проекта в проект и копировать по сто раз? Можно же сделать отдельный проект-библиотеку с типовыми узлами, подключать его к проектам и использовать.

Соглашусь
Но не, для данной сборки, так как это параметрическая сборка с изменяемой геометрией

Оффлайн ШашлыкАвтор темы

  • ADN OPEN
  • Сообщений: 8
  • Карма: 0
Обход подсборок выполняется через вызов подпрограммы, по условию.
Вот пример подобного цикла, думаю разберешься.  ;)
https://adn-cis.org/forum/index.php?topic=9999.msg44879#msg44879

Спасибо, помогли в обходе подсборок)
Переименовывание только не вышло
Если переименовать деталь, когда сборка открыта, то тогда её заменить не выйдет, а если переименовать деталь подсборки, до открытия основной сборки, то тогда при открытии основной сборки не получится программно обойти эту подсборку ... 

Оффлайн filat

  • ADN Club
  • ****
  • Сообщений: 265
  • Карма: 2
Если переименовать деталь, когда сборка открыта, то тогда её заменить не выйдет, а если переименовать деталь подсборки, до открытия основной сборки, то тогда при открытии основной сборки не получится программно обойти эту подсборку ...
Вы смешиваете два процесса!
В цикле обхода дерева Вы получаете путь к подсборке! Если эта подсборка требует замены, то вы сохраняете ее по новому адресу! При этом в ней остаются старые ссылки. Нужно по условию вызвать саб(функцию) - эта операция должна быть рекурсивна ко всем элементам, входящим в эту подсборку(т.е. к деталям и другим подсборкам), который выполнит сохранение и замену имен в этой подсборке к входящим элементам. Если не требует - переходим к следующему элементу цикла

Оффлайн ШашлыкАвтор темы

  • ADN OPEN
  • Сообщений: 8
  • Карма: 0
Я правильно понимаю, что для копирования таких сборок Вы предлагаете такой алгоритм:

1) Копировать и переименовать сборку
2) Затем открыть сборку, которая не переименовывалась и у неё заменить детали, на детали из сборки, которую переименовали 

или же во время обхода каждую деталь "сохранить как" ?

Оффлайн filat

  • ADN Club
  • ****
  • Сообщений: 265
  • Карма: 2
или же во время обхода каждую деталь "сохранить как" ?
Открываете файл новой сборки(с новым именем) и для каждого элемента выполняете сохранение под новым именем. А также выполняете замену ссылки для этого элемента - на новую.

Оффлайн ШашлыкАвтор темы

  • ADN OPEN
  • Сообщений: 8
  • Карма: 0
Спасибо за идею, получилось всё реализовать и даже работает )

Если кому-то вдруг будет интересна реализация
Писал на Python, так как буду писать ещё графический интерфейс, но по факту можно всё реализовать на VBA

Код - Python [Выбрать]
  1. import win32com.client as wc32
  2.  
  3.  
  4. def save_as(component, filepath: str, dct_replace: dict) -> str:
  5.     """
  6.    :param component: ...ComponentDefinition.Occurrences
  7.    :param filepath: Полный путь к component
  8.    :param dct_replace: словарь {'Старое имя': 'Новое имя'...}
  9.    :return: Новый путь к component
  10.    """
  11.     name = str(component.Name)
  12.     new_filepath = ""
  13.  
  14.     for old, new in dct_replace.items():
  15.         name = name.replace(old, new)
  16.  
  17.         if not new_filepath:
  18.             new_filepath = filepath.replace(old, new)
  19.         else:
  20.             new_filepath = new_filepath.replace(old, new)
  21.     try:
  22.         component.Name = name
  23.         component.Definition.Document.SaveAs(new_filepath, True)
  24.         component.Replace(new_filepath, True)
  25.     except Exception as error:
  26.         # Если библиотечные файлы или какие-то общие
  27.         print(error, filepath, new_filepath, sep='\n', end='\n\n')
  28.  
  29.     return new_filepath
  30.  
  31.  
  32. def copy_assembly(document, is_recursion: bool, dct_replace: dict, set_unique=None) -> None:
  33.     """
  34.    :param document: InventorApplication.Document
  35.    :param is_recursion: Первый запуск функции или рекурсивно
  36.    :param dct_replace: словарь {'Старое имя': 'Новое имя'...}
  37.    :param set_unique: множество из новых и старых путей компонентов
  38.    :return: None
  39.    """
  40.     if set_unique is None:
  41.         # Множество для добавления в него старых и новых путей к файлам, чтобы которые уже обработаны,
  42.         # чтобы не работать с ними несколько раз, так как в сборках компоненты могут повторятся
  43.         set_unique = set()
  44.  
  45.     if not is_recursion:
  46.         # Начало рекурсии. Когда мы работаем с базовым файлом
  47.         list_component = document.ComponentDefinition.Occurrences
  48.     else:
  49.         # Рекурсия, когда уже начали перебор подсборок
  50.         list_component = document.SubOccurrences
  51.  
  52.     for component in list_component:
  53.         count = int(component.SubOccurrences.Count)
  54.         filepath = str(component.Definition.Document.FullFileName)
  55.  
  56.         if count != 0:
  57.             # Если компонентов в подсборке более 0, то тогда мы заходим в неё и перебираем в рекурсии
  58.             copy_assembly(document=component, is_recursion=True, dct_replace=dct_replace, set_unique=set_unique)
  59.  
  60.         if filepath not in set_unique and 'OldVersions' not in filepath:
  61.             new_file_path = save_as(component=component, filepath=filepath, dct_replace=dct_replace)
  62.             set_unique.add(filepath)
  63.             set_unique.add(new_file_path)
  64.             # print(new_file_path)
  65.  
  66.  
  67. if __name__ == '__main__':
  68.     # Имя сборки, которую необходимо копировать
  69.     path_assembly = r'C:\Users\p.golubev\Desktopробники Inventorестница 3900\ALS.LADDER.ZONE.XX.00.00.000\ALS.LADDER.ZONE.XX.00.00.000.iam'
  70.  
  71.     # Словарь того, какие символы необходимо заменить в именах файлов и компонентов
  72.     dict_replace_name = {r'C:\Users\p.golubev\Desktopробники Inventorестница 3900': r'\\pdm\PKODocs\Inventor Project\Programs_for_constructors\temp',
  73.                          'LADDER.ZONE.XX': 'LEB1553.045.01',
  74.                          'X. ': '4.1 '}
  75.  
  76.     app = wc32.GetActiveObject('Inventor.Application')
  77.     doc = app.Documents.Open(path_assembly)
  78.  
  79.     copy_assembly(document=doc, is_recursion=False, dct_replace=dict_replace_name)
  80.  
  81.     for old, new in dict_replace_name.items():
  82.         doc.DisplayName = doc.DisplayName.replace(old, new)
  83.         path_assembly = path_assembly.replace(old, new)
  84.  
  85.     doc.SaveAs(path_assembly, True)
  86.     doc.Close(True)
  87.  
« Последнее редактирование: 14-05-2024, 17:52:14 от Александр Ривилис »

Оффлайн ШашлыкАвтор темы

  • ADN OPEN
  • Сообщений: 8
  • Карма: 0
или же во время обхода каждую деталь "сохранить как" ?
Открываете файл новой сборки(с новым именем) и для каждого элемента выполняете сохранение под новым именем. А также выполняете замену ссылки для этого элемента - на новую.

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

Поэтому просто взять и "Сохранить как" хорошая идея, но не для встроенных "Генераторов", всё нужен API именно к "Скорректировать файл" ...

Оффлайн filat

  • ADN Club
  • ****
  • Сообщений: 265
  • Карма: 2
Но если просто переименовать файл "ссылочная модель рамы", затем открыть сборку (сборка будет жаловаться, что не может найти этот файл, так как он переименован) и нажать скорректировать файл и выбрать недостающий переименованный файл "ссылочная модель рамы", то генератор рам будет работать.
Все это можно сделать в рамках код, просто внедряется условие не обходить файлы, если они ссылочные...
Для решения описанной задачи VBA и API дают вам равные возможности.

Оффлайн R.I.Chernov

  • ADN Club
  • *****
  • Сообщений: 568
  • Карма: 18
Всё же всё классно, но не для проектируемых рам. В нём есть так называемая "ссылочная модель рамы", которую нельзя просто взять и "Сохранить как", а затем сделать замену, так как после этого ломается генератор рам и уже нельзя его редактировать.

Про генератор рам сто лет назад спрашивал  Владимира Ананьева на конференции Автодеска. Насколько я понял, это модуль/надстройка над инвентором и с помощью API адекватно управлять генератором рамы нельзя. По идее, если вам что-то такое нужно, то требуется создать собственный аналог ))
В программировании я новичок...но ненадолго! ;)