private static void AddFieldToSchedule( ViewSchedule viewSchedule, BuiltInParameter builtInParameter, out bool fieldAlreadyAdded) { var schedulableFields = viewSchedule.Definition.GetSchedulableFields(); fieldAlreadyAdded = false; foreach (var sf in schedulableFields) { if (sf.FieldType != ScheduleFieldType.Instance) { continue; } if (sf.ParameterId.IntegerValue != (int)builtInParameter) { continue; } // Get all schedule field ids var ids = viewSchedule.Definition.GetFieldOrder(); foreach (var id in ids) { try { var scheduleField = viewSchedule.Definition.GetField(id); if (scheduleField.GetSchedulableField() == sf) { fieldAlreadyAdded = true; scheduleField.IsHidden = false; break; } } catch { // Тут бывают какие-то ошибки, но мне они не важны, поэтому проще их "проглотить" } } if (fieldAlreadyAdded == false) { viewSchedule.Definition.AddField(sf); } } viewSchedule.RefreshData(); viewSchedule.Document.Regenerate(); }
/// <summary> /// Получение сортированных элементов из спецификации с не установленной галочкой "Для каждого экземпляра" /// </summary> /// <param name="viewSchedule">Вид спецификации</param> /// <param name="elements">Элементы, полученные с этого вида</param> private IEnumerable <RowData <int> > GetSortedElementsFromNotItemizedScheduleBySignalValue( ViewSchedule viewSchedule, List <Element> elements) { var sortedElements = new List <RowData <int> >(); var builtInParameter = GetBuiltInParameterForElements(elements); if (builtInParameter == null) { return(sortedElements); } // запоминаю начальные значения в параметре var cachedParameterValues = new Dictionary <Element, string>(); elements.ForEach(e => { var parameter = e.get_Parameter(builtInParameter.Value); cachedParameterValues.Add(e, parameter.AsString()); }); const string signalValue = "$Filled$"; var columnNumber = -1; var startRowNumber = -1; bool fieldAlreadyAdded; using (var transaction = new SubTransaction(viewSchedule.Document)) { transaction.Start(); // всем элементам записываем в комментарий сигнальное значение в виде двух специальных символов elements.ForEach(e => { if (e.GroupId != ElementId.InvalidElementId) { (e.Document.GetElement(e.GroupId) as Group)?.UngroupMembers(); } var parameter = e.get_Parameter(builtInParameter.Value); parameter.Set(signalValue); }); // К спецификации добавляем поле. Код из справки, за исключением try {} catch{} AddFieldToSchedule(viewSchedule, builtInParameter.Value, out fieldAlreadyAdded); // в зависимости от количества строк в таблице сразу заполняю коллекцию "болванками" и // нахожу номер нужной колонки и первой строки var sectionData = viewSchedule.GetTableData().GetSectionData(SectionType.Body); var rowNumber = 0; for (var r = sectionData.FirstRowNumber; r <= sectionData.LastRowNumber; r++) { for (var c = sectionData.FirstColumnNumber; c <= sectionData.LastColumnNumber; c++) { var cellValue = viewSchedule.GetCellText(SectionType.Body, r, c); if (cellValue.Contains(signalValue)) { rowNumber++; sortedElements.Add(new RowData <int>(rowNumber)); if (startRowNumber == -1) { startRowNumber = r; } if (columnNumber == -1) { columnNumber = c; } break; } } } transaction.Commit(); } // теперь выполняю итерацию по всем элементам for (var index = 0; index < elements.Count; index++) { var element = elements[index]; using (var transaction = new SubTransaction(viewSchedule.Document)) { transaction.Start(); if (index != 0) { var parameter = elements[index - 1].get_Parameter(builtInParameter.Value); // возвращаю элементу значение в параметр parameter.Set(signalValue); } { // элементу стираю второй символ. Первый символ нужен, чтобы идентифицировать ячейку var parameter = element.get_Parameter(builtInParameter.Value); parameter.Set(string.Empty); } // регенерирую таблицу, чтобы обновить представление viewSchedule.RefreshData(); viewSchedule.Document.Regenerate(); transaction.Commit(); } // теперь смотрю какая ячейка погасла var sectionData = viewSchedule.GetTableData().GetSectionData(SectionType.Body); var rowNumber = 0; for (var r = startRowNumber; r <= sectionData.LastRowNumber; r++) { rowNumber++; var cellValue = viewSchedule.GetCellText(SectionType.Body, r, columnNumber); /* * Начиная с версии 2022 в ячейках с разными значениями пишется <варианты>. Проверять буду по скобкам */ if (string.IsNullOrEmpty(cellValue) || (cellValue.StartsWith("<") && cellValue.EndsWith(">"))) { var elInRow = sortedElements.FirstOrDefault(e => e.RowNumber == rowNumber); elInRow?.Items.Add(element.Id.IntegerValue); break; } } } // восстанавливаю начальные значения параметров using (var transaction = new SubTransaction(viewSchedule.Document)) { transaction.Start(); foreach (var pair in cachedParameterValues) { var parameter = pair.Key.get_Parameter(builtInParameter.Value); parameter.Set(pair.Value); } // если поле не было добавлено изначально, то нужно его удалить if (!fieldAlreadyAdded) { RemoveFieldFromSchedule(viewSchedule, builtInParameter.Value); } transaction.Commit(); } return(sortedElements); }