Доброго времени суток, коллеги! Вопрос был от меня по факту. Поясню ситуацию: необходимо проработать библиотеку материалов в очень большом объёме - задать правильные параметры идентификации, графики и представления. Общиё объём данных - 500+ позиций. Выполнять данный процесс вручную крайне нудно и тяжело, поэтому и возник вопрос об автоматизации этого процесса.
Так же хотел бы пояснить, что до этого с этим делом справлялся с помощью языка AutoIT - писал кликер, который у нужные окна подставляет нужную информацию и производит нужные клики в нужных местах окна. И в целом оно работает, но это не совсем корректный путь, да и способ доступа к библиотеке получается не унифицировать.
Задача наполнения библиотеки ещё осложняется тем, что в перспективе данную базу придётся модифицировать добавлением физических и термальных представлений.
Ниже приведу код, сразу оговорюсь, что программировать стал не так давно, поэтому понимаю, что код можно улучшить и упростить
; Кликер для добавления нужных материалов в библиотеку материалов Revit
#include <Array.au3>
#include <Excel.au3>
#include <MsgBoxConstants.au3>
#include <Date.au3>
#include <File.au3>
HotKeySet("{ESC}", "Terminate")
AutoItSetOption("MouseCoordMode",0)
Global $nSchot
$nSchot = 0 ; Глобальный счётчик
;~ $hWindow = _OpenMaterialManager()
;~ $sExcelFile = "D:\kad\documents\Задания\clicker_revit_materials\gost_14332.xlsx"
; Для автоматического подсчёта количества всей проделанной работы
$aExcelFiles = _FileListToArray('D:\kad\documents\Задания\clicker_revit_pipes\xlsx','*',$FLTA_FILES,True)
For $ni5 = 1 to $aExcelFiles[0] Step 1
$sExcel = _OpenExcel($aExcelFiles[$ni5]) ; Открыли Excel и получили ссылку на таблицу
$nNumberStroks = _KolStrokVExcel($sExcel) ; Получили количество строк в файле
Next
; Для диспетчера материалов
;~ $nMMWindow = _MaterialWinMove() ; Получили переименованное окно Диспетчера материалов
;~ _DeleteOldMaterials($nMMWindow)
;~ For $ni2 = 1 to $nNumberStroks Step 1 ; Удаляем старые
;~ _DeleteWrongMaterials(); материалы
;~ Next ; из библиотеки
;~ $sExcel = _OpenExcel($sExcelFile) ; Открыли Excel и получили ссылку на таблицу
;~ $s = 1
;~ $sMatWindow = _AddNewMaterial($s,$sExcel)
;~ _AddNewMaterialToLib($sMatWindow)
;~ _DeleteNewMat()
;~ $sExcel = _OpenExcel($sExcelFile) ; Открыли Excel и получили ссылку на таблицу
;~ For $s = 1 to $nNumberStroks Step 1
;~ $sMatWindow = _AddNewMaterial($s,$sExcel) ; Добавляет новый материал в ПРОЕКТ
;~ _AddNewMaterialToLib($sMatWindow) ; Добавляет новый материал в БИБЛИОТЕКУ
;~ _DeleteNewMat()
;~ Next
;~ ConsoleWrite(@ScriptLineNumber & ' ' & $nSchot & @CRLF)
; Возвращаемся в редактор кода
$hWnd1 = WinWait('[CLASS:SciTEWindow]','Source',2)
$hWnd2 = WinActivate($hWnd1)
Func _OpenExcel($sExcelFile); Открываем наш excel файл
Local $oExcel = _Excel_Open()
If @error Then Exit MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_RangeRead Example", "Error creating the Excel application object." & @CRLF & "@error = " & @error & ", @extended = " & @extended)
Local $oWorkbook = _Excel_BookOpen($oExcel, $sExcelFile)
If @error Then
MsgBox($MB_SYSTEMMODAL, "Excel UDF: _Excel_RangeRead Example", "Error opening workbook '" & $sExcelFile & @CRLF & "@error = " & @error & ", @extended = " & @extended)
_Excel_Close($oExcel)
Exit
EndIf
Return $oWorkbook
EndFunc
Func _OpenMaterialManager()
Local $hWnd1, $hWnd2, $hWnd3, $hWnd4
$hWnd1 = WinWait('Диспетчер материалов - Аналитическая модель поверхности перекрытия','',2) ; Нашли окно Диспетчер материалов
If $hWnd1 = 0 Then ; Если окно закрыто
$hWnd2 = WinWait('Autodesk Revit 2015 - [План этажа: Уровень 1 - Проект1]','', 2) ; Нашли окно Revit
$hWnd3 = WinActivate($hWnd2) ; Нашли окно Revit
WinSetState ($hWnd3, '', @SW_MAXIMIZE ) ; Развернули на весь экран
MouseClick("main",895,35,1,10) ; Кликнули Управление
MouseClick("main",103,65,1,10) ; Кликнули Материалы
EndIf
$hWnd1 = WinWait('Диспетчер материалов - Аналитическая модель поверхности перекрытия','',2) ; Нашли окно Диспетчер материалов
If $hWnd1 = 0 Then
Exit 0
EndIf
$hWnd4 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
ControlClick($hWnd4, '', '[CLASS:QWidget; INSTANCE:1]', "main",1,66,102)
Return $hWnd4
EndFunc
Func _DeleteOldMaterials($hWindow)
$hWnd1 = WinActivate($hWindow) ; Активировали окно Диспетчер материалов
ControlClick($hWnd1, '', '[CLASS:QWidget; INSTANCE:1]', "main",1,85,140) ; Щёлкнули по первому материалу
For $ni1 = 1 to 17 Step 1
Send("{DEL}")
Next
EndFunc
Func _AddNewMaterial($s,$sExcel)
Local $hWnd1, $hWnd2, $hWnd3, $hWnd4
BlockInput(1)
$hWnd1 = WinWait('Диспетчер материалов','WinWidget',2) ; Нашли окно Диспетчер материалов
$hWnd2 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
; Считываем информацию из таблицы excel
$sReadColumnA = _Excel_RangeRead($sExcel, Default, "A" & $s) ; ГОСТ
$sReadColumnB = _Excel_RangeRead($sExcel, Default, "B" & $s) ; Наименование ГОСТ
$sReadColumnC = _Excel_RangeRead($sExcel, Default, "C" & $s) ; Тип материала
$sReadColumnD = _Excel_RangeRead($sExcel, Default, "D" & $s) ; Суффикс "_GAL"
$sReadColumnE = _Excel_RangeRead($sExcel, Default, "E" & $s) ; Комментарий
$sReadColumnJ = _Excel_RangeRead($sExcel, Default, "J" & $s) ; Марка
; Копируем исходный материал
ControlClick($hWnd2, '', '[CLASS:QWidget; INSTANCE:1]', "right",1,75,110) ; ПКМ вызвали меню
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{ENTER}")
Sleep(25)
; Заполняем наименование
$hWnd2 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
For $ni1 = 1 To 16 Step 1 ; Добираемся табами до поля ввода
Send("{TAB}")
Sleep(20)
Next ; Добрались
Send("{DEL}")
$sToSend = $sReadColumnJ & "_" & $sReadColumnA & $sReadColumnD
Send($sToSend)
Sleep(50)
Send("{TAB}") ; Перешли на Описание
; Заполняем описание
Sleep(25)
Send("^a")
Sleep(25)
Send("{DEL}")
$sToSend = $sReadColumnB
Send($sToSend)
Sleep(50)
Send("{TAB}") ; Перешли на Класс
Sleep(25)
; Заполняем класс
Send("^a")
Sleep(25)
Send("{DEL}")
$sToSend = $sReadColumnC
Send($sToSend)
Sleep(50)
Send("{TAB}")
Sleep(25)
Send("{TAB}") ; Перешли на комментарий
Sleep(25)
; Заполняем комментарий
$sToSend = $sReadColumnE
Send($sToSend)
Sleep(25)
Send("{ENTER}")
$sToSend = _NowCalc()
Send($sToSend)
Sleep(50)
Send("{TAB}") ; Перешли на Ключевые слова
Sleep(25)
; Заполняем ключевые слова
$sToSend = $sReadColumnJ & ', ' & $sReadColumnA & ', ' & $sReadColumnC
Send($sToSend)
Sleep(50)
Send("{TAB}")
Sleep(25)
Send("{TAB}")
Sleep(25)
Send("{TAB}")
Sleep(25)
Send("{TAB}")
Sleep(25)
Send("{TAB}")
Sleep(25)
Send("{TAB}")
Sleep(25)
Send("{TAB}")
Sleep(25)
Send("{TAB}") ; Перешли на маркировку
Sleep(25)
; Заполним маркировку
$sToSend = $sReadColumnJ
ConsoleWrite(@ScriptLineNumber & ' ' & $sToSend & @CRLF)
Send($sToSend)
ControlClick($hWnd2, '', '[CLASS:QWidget; INSTANCE:1]', "main",1,440,230) ; Сбросили выделение
BlockInput(0)
$nSchot = $nSchot + 1
Return $hWnd2
EndFunc
Func _AddNewMaterialToLib($sMatWindow)
Local $hWnd1, $hWnd2, $hWnd3, $hWnd4
$hWnd1 = WinWait($sMatWindow,'',2) ; Нашли окно Диспетчер материалов
$hWnd2 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
ControlClick($hWnd2, '', '[CLASS:QWidget; INSTANCE:1]', "right",1,147,150)
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{RIGHT}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{RIGHT}") ; Перешли на последнее вложение
Sleep(25)
Send("{DOWN}") ; 1
Sleep(25)
Send("{DOWN}") ; 2
Sleep(25)
Send("{DOWN}") ; 3
Sleep(25)
Send("{DOWN}") ; 4
Sleep(25)
;~ Send("{DOWN}") ; 5
;~ Sleep(25)
;~ Send("{DOWN}") ; 6
;~ Sleep(25)
;~ Send("{DOWN}") ; 7
;~ Sleep(25)
;~ Send("{DOWN}") ; 8
;~ Sleep(25)
;~ Send("{DOWN}") ; 9
;~ Sleep(25)
;~ Send("{DOWN}") ; 10
;~ Sleep(25)
;~ Send("{DOWN}") ; 11
;~ Sleep(25)
Send("{ENTER}")
EndFunc
Func _DeleteNewMat()
$hWnd1 = WinWait('Диспетчер материалов','WinWidget',2) ; Нашли окно Диспетчер материалов
$hWnd2 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
ControlClick($hWnd2, '', '[CLASS:QWidget; INSTANCE:1]', "right",1,70,150)
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{DOWN}")
Sleep(25)
Send("{ENTER}")
EndFunc
Func _MaterialWinMove() ; Двигаем наше окно
$hWnd1 = WinWait('Диспетчер материалов','WinWidget',2) ; Нашли окно Диспетчер материалов
$hWnd2 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
$hWnd3 = WinMove($hWnd1,'',0,0,(1920/2),(1040/2)) ; Активировали окно Диспетчер материалов
Sleep(500)
;~ $hWnd4 = WinSetTitle($hWnd2,'','Manager') ; Активировали окно Диспетчер материалов
Return $hWnd2
EndFunc
Func Terminate()
Exit 0
EndFunc
Func _DeleteWrongMaterials()
$hWnd1 = WinWait('Диспетчер материалов','WinWidget',2) ; Нашли окно Диспетчер материалов
$hWnd2 = WinActivate($hWnd1) ; Активировали окно Диспетчер материалов
ControlClick($hWnd2, '', '[CLASS:QWidget; INSTANCE:1]', "right",1,300,351)
Sleep(100)
Send("{DOWN}")
Sleep(100)
Send("{DOWN}")
Sleep(100)
Send("{ENTER}")
Sleep(100)
EndFunc
Func _KolStrokVExcel($sExcel) ; Автоматический подсчёт строк в екселе
Local $s, $sReadColumnA
$s = 1
$sReadColumnA = 1
While $sReadColumnA <> ''
$sReadColumnA = _Excel_RangeRead($sExcel, Default, "A" & $s)
$s = $s + 1
WEnd
$s = $s - 2
;~ ConsoleWrite(@ScriptLineNumber & ' ' & $s & @CRLF)
ConsoleWrite($s & @CRLF)
Return $s
EndFunc
Так же пытался добраться до материалов с помощью файлов журнала. Опять же получается достаточно трудоёмко и отсутствует возможность перемещать созданные материалы в библиотеку в нужный раздел.
' Build: 20140322_1515(x64)
' Branch: RELEASE_2015_RTM
Dim Jrn
Set Jrn = CrsJournalScript
' Открываем новый, пустой проект
Jrn.Command "StartupPage" , "Create a new project , ID_FILE_NEW_CHOOSE_TEMPLATE"
Jrn.PushButton "Modal , New Project , Dialog_Revit_NewProject" , "OK, IDOK"
Jrn.Directive "DocSymbol" , "[Project1]"
Jrn.Data "TaskDialogResult" , "Which system of measurement do you want to use in your project?", "Metric", "1002"
Jrn.Data "Transaction Successful" , "Create Type Previews"
' Жмакаем на панельку с материалами
Jrn.RibbonEvent "TabActivated:Manage"
' Открываем материалы
Jrn.Command "Internal" , "Modify materials , ID_SETTINGS_MATERIALS"
' Добавляем новый материал
Jrn.WidgetEvent "MaterialSelected" , "Modal , Material Browser , Dialog_Revit_MaterialBrowser"
Jrn.Data "AssetIdName" , "PhysMat", "Default"
Jrn.WidgetEvent "ShowMaterialEditor" , "Modal , Material Browser - Default , Dialog_Revit_MaterialBrowser"
Jrn.Data "ShowMaterialEditor" , 1, "Default", 1
' Выбор того чего будем дублировать
Jrn.WidgetEvent "SelectAspect" , "Modal , Material Browser - Default , Dialog_Revit_MaterialBrowser"
Jrn.Data "AssetAspect" , "Graphics"
' Процедура дублирования
Jrn.WidgetEvent "DuplicateAsset" , "Modal , Material Browser - Default , Dialog_Revit_MaterialBrowser"
Jrn.Data "AssetInfo" , "", "", "Default" , ""
' Выбор дублированного материала
Jrn.WidgetEvent "MaterialSelected" , "Modal , Material Browser - Default , Dialog_Revit_MaterialBrowser"
Jrn.Data "AssetIdName" , "PhysMat", "Default(1)"
' Переименование дублированного материала
Jrn.WidgetEvent "RenameAsset" , "Modal , Material Browser - Default(1) , Dialog_Revit_MaterialBrowser"
Jrn.Data "RenameAsset" , "Default(1)", "New material over GOST"
' Удаление выделенного материала
'Jrn.PushButton "Modal , Material Browser - Default(1) , Dialog_Revit_MaterialBrowser" , "OK, IDOK"
'Jrn.Data "Transaction Successful" , "Materials"