Hi all,
I am running into an issue with sub transactions not being closed but i have no idea why.
I am trying to override dimension values in a loop. It works and i can print out the overridden values fine from the dimensions, but after it’s done, it doesnt change the dimensions and revit gives me the following error:
A transaction or sub-transaction was opened but not closed. All changes to the active document made by External Command will be discarded.
my log shows no errors and the print shows that the dimensions get properly overridden:
I assume the issue is somewhere in the calculate_koppenmaat function. but the logs look fine
Import successful.
got here
('Data has been retrieved from: snip
[<Autodesk.Revit.DB.Dimension object at 0x00000000000021E8 [Autodesk.Revit.DB.Dimension]>, <Autodesk.Revit.DB.Dimension object at 0x00000000000021E9 [Autodesk.Revit.DB.Dimension]>]
('the overridden dimension', <Autodesk.Revit.DB.DimensionSegment object at 0x00000000000021EA [Autodesk.Revit.DB.DimensionSegment]>, 'the value below', '2K + R', 'the form:', '2K + R')
('the overridden dimension', <Autodesk.Revit.DB.DimensionSegment object at 0x00000000000021EB [Autodesk.Revit.DB.DimensionSegment]>, 'the value below', '12K', 'the form:', '12K')
('the overridden dimension', <Autodesk.Revit.DB.Dimension object at 0x00000000000021E9 [Autodesk.Revit.DB.Dimension]>, 'the value below', '14K + R', 'the form:', '14K + R')
Dimensions updated successfully.
Transaction completed successfully.
import sys
import os
import clr
# Dynamically construct the path to the lib directory
user_home = os.path.expanduser("~")
lib_path = os.path.join(user_home, "AppData", "Roaming", "pyRevit", "Extensions", "IA.extension", "lib")
# Add the lib_path to sys.path for JSON_utils import only
sys.path.append(lib_path)
# Import JSON_utils and Revit/pyRevit libraries
try:
# Custom utility import
import JSON_utils
# clr references and RevitServices import
clr.AddReference("RevitServices")
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
# Revit API import
from Autodesk.Revit.UI import Selection
from Autodesk.Revit.DB import Dimension
# pyRevit and rpw imports
from pyrevit import script
from rpw.ui.forms import FlexForm, TextBox, Label, Button, Alert, ComboBox
print("Import successful.")
except ImportError as e:
print("ImportError:", e)
# Define constants
config_name = 'metselwerk_maatvoering'
kop_afkorting = "K"
voeg_afkorting = "V"
rest_afkorting = "R"
overriding_method = "override"
below_method = "below"
above_method = "above"
saved_config = JSON_utils.get_json_data(config_name)
# Access the active document
uidoc = __revit__.ActiveUIDocument
doc = uidoc.Document
# Define utility functions
def verify_inputs(data):
for value in data.values():
if not isinstance(value, int):
try:
int(value)
except ValueError:
return False
return True
def destringify_inputs(data):
return {key: int(value) for key, value in data.items()}
def convert_ft_to_mm(value):
"""Converts feet to millimeters and rounds to two decimal places."""
return round(value * 304.8)
def calculate_koppenmaat(brick_values, override_method, dimension):
brick_values = destringify_inputs(brick_values)
kop, stootvoeg = [brick_values[key] for key in ('kop', 'stootvoeg')]
dimension_value = convert_ft_to_mm(dimension.Value)
x = str(int(round(dimension_value / kop)))
if dimension_value % kop == stootvoeg:
form = x + kop_afkorting + " + " + voeg_afkorting
elif dimension_value % kop == kop - stootvoeg:
form = x + kop_afkorting + " - " + voeg_afkorting
elif dimension_value % kop == 0:
form = x + kop_afkorting
else:
form = str(int(dimension_value // kop)) + kop_afkorting + " + " + rest_afkorting
if override_method == above_method:
dimension.Above = form
elif override_method == below_method:
dimension.Below = form
elif override_method == overriding_method:
dimension.ValueOverride = form
print('the overridden dimension',dimension, "the value below", dimension.Below, "the form:", form)
return form
def get_user_inputs():
dropdown_options = {'override': overriding_method, 'below': below_method, 'above': above_method}
components = [
Label('Kop [mm]:'), TextBox('kop', Text=JSON_utils.get_default_value(saved_config, 'kop')),
Label('Steenhoogte [mm]:'), TextBox('steenhoogte', Text=JSON_utils.get_default_value(saved_config, 'steenhoogte')),
Label('Stootvoeg [mm]:'), TextBox('stootvoeg', Text=JSON_utils.get_default_value(saved_config, 'stootvoeg')),
Label('Lintvoeg [mm]:'), TextBox('lintvoeg', Text=JSON_utils.get_default_value(saved_config, 'lintvoeg')),
Label('Manier van dimension overschrijven:'), ComboBox('override_method', dropdown_options, default=JSON_utils.get_default_value(saved_config, 'override_method') or override),
Button('Selecteer dimensions')
]
form = FlexForm('Gegevens Invoer', components)
form_result = form.show()
if not form_result:
print("User cancelled the input.")
return None
return form.values
def get_dimensions():
try:
selected_elem_refs = uidoc.Selection.PickObjects(Selection.ObjectType.Element, "Select dimensions")
selected_dims = [doc.GetElement(ref) for ref in selected_elem_refs]
selected_dims = [dim for dim in selected_dims if isinstance(dim, Dimension)] # Filter only Dimension types
if not selected_dims:
Alert("No dimensions selected. Please select dimension elements.")
return None
except:
Alert("Selection canceled. No dimensions selected.")
return None
print(selected_dims)
return selected_dims
# Main script execution
if __name__ == "__main__":
inputs = get_user_inputs()
if inputs is None:
print("No input collected.")
else:
brick_values = {key: value for key, value in inputs.items() if key != 'override_method'}
override_method = inputs.get('override_method')
if verify_inputs(brick_values):
try:
JSON_utils.store_json_data(config_name, inputs)
dimensions = get_dimensions()
if dimensions:
TransactionManager.Instance.EnsureInTransaction(doc) # Start the transaction
forms = []
for dims in dimensions:
if dims.Value is None:
form = [calculate_koppenmaat(brick_values, override_method, dim) for dim in dims.Segments]
else:
form = [calculate_koppenmaat(brick_values, override_method, dims)]
forms.append(form)
TransactionManager.Instance.TransactionTaskDone() # Ensure the transaction is completed
print("Dimensions updated successfully.")
else:
print("No dimensions to update.")
finally:
print("Transaction completed successfully.")
else:
print("Invalid inputs provided.")