2023-07-21 07:54 PM
I am looking to modify the Excel Exporter script provided by Graphisoft to give me a list of objects, their associated rooms/levels, and a handful of User Defined properties. I'm having a few issues that I could use some help with:
Can anyone help me with this?
from archicad import ACConnection, handle_dependencies
from typing import List
import os, sys
handle_dependencies('openpyxl')
from openpyxl import Workbook
conn = ACConnection.connect()
assert conn
acc = conn.commands
act = conn.types
acu = conn.utilities
scriptFolder = os.path.dirname(os.path.realpath(__file__))
################################ CONFIGURATION #################################
worksheetTitlesAndElements = {
"Objects": acc.GetElementsByType("Object"),
}
propertyUserIds = [
act.BuiltInPropertyUserId("General_ElementID"),
act.BuiltInPropertyUserId("IdAndCategories_Name"),
#these properties are all returning blank values; I want them to give me the object room and level name and number
act.BuiltInPropertyUserId("General_RelatedZoneName"),
act.BuiltInPropertyUserId("General_RelatedZoneNumber"),
act.BuiltInPropertyUserId("General_FromZone"),
act.BuiltInPropertyUserId("General_FromZoneNumber"),
#down here I'd like to add some user defined properties but can't get the syntax to work. I have tried the act.UserDefinedPropertyUserID method and it gives me an error, something to do with classes and strings
]
outputFolder = scriptFolder
outputFileName = "Objects.xlsx"
################################################################################
def AutoFitWorksheetColumns(ws):
for columnCells in ws.columns:
length = max(len(str(cell.value)) for cell in columnCells)
ws.column_dimensions[columnCells[0].column_letter].width = length
def PrintWorksheetContent(ws):
for columnCells in ws.columns:
for cell in columnCells:
print(f"{ws.title}!{cell.column_letter}{cell.row}={cell.value}")
def FillExcelWorksheetWithPropertyValuesOfElements(ws, propertyIds: List[act.PropertyIdArrayItem], elements: List[act.ElementIdArrayItem]):
propertyValuesDictionary = acu.GetPropertyValuesDictionary(elements, propertyIds)
propertyDefinitionsDictionary = dict(zip(propertyIds, acc.GetDetailsOfProperties(propertyIds)))
ws.cell(row=2, column=1).value = "Element Guid"
row = 3
for element, valuesDictionary in propertyValuesDictionary.items():
ws.cell(row=row, column=1).value = str(element.elementId.guid)
column = 2
for propertyId, propertyValue in valuesDictionary.items():
if row == 3:
ws.cell(row=1, column=column).value = str(propertyId.propertyId.guid)
propertyDefinition = propertyDefinitionsDictionary[propertyId].propertyDefinition
ws.cell(row=2, column=column).value = f"{propertyDefinition.group.name} / {propertyDefinition.name}"
ws.cell(row=row, column=column).value = propertyValue
column += 1
row += 1
AutoFitWorksheetColumns(ws)
PrintWorksheetContent(ws)
propertyIds = acc.GetPropertyIds(propertyUserIds)
wb = Workbook()
ws = wb.active
i = 0
for title, elements in worksheetTitlesAndElements.items():
if i == 0:
ws.title = title
else:
ws = wb.create_sheet(title)
FillExcelWorksheetWithPropertyValuesOfElements(ws, propertyIds, elements)
i += 1
excelFilePath = os.path.join(outputFolder, outputFileName)
wb.save(excelFilePath)
acu.OpenFile(excelFilePath)
if os.path.exists(excelFilePath):
print("Saved Excel")
2023-07-28 10:57 PM
2nd question:
This should work for properties that you have created yourself:
#Example
act.UserDefinedPropertyId(["Product Info - Facilities Management", "Model"]) #First the name of the property group, second the property name(id) in that particular group. Note the square brackets.
1st question:
I don't think that there is a built-in property type for the level/story name that you can use in a Python script to retrieve the information directly from the Archicad project. However, you can create a property (type: expression) inside the Archicad project which retrieves the story/level name and use it in a Python script as a UserDefinedPropertyUserId -type. Just make sure that the property is available for all classifications and the elements are classified. Otherwise, the Excel worksheet will have a blank cell for unclassified elements. Call this property in the same way in the Python script as in the example above.
These two types work with doors and windows but not with objects. Therefore, they return a blank value to cells in an Excel worksheet.
act.BuiltInPropertyUserId("General_FromZone"), act.BuiltInPropertyUserId("General_FromZoneNumber"),
These two, in other hand, should work with the objects. At least I got the right data transferred to Excel. The only time the data didn't show up in the Excel file was when the layer of the zones was invisible in the project when running the script.
act.BuiltInPropertyUserId("General_RelatedZoneName"), act.BuiltInPropertyUserId("General_RelatedZoneNumber"),
-JT