Set different value to a set of elements

Set different value to a set of elements

Anonymous
Not applicable
697 Views
6 Replies
Message 1 of 7

Set different value to a set of elements

Anonymous
Not applicable

Hi everyone,

 

So I am trying to filter all the beams in my project and set values to the Parameter Mark. I would like to mark it in a sequence, say from 3 to 10. Here are what I have done so far:

 

from Autodesk.Revit.DB import *

doc = __revit__.ActiveUIDocument.Document

bc = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFraming).WhereElementIsNotElementType().ToElements()

t = Transaction(doc, 'Mark changing')

t.Start()

for bm in bc:
	mark = bm.LookupParameter("Mark")
	if mark:
		for i in range(3,10):
			newMark = mark.Set(str(i))

t.Commit()

I have 7 beams and if this code works, it should give them the Mark value of 3, 4, 5, 6, 7, 8, 9, respectively. However, my code only give all beams one value of 9. I would appreciate any help.

 

Cheers

Thai

0 Likes
Accepted solutions (3)
698 Views
6 Replies
Replies (6)
Message 2 of 7

naveen.kumar.t
Autodesk Support
Autodesk Support
Accepted solution

Try this code

 Dim i As Integer = 3
            Dim collector As FilteredElementCollector = New FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFraming).WhereElementIsNotElementType()
            Dim eids As IList(Of ElementId) = TryCast(collector.ToElementIds(), IList(Of ElementId))
            TaskDialog.Show("BEams count", eids.Count.ToString())
            For Each eid As ElementId In eids
                Dim e As Element = doc.GetElement(eid)
                Dim P As Parameter = e.LookupParameter("Mark")
                If P IsNot Nothing Then
                    P.[Set](i.ToString())
                    If Not P.HasValue Then
                        P.SetValueString(i.ToString())
                    End If

                    i = i + 1
                End If
            Next

            doc.Regenerate()

Naveen Kumar T
Developer Technical Services
Autodesk Developer Network

0 Likes
Message 3 of 7

jeremy_tammik
Alumni
Alumni
Accepted solution

Many thanks to Naveen for answering!

 

In the original code, you loop from 3 to 9 for each of the beams, set each of those values to the parameter in each of the beams, and end up at the value 9 on each one of them. That explains the behaviour you describe.

 

You can solve it by not looping over all the numbers in an inner loop, but just incrementing the mark number after setting each element's parameter in turn.

  

Some comments and suggestions to both of you:

 

 

Here is my suggestion how to solve this, iterating directly over the collector with no casts at all:

  

    void NumberStructuralFraming( Document doc )
    {
      FilteredElementCollector beams
        = new FilteredElementCollector( doc )
          .OfCategory( BuiltInCategory.OST_StructuralFraming )
          .WhereElementIsNotElementType();

      using( Transaction t = new Transaction( doc ) )
      {
        t.Start( "Renumber marks" );

        int mark_number = 3;

        foreach( FamilyInstance beam in beams )
        {
          Parameter p = beam.get_Parameter(
            BuiltInParameter.ALL_MODEL_MARK );

          p.Set( (mark_number++).ToString() );
        }
        t.Commit();
      }
    }

 

I hope this helps.

 

Cheers,

 

Jeremy

 

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

jeremy_tammik
Alumni
Alumni
Accepted solution

By the way, I once implemented a more full-fledged element numbering system for structural concrete setout points:

 

http://thebuildingcoder.typepad.com/blog/2012/08/structural-concrete-setout-point-add-in.html

 

https://github.com/jeremytammik/SetoutPoints

 

Cheers,

 

Jeremy

 

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

Anonymous
Not applicable

Thank you all for suggesting and commenting. I have combined your ideas and have come up with a simple solution as following:

from Autodesk.Revit.DB import *

doc = __revit__.ActiveUIDocument.Document

bc = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_StructuralFraming).WhereElementIsNotElementType()
	
t = Transaction(doc, 'Mark changing')

t.Start()
i = 1
for bm in bc:
	mark = bm.LookupParameter("Mark")
	newMark = mark.Set(str(i))
	i = i+1

t.Commit()

However, I still do not get Jeremy's suggestion: 

  • "LookupParameter is not optimal; when possible, use a built-in parameter enum instead of the display name."

 

0 Likes
Message 6 of 7

jeremy_tammik
Alumni
Alumni

Well done!

 

Looking good.

 

Still room for improvement:

 

A transaction should be enclosed in a `using` statement: 

 

http://thebuildingcoder.typepad.com/blog/2012/04/using-using-automagically-disposes-and-rolls-back.h...

 

LookupParameter takes a language dependent display string.

 

This has several disadvantages:

 

  • Several parameters can have the same display string. How do you guarantee you got the right one?
  • Display strings are language dependent. How are you going to go international?
  • String comparisons are more expensive than integer or enum value comparisons. Are you interested in speed? Perfection?

 

Cheers,

 

Jeremy

 

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

Anonymous
Not applicable

Thank you for your suggestions Jeremy. I will dig deeper about this matter.

 

Regards,

Thai

0 Likes