Часто при разработке в 1С возникает необходимость реализовать зависимое поведение строк в табличной части документа. Например, если пользователь устанавливает в текущей строке статус «Выполнено», система должна автоматически подставить в следующую строку статус «Принято к выполнению» и сделать её доступной для редактирования. Разберем по шагам, как правильно и оптимально реализовать такую логику, избежав типичных ошибок начинающих разработчиков.
Проанализируем ситуацию: у нас есть табличная часть на управляемой форме. Пользователь меняет значение определенного реквизита (например, состояния) в одной из строк. Нам необходимо отловить это событие, найти следующую строку в таблице и изменить в ней данные по заданному условию.
Первая и самая частая ошибка при решении этой задачи — использование идентификатора строки для поиска следующей. Разберем подробнее, в чем кроется подвох.
Свойство Элементы.НашаТаблица.ТекущаяСтрока возвращает не порядковый номер строки, а её Идентификатор. Идентификатор — это уникальный внутренний номер, который присваивается строке при её создании и остается с ней навсегда.
Представим, что пользователь добавил шесть строк. Их идентификаторы будут: 1, 2, 3, 4, 5, 6. Если мы хотим обратиться к следующей строке после строки с идентификатором 2, наивный подход ТекущаяСтрока + 1 вернет 3. Но что если пользователь отсортировал список по алфавиту, удалил пару строк или поменял их местами с помощью стрелок «Вверх/Вниз»? Визуальный порядок может стать таким: 5, 2, 4, 6. В этом случае, прибавив к текущей строке (2) единицу, мы попытаемся обратиться к строке с идентификатором 3, которой уже не существует, и получим ошибку исполнения кода.
Чтобы избежать этого, всегда используйте Индекс строки. Индекс отражает реальное визуальное расположение элементов (начиная с нуля). Чтобы получить индекс текущей строки, воспользуемся методом табличной части:
ДанныеСтроки = Элементы.ИмяТаблицы.ТекущиеДанные;
ИндексТекущейСтроки = Объект.ИмяТаблицы.Индекс(ДанныеСтроки);
Посмотрим на следующий важный этап — проверку наличия последующей строки. Если пользователь редактирует самую последнюю строку в табличной части документа, попытка обратиться к индексу ИндексТекущейСтроки + 1 приведет к выходу за границы массива и аварийному завершению программы.
Обязательно проверяем, что текущая строка не является последней. Условие должно выглядеть так:
Если ИндексТекущейСтроки < Объект.ИмяТаблицы.Количество() - 1 Тогда
// Можно безопасно обращаться к следующей строке
КонецЕсли;
Соберем все знания воедино. Обрабатывать изменение мы будем в событии ПриИзменении самого поля табличной части. Также добавим проверку на Неопределено, чтобы защититься от критических ошибок в случае программной очистки табличной части.
Рассмотрим финальный вариант процедуры:
&НаКлиенте
Процедура ВтулкиСостояниеПриИзменении(Элемент)
ДанныеСтроки = Элементы.Втулки.ТекущиеДанные;
// Защита от отсутствия текущих данных
Если ДанныеСтроки = Неопределено Тогда
Возврат;
КонецЕсли;
ИндексТекущейСтроки = Объект.Втулки.Индекс(ДанныеСтроки);
// Проверяем, что строка не последняя и статус изменен на нужный
Если ИндексТекущейСтроки < Объект.Втулки.Количество() - 1
И ДанныеСтроки.Состояние = ПредопределенноеЗначение("Перечисление.ХХХ_СостояниеВтулокВПроизводстве.Выполнено") Тогда
// Изменяем значение в следующей строке
Объект.Втулки[ИндексТекущейСтроки + 1].Состояние = ПредопределенноеЗначение("Перечисление.ХХХ_СостояниеВтулокВПроизводстве.ВыданоВРаботу");
КонецЕсли;
КонецПроцедуры
Помимо подстановки значения, часто требуется запретить редактирование поля в последующих строках или, наоборот, разрешить его. Важно понимать: в управляемых формах 1С нельзя напрямую обратиться к ячейке в конкретной строке через код, написав что-то вроде Ячейка.Доступность = Ложь. Изменение свойства элемента формы заблокирует колонку сразу во всей таблице.
Для индивидуального управления ячейками используйте механизм Условного оформления формы. Настроим его по шагам:
Только просмотр в значение Истина.Состояние Равно ПустоеЗначение или Состояние Не Равно Принято к выполнению.При таком подходе Платформа 1С:Предприятие будет самостоятельно отслеживать изменения данных и блокировать ячейки без написания громоздкого программного кода.
В завершение разберем несколько неочевидных особенностей платформы, которые необходимо учитывать:
ПриИзменении у этой строки. Если вам нужна «цепная реакция», когда изменение первой строки пересчитывает все последующие до самого конца, вам потребуется реализовать цикл для обхода оставшихся строк табличной части.ПредопределенноеЗначение() на клиенте вполне допустимо и даже кэшируется платформой. Однако, если для определения статуса следующей строки вам потребуется анализировать данные из информационной базы (остатки, реквизиты номенклатуры и т.д.), логику пересчета придется вынести в контекст &НаСервере.