Announcements
Due to scheduled maintenance, the Autodesk Community will be inaccessible from 10:00PM PDT on Oct 16th for approximately 1 hour. We appreciate your patience during this time.
Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Deactivate default unit project settings

11 REPLIES 11
Reply
Message 1 of 12
ggranadosNFAMX
692 Views, 11 Replies

Deactivate default unit project settings

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.

11 REPLIES 11
Message 2 of 12

I asked the development team for you.

  

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

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.

 

 

Message 4 of 12

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

Message 5 of 12

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
Message 6 of 12

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!.

Message 7 of 12

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

Message 8 of 12

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
in reply to: ggranadosNFAMX

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
Message 10 of 12
ggranadosNFAMX
in reply to: Moustafa_K

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!.

Message 11 of 12
Moustafa_K
in reply to: ggranadosNFAMX

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
Message 12 of 12
ggranadosNFAMX
in reply to: Moustafa_K

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!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Rail Community


Autodesk Design & Make Report