Selecting an option in Warning dialog

Hello guys,

I would like to select an option when you have a failure in a transaction.

For example:

grafik

I would like to select that but it does not apply that option.

Here is the code:

import clr
from System.Collections.Generic import *
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
rooms = UnwrapElement(IN[0])
vecs = UnwrapElement(IN[1])
lvl = UnwrapElement(IN[2])
phase = UnwrapElement(IN[3])
roomseps = UnwrapElement(IN[4])
area = UnwrapElement(IN[5])
moveRoomBoundaries = IN[6]
sepids = []

class RoomWarningSwallower(IFailuresPreprocessor):
    def PreprocessFailures(self, failuresAccessor):
        fail_list = List[FailureMessageAccessor]()
        fail_acc_list = failuresAccessor.GetFailureMessages().GetEnumerator()
        for failure in fail_acc_list:
            failure_id = failure.GetFailureDefinitionId()
            failure_severity = failure.GetSeverity()
            failure_type = BuiltInFailures.RoomFailures.RoomHeightNegative
            if failure_id == failure_type:
                print("{0} with id: {1} of type: RoomNotEnclosed removed!".format(failure_severity, failure_id.Guid))
                failuresAccessor.ResolveFailure(failure)
        return FailureProcessingResult.Continue

z= []
for sep in roomseps:
	sepids.append(sep.Id)
sepidlist = List[ElementId](sepids)

plancircuits = doc.PlanTopology[lvl, phase].Circuits
elementlist = []
for item in plancircuits:
	if item.SideNum == len(roomseps) and XYZ(0,0,item.Area).IsAlmostEqualTo(XYZ(0,0,area)):
		elementlist.append(item)
plancircuit = elementlist[0]

i = 0
t = Transaction(doc)
t.Start("Place Room")
for room in rooms:
	if moveRoomBoundaries: ElementTransformUtils.MoveElements(doc, sepidlist, vecs[i].ToXyz())
	doc.Create.NewRoom(room, plancircuit)
	i += 1
	options = t.GetFailureHandlingOptions()
	options.SetFailuresPreprocessor(RoomWarningSwallower())
	t.SetFailureHandlingOptions(options)
	
	
for sepid in sepids:
	doc.Delete(sepid)
t.Commit()

OUT = rooms

I think @SeanP is the right address to visit in that case :slight_smile:

1 Like

In that version it skips the failure message but does not apply the first option.

import clr
from System.Collections.Generic import *
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
rooms = UnwrapElement(IN[0])
vecs = UnwrapElement(IN[1])
lvl = UnwrapElement(IN[2])
phase = UnwrapElement(IN[3])
roomseps = UnwrapElement(IN[4])
area = UnwrapElement(IN[5])
moveRoomBoundaries = IN[6]
sepids = []

class RoomWarningSwallower(IFailuresPreprocessor):
    def PreprocessFailures(self, failuresAccessor):
        fail_list = List[FailureMessageAccessor]()
        fail_acc_list = failuresAccessor.GetFailureMessages().GetEnumerator()
        for failure in fail_acc_list:
            failure_id = failure.GetFailureDefinitionId()
            failure_severity = failure.GetSeverity()
            failure_type = BuiltInFailures.RoomFailures.RoomHeightNegative
            if failure_id == failure_type:
                failuresAccessor.ResolveFailure(failure)
        	return FailureProcessingResult.ProceedWithCommit

z= []
for sep in roomseps:
	sepids.append(sep.Id)
sepidlist = List[ElementId](sepids)

plancircuits = doc.PlanTopology[lvl, phase].Circuits
elementlist = []
for item in plancircuits:
	if item.SideNum == len(roomseps) and XYZ(0,0,item.Area).IsAlmostEqualTo(XYZ(0,0,area)):
		elementlist.append(item)
plancircuit = elementlist[0]

i = 0
t = Transaction(doc)
t.Start("Place Room")
for room in rooms:
	if moveRoomBoundaries: ElementTransformUtils.MoveElements(doc, sepidlist, vecs[i].ToXyz())
	doc.Create.NewRoom(room, plancircuit)
	i += 1
	options = t.GetFailureHandlingOptions()
	options.SetFailuresPreprocessor(RoomWarningSwallower())
	t.SetFailureHandlingOptions(options)
	
	
for sepid in sepids:
	doc.Delete(sepid)
t.Commit()

OUT = rooms

I would have to take a bit more time to review your process failure, but the easy solution here is to set the room offset height before comitting. I have had to do this before as well.

1 Like

I know this is in C#, but I think you need to delete the warning to keep it from being presented.

foreach (FailureMessageAccessor failure in failures)
            {
                if (failure.GetSeverity() == FailureSeverity.Warning)
                {
                    if (failure.GetFailureDefinitionId() == BuiltInFailures.RoomFailures.RoomUnplaceWarning || failure.GetFailureDefinitionId() == BuiltInFailures.RoomFailures.RoomHeightNegative)
                    {
                        failuresAccessor.DeleteWarning(failure);
                    }
                }
                else
1 Like

Thank you very much for reply Sean!

When you delete a warning, will the default resolution be committed? When I delete the warning and then use

FailureProcessingResult.ProceedWithCommit or FailureProcessingResult.Continue

it shows the warning…

hello @Deniz_Maral
try to set the handler just after start transaction

t = Transaction(doc)
t.Start("Place Room")
options = t.GetFailureHandlingOptions()
options.SetFailuresPreprocessor(RoomWarningSwallower())
t.SetFailureHandlingOptions(options)
for room in rooms:
	if moveRoomBoundaries: ElementTransformUtils.MoveElements(doc, sepidlist, vecs[i].ToXyz())
	doc.Create.NewRoom(room, plancircuit)
	i += 1

for sepid in sepids:
	doc.Delete(sepid)
t.Commit()

and set the return FailureProcessingResult.ProceedWithCommit after the complete loop

class RoomWarningSwallower(IFailuresPreprocessor):
	def PreprocessFailures(self, failuresAccessor):
		fail_list = List[FailureMessageAccessor]()
		fail_acc_list = failuresAccessor.GetFailureMessages().GetEnumerator()
		for failure in fail_acc_list:
			failure_id = failure.GetFailureDefinitionId()
			failure_severity = failure.GetSeverity()
			failure_type = BuiltInFailures.RoomFailures.RoomHeightNegative
			if failure_id == failure_type:
				failuresAccessor.ResolveFailure(failure)
		return FailureProcessingResult.ProceedWithCommit
2 Likes

Hello @c.poupin,

it does not change the situation. It does not show the window but it does not place the room. When I do it over UI, it places the room. The default solution is “Grenzen anpassen” but it does not apply that.


Test_FailureAPI.dyn (64.5 KB)
Create a room and then delete it. And try to place it on a view, so as to get negative height.

try to fix your indentation levels :wink:


possible to send rvt ?

Modellierung_UnplatzierteRaeumePlatzieren.rvt (1.2 MB)

Thank you Cyril! Here is .rvt :slight_smile:

try this

import clr
from System.Collections.Generic import *
clr.AddReference('RevitAPI')
from Autodesk.Revit.DB import *

clr.AddReference("RevitNodes")
import Revit
clr.ImportExtensions(Revit.GeometryConversion)

clr.AddReference("RevitServices")
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager

doc = DocumentManager.Instance.CurrentDBDocument
rooms = UnwrapElement(IN[0])
vecs = UnwrapElement(IN[1])
lvl = UnwrapElement(IN[2])
phase = UnwrapElement(IN[3])
roomseps = UnwrapElement(IN[4])
area = UnwrapElement(IN[5])
moveRoomBoundaries = IN[6]
sepids = []
z = []
class RoomWarningSwallower(IFailuresPreprocessor):
	def PreprocessFailures(self, failuresAccessor):
		fail_acc_list = failuresAccessor.GetFailureMessages()
		z.append(failuresAccessor.GetSeverity())
		if failuresAccessor.GetSeverity() == FailureSeverity.Error:
			for failure in fail_acc_list:
				failuredefId = failure.GetFailureDefinitionId()
				if failuredefId == BuiltInFailures.RoomFailures.RoomHeightNegative or failuredefId == BuiltInFailures.RoomFailures.RoomUnplaceWarning :
					failuresAccessor.ResolveFailure(failure)			
			return FailureProcessingResult.ProceedWithCommit

		elif failuresAccessor.GetSeverity() == FailureSeverity.Warning:
			for failure in fail_acc_list:
				failuresAccessor.DeleteWarning(failure)
		else:
			pass
						
		return FailureProcessingResult.Continue

z= []
outnewRoom = []
for sep in roomseps:
	sepids.append(sep.Id)
sepidlist = List[ElementId](sepids)

plancircuits = doc.PlanTopology[lvl, phase].Circuits
elementlist = []
for item in plancircuits:
	if item.SideNum == len(roomseps) and XYZ(0,0,item.Area).IsAlmostEqualTo(XYZ(0,0,area)):
		elementlist.append(item)
plancircuit = elementlist[0]

i = 0
TransactionManager.Instance.ForceCloseTransaction()
t = Transaction(doc)
t.Start("Place Room")
options = t.GetFailureHandlingOptions()
options.SetFailuresPreprocessor(RoomWarningSwallower())
t.SetFailureHandlingOptions(options)	
for room in rooms:
	if moveRoomBoundaries:	
		ElementTransformUtils.MoveElements(doc, sepidlist, vecs[i].ToXyz())
		
		newRoom = doc.Create.NewRoom(room, plancircuit)
		outnewRoom.append(newRoom)
		i += 1

		doc.Regenerate()

for sepid in sepids:
	doc.Delete(sepid)

t.Commit()

OUT = rooms, z, outnewRoom

Did it work on your side? I does not place the room :frowning:

Here my result

testFailure

1 Like

Which Revit-Version do you use? I use 2020.2.
It is very strange because it does not create even model curves now.

Same version

Remove this?

for sepid in sepids:
	doc.Delete(sepid)
1 Like


It created the model curves but not room :S

If I am not mistaken, the FailureProcessingResult.ProceedWithCommit is only when a “Error” level Severity has been resolved, but .Continue is to be used when the warning has been deleted. If you reference the link I previously sent, you’ll see how they are separated.

  public class UnplacedRoomWarning : IFailuresPreprocessor
    {
        public FailureProcessingResult PreprocessFailures(FailuresAccessor failuresAccessor)
        {
            IList<FailureMessageAccessor> failures = new List<FailureMessageAccessor>();
            failures = failuresAccessor.GetFailureMessages();

            foreach (FailureMessageAccessor failure in failures)
            {
                if (failure.GetSeverity() == FailureSeverity.Warning)
                {
                    if (failure.GetFailureDefinitionId() == BuiltInFailures.RoomFailures.RoomUnplaceWarning || failure.GetFailureDefinitionId() == BuiltInFailures.RoomFailures.RoomHeightNegative)
                    {
                        failuresAccessor.DeleteWarning(failure);
                    }
                }
                else
                {
                    failuresAccessor.ResolveFailure(failure);
                    return FailureProcessingResult.ProceedWithCommit;
                }
            }
            return FailureProcessingResult.Continue;
        }
    }
1 Like

Also, I don’t think you return the FailureProcessingResult, but rather set it on the accessor itself.

https://www.revitapidocs.com/2016/8c50ec1e-1709-1d01-994a-079a05ed6fcb.htm

Thanks Sean for you efforts! The code from @c.poupin does same thing as you described. What weird is, that it works for him but not for me… I tried it also in Revit 2021 and no success.

Here is my definition file if you can test
TestCyrilP_FailureAPI.dyn (64.8 KB)

3 Likes