Deactivate default unit project settings

Deactivate default unit project settings

ggranadosNFAMX
Contributor Contributor
1,987 Views
11 Replies
Message 1 of 12

Deactivate default unit project settings

ggranadosNFAMX
Contributor
Contributor

Hi everyone!

 

I am working on a code to remove unit symbols on all the selected schedule fields, by now my code is working well over the fields which are not configured to use default project settings, but for those ones using default project settings I am receiving this error:


" Exception : Autodesk.Revit.Exceptions.InvalidOperationException: UseDefault is true in this FormatOptions.
   at Autodesk.Revit.DB.FormatOptions.GetUnitTypeId()
   at Microsoft.Scripting.Interpreter.FuncCallInstruction`2.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.LightLambda.Run3[T0,T1,T2,TRet](T0 arg0, T1 arg1, T2 arg2)
   at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
   at Microsoft.Scripting.Interpreter.DynamicInstruction`3.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.Interpreter.Run(InterpretedFrame frame)
   at Microsoft.Scripting.Interpreter.LightLambda.Run2[T0,T1,TRet](T0 arg0, T1 arg1)
   at IronPython.Compiler.PythonScriptCode.RunWorker(CodeContext ctx)
   at Microsoft.Scripting.Hosting.ScriptSource.Execute(ScriptScope scope)
   at Microsoft.Scripting.Hosting.ScriptSource.ExecuteAndWrap(ScriptScope scope, ObjectHandle& exception)"

 

If I manually deactivates the use project settings from the Revit UI the code works well, I would like to know if is possible to deactivate that option from the code, I thought the UseDefault property set to None would do this, but in this specific case it is not doing it, this is the code I am using:

 

ids = uidoc.Selection.GetElementIds()
for id in ids:
	sched = doc.GetElement(id)
	t = Transaction(doc, "Remove Unit Symbol")
	t.Start()
	
	#Get Schedule Definition
	sched_def = sched.Definition
	field_count = sched_def.GetFieldCount()
	f_index = range(field_count)
	
	#Itering over the schedule fields
	for i in f_index:
		field = sched_def.GetField(i)
		field_name = field.GetName()
		print (field_name)
		
		#try:
		# Get current FormatOptions from the field
		format_options = field.GetFormatOptions()
		unit_type_id = format_options.GetUnitTypeId()
		accuracy = format_options.Accuracy
		formatOpts = FormatOptions(unit_type_id)
		formatOpts.UseDefault = False
		formatOpts.Accuracy = accuracy
		formatOpts.RoundingMethod.Nearest
		field.SetFormatOptions(formatOpts)
		print("Succesfully unit symbol removed")

		#except:
			
			#pass
			#print("Error on unit setting")
		
	t.Commit()

 


What I am doing wrong in my code?, I have attached an image for reference.

Thanks in advance!, greetings from Mexico city.

0 Likes
1,988 Views
11 Replies
Replies (11)
Message 2 of 12

jeremy_tammik
Alumni
Alumni

I asked the development team for you.

  

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 3 of 12

ggranadosNFAMX
Contributor
Contributor

Hi Jeremy, Thanks so much!, I've clicked on the link in your answer but I can not access that site, please let me know if the development team provide some comments regarding this topic.

 

 

0 Likes
Message 4 of 12

TripleM-Dev.net
Advisor
Advisor

Hi @ggranadosNFAMX,

 

Could be a regeneration (of it's db) issue and you need a seperate transaction if the UseDefaults is changed?

 

First try if you can set the UseDefaults to false and don't call any edits after formatOpts.UseDefault = False

If it works then use a TransactionGroup to change all to UseDefault = False and then change the settings of the object.

 

Ps. The code can be optimized If you first check if UseDefault  = False, and buffer those that are true.

 

- Michel

0 Likes
Message 5 of 12

jeremy_tammik
Alumni
Alumni

Yes, the link is internal, for my personal use, for cross-referencing.

   

The development team answers:  Looks like the exception comes from an accessor on the default options.  If you build the options with UseDefault = false and set it to the field, it should actually override successfully.

Jeremy Tammik Developer Advocacy and Support + The Building Coder + Autodesk Developer Network + ADN Open
0 Likes
Message 6 of 12

ggranadosNFAMX
Contributor
Contributor

Hi @TripleM-Dev.net  and @jeremy_tammik , thanks for your answers, I have tried to build the options with UseDefault = False, it seems to be working for the Length Field, but when it tries to change the velocity parameter it seems to fail when getting its unit type from the current format options, I have modified in the Revit UI the schedule to delete all fields except the Velocity one, and I see that the GetUnitTypeId method is retrieving a "meters" unit, so the exception " The display unit in formatOptions is not a valid display unit for the unit type of this ScheduleField" is happening.

ggranadosNFAMX_0-1717081775376.png


This is my current code:

 

ids = uidoc.Selection.GetElementIds()
for id in ids:
	sched = doc.GetElement(id)
	#Get Schedule Definition
	sched_def = sched.Definition
	field_count = sched_def.GetFieldCount()
	f_index = range(field_count)
	
	#Itering over the schedule fields
	for i in f_index:
		# Get shedule fields
		field = sched_def.GetField(i)
		# Get field name
		field_name = field.GetName()
		print (field_name)
		# Get current format options
		format_options = field.GetFormatOptions()
		# Changing UseDefault property to False
		format_options.UseDefault = False
		# Get field unit type
		unit_type = format_options.GetUnitTypeId().TypeId
		# Printing unit types for checking purpose
		print (unit_type)
		t = Transaction(doc, "Remove Unit Symbol")
		t.Start()
		# Setting the UseDefault to False
		field.SetFormatOptions(format_options)
		t.Commit()
		# Printing UseDefault property to check 
		print (format_options.UseDefault)

 

 

it seems that when I change the UseDefault to false it automatically assign meters as the unit type?, honestly I am not sure how to use transaction groups, I'll take a look on that, maybe there is the key to get it working, Thank you for your time guys!.

0 Likes
Message 7 of 12

TripleM-Dev.net
Advisor
Advisor

See Transactiongroups.Assimilate Method for a sample how to use.

0 Likes
Message 8 of 12

ggranadosNFAMX
Contributor
Contributor

Hi!, just an update on this, I still failing getting the GetUnitTypeId when the project default units are checked in the UI, it turned out that when I set the UseDefault property to False all the schedule fields they return meters automatically, so a workaround to solve this that worked for me by now, is to create a Dictionary with field names or headers as Key, and unit type ids and accuracy as Values, this way after set the UseDefault property to False, it can find the UnitTypeId directly in the Dictionary.

I think I could create a Dictionary including all the parameters I commonly use in the projects to be able to remove/set unit symbols in selected schedules.

 

 

This is the code that worked for me in this example:

var = {
	    "Flow" : [UnitTypeId.CubicFeetPerMinute,1],
	    "Area" : [UnitTypeId.SquareFeet, 0.01],
	    "Velocity" : [UnitTypeId.MetersPerSecond, 0.1],
	    "Length" : [UnitTypeId.Meters, 0.1],
	    "Friction" : [UnitTypeId.PascalsPerMeter, 0.1],
	    "Pressure Drop" : [UnitTypeId.Pascals, 0.01],
	    
					}

ids = uidoc.Selection.GetElementIds()
for id in ids:
	sched = doc.GetElement(id)
	t = Transaction(doc, "Remove Unit Sym")
	t.Start()
	
	#Get Schedule Definition
	sched_def = sched.Definition
	field_count = sched_def.GetFieldCount()
	f_index = range(field_count)
	
	#Itering over the schedule fields
	for i in f_index:
		field = sched_def.GetField(i)
		field_name = field.GetName()
		field_chead = field.ColumnHeading
		
		print (field_chead)
		
		#Removing unit symbol
		for key in var:
			unit = var[key][0]
			accur = var[key][1]
			#Removing unit symbold from fields
			if field_chead == key:
			
				try:
    
					formatOpts = FormatOptions(unit)
					formatOpts.UseDefault = False
					formatOpts.Accuracy = accur
					formatOpts.RoundingMethod.Nearest
					field.SetFormatOptions(formatOpts)
					print(key + " Succesfully unit symbol removed")
     
				except:
					
					pass
					print(key + "Error on unit setting")
		
	t.Commit()

Thanks!

Message 9 of 12

Moustafa_K
Advisor
Advisor

I think the issue here you are setting a new reference to the format options. you need to get the formatoption from the feild it self, change usedefault = false, then set it back to the field.

this example works for me. it is in C# but i trust you can understand how it works

 

Trans.Start();
var schedule = UiDoc.ActiveGraphicalView as ViewSchedule;
for (int i = 0; i < schedule.Definition.GetFieldCount(); i++)
{
    var field = schedule.Definition.GetField(i);
    if(field.GetName()=="Height")
    {
        var form = field.GetFormatOptions();
        form.UseDefault = false;
        field.SetFormatOptions(form);
        break;
    }

}
Trans.Commit();

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes
Message 10 of 12

ggranadosNFAMX
Contributor
Contributor

Hi @TripleM-Dev.net, Thanks for your answer, I tried to apply the solution using python, I think my code is doing the same as yours, But it is dealing with the same problem, for some reason for Set the format options back to the field, it is asking me for specify the UnitTypeId, and it throws the " The display unit in formatOptions is not a valid display unit for the unit type of this ScheduleField".

t = Transaction(doc, "Deactivate project default units")
t.Start()

ids = uidoc.Selection.GetElementIds()
for id in ids:
	sched = doc.GetElement(id)
	#Get Schedule Definition
	sched_def = sched.Definition
	field_count = sched_def.GetFieldCount()
	f_index = range(field_count)
	
	#Itering over the schedule fields
	for i in f_index:
		field = sched_def.GetField(i)
		field_name = field.GetName()
		print(field_name)
		if field_name == "Pressure Drop":
			format_options = field.GetFormatOptions()
			format_options.UseDefault = False
			field.SetFormatOptions(format_options)
		
t.Commit()

ggranadosNFAMX_0-1717606708775.png

 

 

Do you see something that may be causing that in my python code?, Thanks again for your time!.

0 Likes
Message 11 of 12

Moustafa_K
Advisor
Advisor

yep seems, when you set it to false, it doesn't pick one of the possible unit. you need to set the unit your self.

try using this line after setting to false

 

form.SetUnitTypeId(UnitTypeId.FeetOfWater39_2DegreesFahrenheit);

 

for the sake of more clarification

try on the UI and check the unit you need and apply it to the code

Moustafa_K_0-1717607848910.png

 

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes
Message 12 of 12

ggranadosNFAMX
Contributor
Contributor

Thanks, @Moustafa_K. Specifying the unit as you suggested will work. In message 6, I mentioned that I am specifying the unit using dictionary keys and values. What I am trying to do is to get the current unit from the existing FormatOptions and use it to set new FormatOptions with the symbol units disabled.

The issue arises when I set the UseDefault property to False. This causes the GetUnitTypeId() method to automatically assign the meters unit to the FormatOptions. Consequently, the process stops because meters are not the appropriate unit for the fields in my selected schedule.

Therefore, I think using a dictionary or a CSV file with the units data is the solution for now.

Thanks again for your time!

0 Likes