blog/
Задаём свойства объектам в ArchiCAD 23 через Python
Написал программу, задающую свойства объектов из списка (список хранится в 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)+")"))
Может быть интересно:
- Скрипт для выбора победителя в инстаграме (из лайков)
- Скрипт для выбора победителя в инстаграме (из комментариев)
- Про Python и ArchiCAD: удалить лишние слои
- Как разыграть бесплатные места на курсе вёрстки для архитекторов (JS+Instagram)
- Свойства и формулы в Archicad: открывание дверей (англ+рус)
░