Найти тему

REVIT API. PyRevit. Массовое фоновое открытие моделей

Оглавление

Бесит

Есть вот задачи в работе координатора, которые прям бесят и заставляют выть - открыть 200 моделей и прокинуть виды, классический пример.

Это бесило когда я только начал, это бесит и сейчас. Но не так давно я начал по-тихоньку учиться писать небольшие скрипты и автоматизации, в этой статье речь пойдет об одном из них.

Попробую описать что он делает:

  • Открывает в фоновом режиме модели с сервера в автоматическом режиме
  • Закрывает и синхронит так же на автомате

Ой, кажется все весьма просто или нет…

ВАЖНОЕ ПРИМЕЧАНИЕ ОДИН
Я не программист! Я координатор, который не программирует, а пишет скрипты по автоматизации, если вы программист, то и сами знаете как что работает и как сделать круче, лучше и вообще вы классные. Тут простыми словами, о вещах, которые мне помогли облегчить работу. Сам код может быть не очень хорош, но он прекрасно справляется со своей задачей.

ВАЖНОЕ ПРИМЕЧАНИЕ ДВА
Все пишется на ironpython под pyrevit

Начало

-2

1- Кодировка файла для того чтобы использовать русские символы.
2- Имя скрипта которое отобразится на кнопке
3- Указание автора скрипта
3- Описание которое отобразится на кнопке

-3

8-13- Импорты, на 11 строчке импорт функции о которой написал тут:

17-18 - Эти строки создают объект вывода, который используется принтов.
script.get_output().close_others(all_open_outputs=True) закрывает все открытые выводы, чтобы избежать их накапливания.

20 - получаем активный документ Revit и сохраняет его в переменной doc, чтобы можно было обращаться к нему в коде.
21 - получаем апликейшен
22 - получаем имя пользователя, который в данный момент использует Revit, и сохраняет его в переменной user.

23-24- создаем экземпляр класса для подсчета времени и настраиваем формат

Создание локальной копии и получение пути для их хранения

Возрадуемся братья и сестры и скажем аллилуйя, что можно открывать модели в фоновом режиме! Аллилуйя!

В API есть такой вот метод - OpenDocumentFile()

OpenDocumentFile Method (String)
-4

И вроде все ок, весьма просто - пишем функцию или вызываем все напрямую и вуаля, но основная проблема при использование OpenDocumentFile заключается в том, что у данного метода нет опции создать Локальную копию файла который он будет открывать, что странно, так как настройка отсоединяющая модель есть:

-5

Получается что ФХ будет открыт напрямую и чтобы написать аналог галочки «Создать локальную копию» нужно использовать метод CreateNewLocal класса WorksharingUtils

WorksharingUtils Class
-6

В качестве аргументов ему надо отдать 2 ModelPath:

  • адрес текущей модели
  • адрес новой модели (то есть где-то на диске выделить место и придумать имя самого файла)

И, по хорошему, нужно сохранять в туже папку, в которой у нас хранятся локальные копии при открытие через  интерфейс.
И теперь встал вопрос: а как этот путь получить? 

Мы знаем что:

  • Путь для сохранения мы задаем в настройках ревита
  • Все настройки для ревита хранятся в файле Revit.ini 
  • Данный файл расположен в appdata в папке с нужной версией ревита.

Получается чтобы сгенерировать полный путь до новой модели которую создаст CreateNewLocal надо:

-7

Тут мы:

27- Добираемся до папки где лежат настройки и прибавляем к ним имя файла с настройками, что бы сформировать нормальный путь
28- проверяем существует ли по данному пути такой файл
29- печатаем ошибку если его нет
30- и выкидываем False, чтобы прервать скрипт
31- открывает try чтобы поймать ошибку открытия, в целом можно и без этого
32- используя модуль codecs открываем файл в режиме чтения указав в какой кодировке он encoding='utf-16-le'
33- с помощью next отлавливаем первое совпадение с уловием в строчках. Условие такое "if line.startswith('ProjectPath=')" именно тут лежит путь куда сохраняются локальные файлы по дефолту.
35- закрываем ловлю ошибок
35- печатаем ошибку
36- возвращаем False что бы прервать скрипт

Если кто-то знает как, по-другому получить путь, который задается тут:

-8

буду очень рад помощи.

Создание локальной копии

Опишем функцию

-9

Принимает функция: путь до модели которую хотим открыть и путь куда сохранять, это то для чего мы писали функцию get_project_path_from_ini()
40- запускаем таймер
41- на всякий случай нормализую адрес и сохраняю в переменную folderforsave
42 - забираю у адреса модели имя модели и удаляю «.rvt»
43 - создаю новое имя, используя старое + разделитель + имя пользователя которое хранится в глобальной переменной user
46 - создаю полный адрес для новой модели
49 - проверяем существует ли такая модель и если да удаляем ее (стр 52)

Вообще, ревит в таком случае спрашивает что сделать: заменить или добавить к старой дату и время, тем самым освободив имя, но я для экономии места просто затираю старую локалку

54- открываем try except
55- c помощью ModelPathUtils.ConvertUserVisiblePathToModelPath преобразую ссылку на модель в экземпляр класса ModelPath с которым ревит может работать
56- аналогично
57- наконец-то передаем их в метод CreateNewLocal класса WorksharingUtils

WorksharingUtils Class

Итогом работы данной функции является создание локальной копии и возврата нам targetPath- ссылки на локальную копию в виде объекта ModelPath

Открытие моделей

-10

69- создание экземпяра класса OpenOptions()
70- используем свойство Audit задав ему True чтобы открывать с проверкой
71 - создаем настройки рабочих наборов и применяем к ним закрытие
72 - передаем эти настройки к нашему options
73- запускаем таймер
74- на всякий случай обернул в try except
75- от апликешена вызываем открытие модели через OpenDocumentFile передав путь до локальной копии и настройки. Ревит возвращает нам документ файла, которого он откроет, поэтому записываем в переменную doc
76- завершаем подсчет времени
77- печатаем что мы молодцы и сколько это заняло времени
79-80- ловим ошибку и печатаем ее

MAIN

-11

83- вызываем функцию get_project_path_from_ini()
84- проверяем что она не вернула False
85- вызываем функцию select_file(). Она нужна для выбора ссылок на модели. Данную функцию я импортировал на 11 строчке, она самописная. О ней можно прочитать тут

86- проверяем что она нам что-то вернула
87-88- печатаем вступительное слово
89- запускаем таймер общего времени
90-обновляем прогресс бар для визуального отображения хода работы программы
92-начинаем работать со списком моделей которые мы выбрали через sel_models
enumerate используется для итерации по элементам списка и получения индекса элемента (i) и самого элемента (m). Индекс нужен для прогресс бара.
93- печатаем выбранную нами модель
94- вызываем функцию создания локальной копии
95- вызываем функцию открытия модели
96- обновляем прогресс бар
98-100- выводим итоговое время

Итог

Спустя 100 строк кода мы получаем инструмент тотального управления моделями.

Скрипт выдаст вот такое окно:

-12

и теперь если посмотреть скажем через RevitLookup

-13

у нас будет несколько открытых документов, хотя вкладка в Revit всего одна.

Условный JOTools будет видеть эти модели и даст возможность выбрать их как модели, в которые можно что-то скопировать. Другими словами теперь эти модели доступны для редактирования через код или какие то плагины.

Тут разбираем скрипт позволяющий закрыть все эти фоновые модели.

Кстати, есть у меня вот такой тестовый файл размером в 1 Гб

-14

На его открытие ушло всего 2.5 минуты. Разве не чудо?!

-15