private static List<Element> GetSortedElementsFromSchedule(ViewSchedule viewSchedule, List<Element> elements)
{
List<Element> sortedElements = new List<Element>();
using (SubTransaction transaction = new SubTransaction(viewSchedule.Document))
{
transaction.Start();
// Разделитель
var separator = "$ElementId=";
// Записываем Id всех элементов в параметр "Комментарий"
elements.ForEach(e =>
{
var parameter = e.get_Parameter(BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS);
parameter.Set(parameter.AsString() + separator + e.Id.IntegerValue);
});
// К спецификации добавляем поле. Код из справки, за исключением try {} catch{}
IList<SchedulableField> schedulableFields = viewSchedule.Definition.GetSchedulableFields();
foreach (SchedulableField sf in schedulableFields)
{
if (sf.FieldType != ScheduleFieldType.Instance)
continue;
if (sf.ParameterId.IntegerValue != (int)BuiltInParameter.ALL_MODEL_INSTANCE_COMMENTS)
continue;
bool fieldAlreadyAdded = false;
//Get all schedule field ids
IList<ScheduleFieldId> ids = viewSchedule.Definition.GetFieldOrder();
foreach (ScheduleFieldId id in ids)
{
try
{
if (viewSchedule.Definition.GetField(id).GetSchedulableField() == sf)
{
fieldAlreadyAdded = true;
break;
}
}
catch
{
// Тут бывают какие-то ошибки, но мне они не важны, поэтому проще их "проглатить"
}
}
if (fieldAlreadyAdded == false)
{
viewSchedule.Definition.AddField(sf);
}
}
// Ну и сама магия - просто читаем получившуюся спецификацию по ячейкам и получаем
// элементы уже в том порядке, в котором мы их видим в спецификации
TableSectionData sectionData = viewSchedule.GetTableData().GetSectionData(SectionType.Body);
for (int r = sectionData.FirstRowNumber; r <= sectionData.LastRowNumber; r++)
{
for (int c = sectionData.FirstColumnNumber; c <= sectionData.LastColumnNumber; c++)
{
var cellValue = viewSchedule.GetCellText(SectionType.Body, r, c);
if (cellValue.Contains(separator))
{
var idStr = cellValue.Split(separator.ToCharArray()).Last();
if (!string.IsNullOrEmpty(idStr))
{
// Делаем устойчивым к ошибкам - при наличии ошибок все равно код завершится,
// а я буду знать о возможных проблемах. На мой взгляд лучше, чем полное прерывание метода
try
{
sortedElements.Add(viewSchedule.Document.GetElement(new ElementId(Convert.ToInt32(idStr))));
}
catch (Exception exception)
{
ExceptionBox.Show(exception);
}
}
}
}
}
// Откатываем транзакцию
transaction.RollBack();
}
return sortedElements;
}