Replicate Graphical Column Schedule Sort Order with C#

simon.lewisPC7GZ
Explorer
Explorer

Replicate Graphical Column Schedule Sort Order with C#

simon.lewisPC7GZ
Explorer
Explorer

Hi,

 

I am trying to write an add-in with C# to automate the process of sequentially labeling structural columns to match the sequence in the graphical column schedule.

 

I have written the following code to get all the concrete columns in the project and then create a list of their Column Location Marks (ie A(2000)-1(2150) )  (Built-in Category):

 

ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_StructuralColumns);
StructuralMaterialTypeFilter filter_mat = new StructuralMaterialTypeFilter(StructuralMaterialType.Concrete);

IList<Element> columns = collector.WherePasses(filter).WherePasses(filter_mat).WhereElementIsNotElementType().ToElements();

List<XYZ> locations = new List<XYZ>();
List<string> colmarks = new List<string>();

foreach (Element ele in columns)
{
string colmark = ele.get_Parameter(BuiltInParameter.COLUMN_LOCATION_MARK).AsString();
colmarks.Add(colmark);
}

colmarks.Sort();

 

My trouble comes at this point. The colmarks.Sort() method does not match the order of the columns in the graphical column schedule.

 

I have also tried sorting the columns by their XYZ location which doesn't match the order in the graphical column schedule either.

 

Can anyone provide any insight into how the graphical column schedule orders the columns and how I can replicate this.

 

Thanks

 

0 Likes
Reply
Accepted solutions (1)
2,061 Views
7 Replies
Replies (7)

Moustafa_K
Collaborator
Collaborator

can you snapshot the schedule and the results that doesn't match...

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes

simon.lewisPC7GZ
Explorer
Explorer

See attached screenshots.

 

I've tried a few different ways which involve creating a list of the parameter as strings and then sorting or using orderby as below:

 

List<Element> sortedElements = columns.OrderBy(x => x.get_Parameter(BuiltInParameter.COLUMN_LOCATION_MARK).AsString()).ToList();

0 Likes

simon.lewisPC7GZ
Explorer
Explorer

I have the same issue in dynamo too, the order seems to match my code but not the graphical column schedule... (screenshot attached).

0 Likes

Moustafa_K
Collaborator
Collaborator

@simon.lewisPC7GZ 

sorry to say, It is a well known limitation to this feature see this link

https://forums.autodesk.com/t5/revit-ideas/graphical-column-schedule-in-revit-sort-by-specified-para...

I was able to reproduce the same as well.

 

Moustafa Khalil
Cropped-Sharp-Bim-500x125-Autodesk-1
0 Likes

simon.lewisPC7GZ
Explorer
Explorer

Thanks mostafa,

 

I did see this thread but I was hoping someone might be able to shed some light on the logic Revit uses to sort the columns in the graphical column schedule so that I could replicate it with my own code in c#.

 

 

0 Likes

FAIR59
Advisor
Advisor
Accepted solution

LocationMark syntax :

A(xxxx)-1(yyyy)

sort order:

  • gridsequence A: alphabetic ascending
  • gridsequence 1: alphabetic ascending
  • xxxx value, first the positive values from smallest to largest, then negative values from smallest to largest
  • yyyy value, first the positive values from smallest to largest, then negative values from smallest to largest
List<FamilyInstance> colums = new FilteredElementCollector(doc)
				.WhereElementIsNotElementType()
				.OfCategory(BuiltInCategory.OST_StructuralColumns)
				.OfClass(typeof(FamilyInstance))
				.Cast<FamilyInstance>()
				.ToList();
colums.Sort(new ColumnMarkComparer());

helper classes:

public static class Extensions
{
	public static string GetColumnLocationMark(this FamilyInstance f)
	{
		Parameter p = f.get_Parameter(BuiltInParameter.COLUMN_LOCATION_MARK);
		if (p==null) return string.Empty;
		return p.AsString();
	}
}
public class ColumnMarkComparer: IComparer<FamilyInstance>
{
	int IComparer<FamilyInstance>.Compare(FamilyInstance x, FamilyInstance y)
	{
		if( x ==null)
		{
			return y==null? 0 : -1 ;
		}
		if (y ==null ) return 1;
		string[] mark1 = x.GetColumnLocationMark().Split('(' ,')');
		string[] mark2 = y.GetColumnLocationMark().Split('(',')');
		if (mark1.Length<4)
		{
			return mark2.Length<4? 0 : -1;
		}
		if(mark2.Length<4) return 1;
		//gridsequence A
		int res = string.Compare(mark1[0],mark2[0]);
		if( res!=0) return res ;

		//gridsequence 1
		string m12 = mark1[2].Remove(0,1);
		string m22 = mark2[2].Remove(0,1);
		res = string.Compare(m12,m22);
		if(res!=0) return res ;

		// value xxxx
		double d1 = 0;
		double d2=0;
		double.TryParse(mark1[1],out d1);
		double.TryParse(mark2[1], out d2);
		if (Math.Round(d1-d2,4)!=0)
		{
			if ( d1<0 ^ d2<0)
			{
				return d1<0? 1 : -1;
			}
			else{
				return Math.Abs(d1) < Math.Abs(d2) ? -1 : 1 ;
			}
		}

		// value yyyy
		double.TryParse(mark1[3],out d1);
		double.TryParse(mark2[3], out d2);
		if (Math.Round(d1-d2,4)!=0)
		{
			if ( d1<0 ^ d2<0)
			{
				return d1<0? 1 : -1;
			}
			else{
				return Math.Abs(d1) < Math.Abs(d2) ? -1 : 1 ;
			}
		}
		return 0;
	}
}

jeremytammik
Autodesk
Autodesk

Many thanks to Fair59 for yet another brilliant and succinct answer.

 

Edited and saved for posterity on the blog:

 

https://thebuildingcoder.typepad.com/blog/2019/11/dll-conflicts-and-replicating-schedule-sort-order....

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

0 Likes