Hello guys,
I would like to select an option when you have a failure in a transaction.
For example:
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
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
SeanP
July 14, 2021, 3:24am
4
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
SeanP
July 14, 2021, 4:18am
5
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
c.poupin:
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()
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
possible to send rvt ?
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
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
SeanP
July 14, 2021, 11:31am
17
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
SeanP
July 14, 2021, 11:41am
18
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