blog/

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

Ivan @ 06 / 09 / 2020 @ Blog / ArchiCAD / BIM и CAD / Медиа / Памятки / Программирование / Уроки
( / / / )

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

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

import os
import sys
import xlrd

i=0

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


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))
        else:
            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
                                except:
                                    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)+")"))

 

 


Может быть интересно:


Подпишитесь на нас в социальных сетях!

Instagram
VK
Facebook
YouTube!
Telegram!

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



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