Hi! I am trying to swap all instances of family symbols in a project with a different family and its symbol which is selected from a UI by the user. The code seems to execute with no exceptions but no changes are taking place to the model even after committing the transaction. I'm not sure if this is possible, but it seems like a typical use case so I'm sure its something simple in my code. Appreciate any assistance anyone can provide!!
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = commandData.Application.ActiveUIDocument.Document; FormPopulatePlbgFixtures form = new FormPopulatePlbgFixtures(doc); var result = form.ShowDialog(); if (result == DialogResult.OK) { var trans = new Transaction(doc, "Family Swap"); trans.Start(); try { //Loop through each Swap Family for (var i = 0; i < form.SwapReturnValues.Count; i++) { var selectedFamily = new FilteredElementCollector(doc) .OfClass(typeof(Family)) .Cast<Family>() // family .FirstOrDefault(x => x.Name.Equals(form.SwapReturnValues[i].swapFamilyName)); //var famElem = doc.GetElement(selectedFamily.Id); FamilySymbol selectedFamSymbol = null; //Get all family symbols var familySymbolIds = selectedFamily.GetFamilySymbolIds(); //Match the selected swap family symbol foreach (var id in familySymbolIds) { var familySymbol = selectedFamily.Document.GetElement(id) as FamilySymbol; // Get family symbol name if (familySymbol.Name == form.SwapReturnValues[i].swapFamilyType) selectedFamSymbol = familySymbol; break; } //Loop through each arch family instance foreach (var f in form.SwapReturnList) { var fam = f.FamilySymbol.Family; var fi = f.FamilyInstance; var fs = f.FamilySymbol; //set family and symbol var famTypeId = doc.GetDefaultFamilyTypeId(selectedFamSymbol.GetTypeId()); var typename = fs.GetType().FullName; var subtrans = new SubTransaction(doc); subtrans.Start(); fs = selectedFamSymbol; subtrans.Commit(); } } doc.Regenerate(); trans.Commit(); return Result.Succeeded; } catch (Exception e) { trans.RollBack(); return Result.Failed; } } return Result.Cancelled; }
Hi! I am trying to swap all instances of family symbols in a project with a different family and its symbol which is selected from a UI by the user. The code seems to execute with no exceptions but no changes are taking place to the model even after committing the transaction. I'm not sure if this is possible, but it seems like a typical use case so I'm sure its something simple in my code. Appreciate any assistance anyone can provide!!
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = commandData.Application.ActiveUIDocument.Document; FormPopulatePlbgFixtures form = new FormPopulatePlbgFixtures(doc); var result = form.ShowDialog(); if (result == DialogResult.OK) { var trans = new Transaction(doc, "Family Swap"); trans.Start(); try { //Loop through each Swap Family for (var i = 0; i < form.SwapReturnValues.Count; i++) { var selectedFamily = new FilteredElementCollector(doc) .OfClass(typeof(Family)) .Cast<Family>() // family .FirstOrDefault(x => x.Name.Equals(form.SwapReturnValues[i].swapFamilyName)); //var famElem = doc.GetElement(selectedFamily.Id); FamilySymbol selectedFamSymbol = null; //Get all family symbols var familySymbolIds = selectedFamily.GetFamilySymbolIds(); //Match the selected swap family symbol foreach (var id in familySymbolIds) { var familySymbol = selectedFamily.Document.GetElement(id) as FamilySymbol; // Get family symbol name if (familySymbol.Name == form.SwapReturnValues[i].swapFamilyType) selectedFamSymbol = familySymbol; break; } //Loop through each arch family instance foreach (var f in form.SwapReturnList) { var fam = f.FamilySymbol.Family; var fi = f.FamilyInstance; var fs = f.FamilySymbol; //set family and symbol var famTypeId = doc.GetDefaultFamilyTypeId(selectedFamSymbol.GetTypeId()); var typename = fs.GetType().FullName; var subtrans = new SubTransaction(doc); subtrans.Start(); fs = selectedFamSymbol; subtrans.Commit(); } } doc.Regenerate(); trans.Commit(); return Result.Succeeded; } catch (Exception e) { trans.RollBack(); return Result.Failed; } } return Result.Cancelled; }
Hi @sgermanoZ2Y2F ,
1)choose the element type
2)get the element type id
3)choose the element to which you want to change the type
4) using ChangeTypeId ,change the element type.
ElementId typeid;//get the element typeid Element e;//choose the element e.ChangeTypeId(typeid);//change the typeid
Hi @sgermanoZ2Y2F ,
1)choose the element type
2)get the element type id
3)choose the element to which you want to change the type
4) using ChangeTypeId ,change the element type.
ElementId typeid;//get the element typeid Element e;//choose the element e.ChangeTypeId(typeid);//change the typeid
I'm not sure you are going to be able to do what you want to do without some extra work.
I think Jeremy's usual quote probably applies here: If you can't do it with the Revit User Interface, you probably can't do it with the API.
So for example, the Revit user interface will allow us to change one electrical device family to another electrical device family. However, it will not allow me to change an electrical device to another type of family, like a light switch family, for example.
So it seems the Revit API is the same way: I can use the code below to change one electrical device family to another device family, but I cannot change the family types with the code below - I get an error message.
(Changing one device family to another seems kind of trivial, since we can also do this with the user interface by picking one element, choosing "Select All Instances", or "Select All Instances in Current View", and just using the family properties window to select another family.)
// to keep things simple, this code just takes all the selected elements and changes them to the same ID as
//the first selected element. It assumes that at least 2 elements are selected before running this code.
// Get the element selection of current document Selection selection = uidoc.Selection; //store element id's ICollection<ElementId> selectedIds = uidoc.Selection.GetElementIds(); ElementId id1 = selectedIds.First(); Element e1 = doc.GetElement(id1); ElementId myid1 = e1.GetTypeId(); TaskDialog.Show("The Type ID to Change Everthing to is;", myid1.ToString ()); foreach (ElementId id in selectedIds) { Element e = doc.GetElement(id); Transaction trans = new Transaction(doc, "Change Element" ); trans.Start(); e.ChangeTypeId (myid1); trans.Commit (); }// end foreach
However, I haven't tried this with the API, but it seems like we can work around the limitation in the following way:
1. Select an element to change.
2. Edit the family and save as a new temporary family name (so we don't mess up the existing family).
3. Change all the elements to the new temporary family.
4. Edit the temp. family again, and change the family type to the new type. (For example, change from electrical devices to lighting devices.)
5. Load the new changed family into the project, overwriting all the existing element parameters.
6. Now we have all the elements of the right type, so we can use ChangeTypeId to change all the elements to the desired family type or symbol.
7. Clean up the file by deleting the temporary family we made.
I'm going to try this when I have time. Hopefully, all the required steps are available via the API.
I'm not sure you are going to be able to do what you want to do without some extra work.
I think Jeremy's usual quote probably applies here: If you can't do it with the Revit User Interface, you probably can't do it with the API.
So for example, the Revit user interface will allow us to change one electrical device family to another electrical device family. However, it will not allow me to change an electrical device to another type of family, like a light switch family, for example.
So it seems the Revit API is the same way: I can use the code below to change one electrical device family to another device family, but I cannot change the family types with the code below - I get an error message.
(Changing one device family to another seems kind of trivial, since we can also do this with the user interface by picking one element, choosing "Select All Instances", or "Select All Instances in Current View", and just using the family properties window to select another family.)
// to keep things simple, this code just takes all the selected elements and changes them to the same ID as
//the first selected element. It assumes that at least 2 elements are selected before running this code.
// Get the element selection of current document Selection selection = uidoc.Selection; //store element id's ICollection<ElementId> selectedIds = uidoc.Selection.GetElementIds(); ElementId id1 = selectedIds.First(); Element e1 = doc.GetElement(id1); ElementId myid1 = e1.GetTypeId(); TaskDialog.Show("The Type ID to Change Everthing to is;", myid1.ToString ()); foreach (ElementId id in selectedIds) { Element e = doc.GetElement(id); Transaction trans = new Transaction(doc, "Change Element" ); trans.Start(); e.ChangeTypeId (myid1); trans.Commit (); }// end foreach
However, I haven't tried this with the API, but it seems like we can work around the limitation in the following way:
1. Select an element to change.
2. Edit the family and save as a new temporary family name (so we don't mess up the existing family).
3. Change all the elements to the new temporary family.
4. Edit the temp. family again, and change the family type to the new type. (For example, change from electrical devices to lighting devices.)
5. Load the new changed family into the project, overwriting all the existing element parameters.
6. Now we have all the elements of the right type, so we can use ChangeTypeId to change all the elements to the desired family type or symbol.
7. Clean up the file by deleting the temporary family we made.
I'm going to try this when I have time. Hopefully, all the required steps are available via the API.
Thanks for the replies folks, I am going to switch to changing the element id and set the types. For those families with different categories I may try that temporary family solution you mentioned Steve, thanks for the tip. I will post back once Ive updated and tested my code. Appreciate it y'all, you guys rock!
Thanks for the replies folks, I am going to switch to changing the element id and set the types. For those families with different categories I may try that temporary family solution you mentioned Steve, thanks for the tip. I will post back once Ive updated and tested my code. Appreciate it y'all, you guys rock!
Can't find what you're looking for? Ask the community or share your knowledge.