9 août 2020

[Dynamo += Python ] Gestion des sous-projets des maquettes liées

 



Comment gérer les états des sous projets en Python avec l'API Revit ?


Suite à une idée d'amélioration, voici un exemple de script permettant de gérer l'ouverture et la fermeture des sous-projets d'une maquette liée tout-en-IronPython 😁 (avec une interface Winform)

Le seul moyen à ce jour pour changer les états des sous-projets d'une maquette liée via l'API Revit c'est de rechargé le lien avec une configuration via la méthode LoadFrom()

Dans l'exemple ci-après, on crée une configuration par défaut où les sous projets "utilisateur" sont fermés. Puis on ouvre ceux que l'on souhaite avec la méthode Open() 

WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)

Pour ceux qu'ils souhaitent ce script peut être encore amélioré avec l'intégration d'un TreeNode regroupant l'ensemble des maquettes liées (mode collaboratif activé), ou chaque nœud principal serait une maquette liée.

J'en profite pour y introduire un bref exemple de gestion multi-langage sur une Interface User grâce à l'API Revit

 if app.Language == Autodesk.Revit.ApplicationServices.LanguageType.French


 
import clr
import sys
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *

#import net library
clr.AddReference('System')
from System.Collections.Generic import List

clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

#Get Important vars
doc = DocumentManager.Instance.CurrentDBDocument
uiapp = DocumentManager.Instance.CurrentUIApplication
app = uiapp.Application

clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
import System.Drawing
import System.Windows.Forms

from System.Drawing import *
from System.Windows.Forms import *

class WksetLnkUtils(Form):
    def __init__(self):
        rvtLinkInst = FilteredElementCollector(doc).OfClass(RevitLinkInstance)
        self._dictRvtInstance = {}
        for x in rvtLinkInst:
            _lkdoc = x.GetLinkDocument()
            if _lkdoc.IsWorkshared:
                self._dictRvtInstance[x.Name] = x
        self._dictWkset = {}
        self.rvtRvtlinkType = None
        self.out = None
        self.InitializeComponent()
    
    def InitializeComponent(self):
        self._groupBox1 = System.Windows.Forms.GroupBox()
        self._checkedListBox1 = System.Windows.Forms.CheckedListBox()
        self._buttonOpen = System.Windows.Forms.Button()
        self._buttonClose = System.Windows.Forms.Button()
        self._comboBoxRvtLink = System.Windows.Forms.ComboBox()
        self._groupBox2 = System.Windows.Forms.GroupBox()
        self._groupBox1.SuspendLayout()
        self._groupBox2.SuspendLayout()
        self.SuspendLayout()
        # 
        # groupBox1
        self._groupBox1.Controls.Add(self._checkedListBox1)
        self._groupBox1.Location = System.Drawing.Point(30, 123)
        self._groupBox1.Name = "groupBox1"
        self._groupBox1.Size = System.Drawing.Size(361, 423)
        self._groupBox1.TabIndex = 0
        self._groupBox1.TabStop = False
        self._groupBox1.Text = "Select Workset"
        # 
        # checkedListBox1
        self._checkedListBox1.FormattingEnabled = True
        self._checkedListBox1.Items.Clear()
        self._checkedListBox1.Location = System.Drawing.Point(16, 42)
        self._checkedListBox1.Name = "checkedListBox1"
        self._checkedListBox1.Size = System.Drawing.Size(326, 361)
        self._checkedListBox1.TabIndex = 0
        # 
        # buttonOpen
        self._buttonOpen.Location = System.Drawing.Point(60, 560)
        self._buttonOpen.Name = "buttonOpen"
        self._buttonOpen.Size = System.Drawing.Size(300, 40)
        self._buttonOpen.TabIndex = 1
        if app.Language == Autodesk.Revit.ApplicationServices.LanguageType.French:
            self._buttonOpen.Text = "Ouvrir les sous-projets selectionnés \n(les autres seront fermés)"
        else:
            self._buttonOpen.Text = "Open Selected Worksets (others will be close)"     
        self._buttonOpen.UseVisualStyleBackColor = True
        self._buttonOpen.Click += self.ButtonOpenClick
        # 
        # buttonClose
        self._buttonClose.Location = System.Drawing.Point(60, 620)
        self._buttonClose.Name = "buttonClose"
        self._buttonClose.Size = System.Drawing.Size(300, 40)
        self._buttonClose.TabIndex = 1
        if app.Language == Autodesk.Revit.ApplicationServices.LanguageType.French:
            self._buttonClose.Text = "Fermer les sous-projets selectionnés \n(les autres seront ouverts)"
        else:
            self._buttonClose.Text = "Close Selected Worksets (others will be open)"
        self._buttonClose.UseVisualStyleBackColor = True
        self._buttonClose.Click += self.ButtonCloseClick
        # 
        # comboBoxRvtLink
        self._comboBoxRvtLink.Items.AddRange(System.Array[System.Object](self._dictRvtInstance.keys()))
        self._comboBoxRvtLink.FormattingEnabled = True
        self._comboBoxRvtLink.Location = System.Drawing.Point(19, 41)
        self._comboBoxRvtLink.Name = "comboBoxRvtLink"
        self._comboBoxRvtLink.Size = System.Drawing.Size(323, 24)
        self._comboBoxRvtLink.TabIndex = 2
        self._comboBoxRvtLink.SelectedIndexChanged += self.ComboBoxRvtLinkSelectedIndexChanged
        # 
        # groupBox2
        self._groupBox2.Controls.Add(self._comboBoxRvtLink)
        self._groupBox2.Location = System.Drawing.Point(30, 17)
        self._groupBox2.Name = "groupBox2"
        self._groupBox2.Size = System.Drawing.Size(361, 89)
        self._groupBox2.TabIndex = 3
        self._groupBox2.TabStop = False
        self._groupBox2.Text = "Select Revit Link"
        # 
        # MainForm
        self.ClientSize = System.Drawing.Size(430, 700)
        self.Controls.Add(self._groupBox2)
        self.Controls.Add(self._buttonClose)
        self.Controls.Add(self._buttonOpen)
        self.Controls.Add(self._groupBox1)
        self.Name = "WksetLnkUtils"
        self.Text = "Manage linked model Worksets"
        self._groupBox1.ResumeLayout(False)
        self._groupBox2.ResumeLayout(False)
        self.ResumeLayout(False)


    def setLinkstatut(self, wksetsId):
        if self.rvtRvtlinkType is not None:
            #create WorksetConfiguration with CloseAllWorksets by default
            wkstConfig = WorksetConfiguration(WorksetConfigurationOption.CloseAllWorksets)
            lstWksetId = List[WorksetId](wksetsId)
            wkstConfig.Open(lstWksetId) 
            loada = self.rvtRvtlinkType.LoadFrom(self.mpath, wkstConfig)
            self.out = loada.LoadResult
            wkstConfig.Dispose()        
            
    def ButtonOpenClick(self, sender, e):
        wksetsId = [ self._dictWkset.get(wksetnam) for wksetnam in self._checkedListBox1.CheckedItems]
        self.setLinkstatut(wksetsId)


    def ButtonCloseClick(self, sender, e):
        self.wksetsId = []
        #get items are not checked for open others Worksets
        setDiff = set(self._checkedListBox1.Items) - set(self._checkedListBox1.CheckedItems)
        wksetsId = [ self._dictWkset.get(wksetnam) for wksetnam in setDiff]
        self.setLinkstatut(wksetsId)


    def ComboBoxRvtLinkSelectedIndexChanged(self, sender, e):
        rvtLinkInstance = self._dictRvtInstance.get(sender.Text)
        self.rvtRvtlinkType = doc.GetElement(rvtLinkInstance.GetTypeId())
        _linkdoc = rvtLinkInstance.GetLinkDocument()
        _worksetTable = _linkdoc.GetWorksetTable()
        self.mpath = _linkdoc.GetWorksharingCentralModelPath()
        
        lstPreview =  WorksharingUtils.GetUserWorksetInfo(self.mpath)
        self._dictWkset = {item.Name : _worksetTable.GetWorkset(item.Id).Id for item in lstPreview }
        self._checkedListBox1.Items.Clear()
        self._checkedListBox1.Items.AddRange(System.Array[System.Object](self._dictWkset.keys()))
        
objForm = WksetLnkUtils()
objForm.Show()

OUT = 0

Voilà à vos claviers, avec ou sans glaces 
Home - Roezelec, électricité générale à Roézé sur Sarthe Il fait chaud! | Dessin smiley, Emoticone amour, Smileys

4 commentaires:

  1. Excellent. Je vais l'essayer de suite. Merci

    RépondreSupprimer
  2. Adding
    # -*- coding: latin-1 -*-
    and it works well in a pyrevit toolbar

    RépondreSupprimer
  3. Bonjour Cyril, excellent script! Quelles sont les modifications à faire pour que ce script fonctionne avec des maquettes hébergées sur le BIM360 (cloud)? De mon côté le script fonctionne seulement sur les maquettes sur un réseau "local". Merci!

    RépondreSupprimer
    Réponses
    1. Bonjour,
      Actuellement je n'ai pas accès à BIM360, donc je ne sais
      (je suppose qu'il faut utiliser la méthode 'LoadFrom Method (ExternalResourceReference, WorksetConfiguration)')
      Je mettrai l'article à jour si le cas se présente

      Supprimer