(Russian) Задаём свойства объектам в ArchiCAD 23 через Python

Ivan @ 06 / 09 / 2020 @ ArchiCAD / BIM / Медиа / Памятки / Programming / Уроки
( / / / )

Время чтения: ~ 9 мин.

Sorry, this entry is only available in Russian. For the sake of viewer convenience, the content is shown below in the alternative language. You may click the link to switch the active language.

Написал программу, задающую свойства объектов из списка (список хранится в excel, сохранённый из ArchiCAD, потому что Graphisoft не догадались сделать функцию в своём питоновском api, через которую можно было бы получить размеры библиотечного (очевидно, GDL) элемента).
Все сказано в ролике, текст программы ниже sort_and_rename_the_holes.py.
Ещё про питон — см. в рубрике программирование.

import os
import sys
import xlrd


theStart=0 #these two params allow to limit the script so it could somehow run in AC: start from 0 index

excelFilePath = os.path.join (os.path.dirname (sys.argv[0]), "scheme.xls") #change scheme.xls with your file name
if os.path.isfile (excelFilePath) is False:
    sys.exit ("File does not exist: {}".format (excelFilePath))
xl_workbook = xlrd.open_workbook(excelFilePath)
xl_sheet = xl_workbook.sheet_by_index(0)

class hole: # create a class of an object hole in which we will store the data to use later 
    def __init__(self, the_id, width_height):
        self.the_id = the_id
        self.width_height = width_height
holesList = []
sizesList = []
sizeDictionary = {}

for row in range (i,xl_sheet.nrows): # create objects and put them into a dictionary, organized by objectSize
        objectWidth = (xl_sheet.cell_value(row, colx=0))
        objectHeight = (xl_sheet.cell_value(row, colx=1))
        objectGUID = (xl_sheet.cell_value(row, colx=2))
        objectSize = str(int(objectWidth)) + "/" + str(int(objectHeight))
        holesList.append(hole(str(objectGUID), objectSize))
        if objectSize in sizeDictionary:
            sizeDictionary[objectSize].append(hole (str(objectGUID), objectSize))
            sizeDictionary[objectSize]=[hole (str(objectGUID), objectSize)]

print ("dictionary length:", len(sizeDictionary.keys()), str(sizeDictionary.keys())) #output the number of object sizes and their names

cycleIterator = 0 # overall progress iterator
for key in sizeDictionary.keys(): #cycle through the dictionary keys
    typeNumber = i+1 # add 1 to the type iterator as we need the mark star from 1, not 0
    if (cycleIterator <= theEnd and cycleIterator >= theStart): #if we are in our set range, print the current size list
        print ('{:-^60}'.format ("  "+str(typeNumber)+" :  "+str(key)+"  "))
    for obj in sizeDictionary[key]: # cycle through the object list in the dictionary list of current object size
        cycleIterator += 1
        elem = obj.the_id # put a link to the object id into the elem variable to use in the api calls
        if (cycleIterator <= theEnd and cycleIterator >= theStart): # if we are in the set range, go in and process the items
            for d in GetElementPropertyDefinitionDictionary (elem, API_PropertyDefinitionFilter_UserDefined).values(): # get the current object's definition dictionary (api call), and cycle through all its properties (which are Archicad API objects)
                if (d.canValueBeEditable and d.defaultValue.hasExpression == False): # if we have our value editable and not default (which is probably not needed), go on...
                        p=GetElementProperty (elem, d.guid) #  ...store the link to the object's property object in the p variable...
                        if  p.definition.name == "Марка отверстия": # ...if the name of the propery is the one we need, go on...
                            #print (p.definition.name)
                            theProperty = p # excessive line, but let it be
                            #print (theProperty.value, typeNumber)
                            if theProperty.value != typeNumber: #if the property value is not the one we need, change its properties. (theProperty is a link to the AC API object, we are checking) 
                                theProperty.isDefault = False # set it to be not default
                                theProperty.value = str(typeNumber) # set the property value to be String of our number 
                                try: # to avoid the termination of the program, if the API call won't work, wrap it into try...except
                                    SetElementProperty (elem, theProperty) # call the API function to set the property (passing it the elem wich is the elemet object and theProperty as described earlier
                                    print (str(cycleIterator)+" of "+str(theEnd)+" > Set the number "+str(typeNumber)+" successfully ") # if we are ok, move on
                                    print (str(cycleIterator)+" of "+str(theEnd)+" > Couldn't set the "+str(typeNumber)+" number for "+str(obj.the_id)) # if not, tell us about it              
    i += 1 # add 1 to the global iterator

print ("{:-^60}".format ("DONE (from "+str(theStart)+" to "+str(theEnd)+")"))



Similar Posts:



Подпишитесь на обновления

* нажимая на кнопку «Подписаться», вы даете согласие на обработку своих персональных данных