Как настроить динамический отбор строк в табличной части при переключении строк в другой табличной части?

Программист 1С v8.3 (Управляемые формы) 1С:ERP Управление предприятием Управленческий учет IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на управляемых формах в 1С часто возникает задача организации связи двух табличных частей по принципу «мастер — деталь». Типичный пример: в основной таблице пользователь выбирает строку (например, продукцию или раздел), а в подчиненной табличной части должны отображаться только те строки, которые относятся к текущему выбранному элементу (например, сырье, материалы или товары выбранного раздела).

Разберем, как устроен этот механизм на уровне платформы «1С:Предприятие 8.3», почему табличная часть может неожиданно оказаться пустой и как правильно реализовать фильтрацию строк программно.

Механизм свойства ОтборСтрок таблицы формы

Для быстрой фильтрации строк таблицы, отображающей данные табличной части объекта, платформа предоставляет свойство элемента формы ОтборСтрок. Оно принимает значение типа ФиксированнаяСтруктура, где ключами выступают имена колонок табличной части, а значениями — фильтруемые данные.

Проанализируем базовый код, который разработчики обычно помещают в обработчик события ПриАктивизацииСтроки ведущей таблицы:


&НаКлиенте
Процедура ВыходныеИзделияПриАктивизацииСтрокиПосле(Элемент)
    
    ТекДанныеВыходныеИзделия = Элементы.ВыходныеИзделия.ТекущиеДанные;
    
    Если ТекДанныеВыходныеИзделия = Неопределено Тогда
        Элементы.МатериалыИРаботы.ОтборСтрок = Неопределено;
    Иначе
        ТекНоменклатура = ТекДанныеВыходныеИзделия.Номенклатура;
        Элементы.МатериалыИРаботы.ОтборСтрок = Новый ФиксированнаяСтруктура("Номенклатура", ТекНоменклатура);
    КонецЕсли;    
    
КонецПроцедуры

На первый взгляд код выглядит абсолютно корректным. Однако при его тестировании разработчики нередко сталкиваются с ситуацией: при выборе первой строки подчиненная таблица отображает данные, а при переходе на другие строки внезапно становится абсолютно пустой. Выясним причину такого поведения.

Анализ проблемы: прикладные данные и логика документа

Когда программный код установки свойства ОтборСтрок синтаксически верен, но подчиненная таблица пуста, корень проблемы практически всегда кроется в несоответствии реальных данных условию отбора.

Рассмотрим специфику документа ПроизводствоБезЗаказа в конфигурации «1С:ERP Управление предприятием»:

  1. Разное назначение колонок: В табличной части ВыходныеИзделия в реквизите Номенклатура указывается готовая продукция. В табличной части МатериалыИРаботы в реквизите Номенклатура указываются исходные компоненты, материалы и полуфабрикаты. Они физически не совпадают, за исключением редких ситуаций разборки или переработки изделия «в само себя». Попытка сопоставить их по полю Номенклатура приводит к тому, что платформа ищет строки материалов, у которых номенклатура в точности равна готовой продукции. Естественно, таких строк не находится, и таблица становится пустой.
  2. Штатный идентификатор связи: В типовых документах ERP строки выпуска и строки списанных затрат связываются между собой не по номенклатуре, а через числовой служебный реквизит НомерГруппыЗатрат.

Вариант 1. Корректная связь табличных частей по служебному ключу

Если в документе включена построчная группировка затрат (варианты «По продукции», «По продукции и назначениям» или «По спецификациям»), строки выпуска и строки затрат обладают одинаковым значением НомерГруппыЗатрат. Для корректной фильтрации нам необходимо накладывать отбор именно по этой числовой колонке.

Посмотрим на пример правильной реализации фильтрации:


&НаКлиенте
Процедура ВыходныеИзделияПриАктивизацииСтрокиПосле(Элемент)
    
    ТекДанные = Элементы.ВыходныеИзделия.ТекущиеДанные;
    
    Если ТекДанные = Неопределено Или Не ЗначениеЗаполнено(ТекДанные.НомерГруппыЗатрат) Тогда
        // Снимаем отбор, если строка не выбрана или группа затрат не определена
        Если Элементы.МатериалыИРаботы.ОтборСтрок <> Неопределено Тогда
            Элементы.МатериалыИРаботы.ОтборСтрок = Неопределено;
        КонецЕсли;
    Иначе
        // Проверяем, изменился ли отбор, чтобы избежать лишней перерисовки формы
        ТекущийОтбор = Элементы.МатериалыИРаботы.ОтборСтрок;
        Если ТекущийОтбор = Неопределено Или ТекущийОтбор.НомерГруппыЗатрат <> ТекДанные.НомерГруппыЗатрат Тогда
            Элементы.МатериалыИРаботы.ОтборСтрок = Новый ФиксированнаяСтруктура("НомерГруппыЗатрат", ТекДанные.НомерГруппыЗатрат);
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

Вариант 2. Реализация отбора по типовому паттерну ERP с задержкой через обработчик ожидания

Событие ПриАктивизацииСтроки генерируется платформой очень часто: при навигации стрелками по клавиатуре, при программных обновлениях, при перерисовке таблицы. Если при каждом таком вызове сразу выполнять тяжелую перенастройку зависимых элементов, интерфейс начнет подвисать или мерцать.

В типовых конфигурациях (например, в документе «Таможенная декларация на импорт» для разделов и товаров) применяется паттерн с отложенным вызовом процедуры установки отбора через ПодключитьОбработчикОжидания.

Разберем по шагам реализацию этого подхода:

  1. В событии активизации строки подключаем однократный обработчик ожидания с минимальной задержкой.
  2. В вызываемой процедуре проверяем текущие данные и сравниваем их с уже установленным отбором.
  3. Если отбор отличается, формируем новую ФиксированнаяСтруктура.

&НаКлиенте
Процедура РазделыПриАктивизацииСтроки(Элемент)
    // Подключаем однократный вызов через 0.2 секунды
    ПодключитьОбработчикОжидания("АктивироватьРаздел", 0.2, Истина);
КонецПроцедуры

&НаКлиенте
Процедура АктивироватьРаздел()
    
    ТекДанные = Элементы.Разделы.ТекущиеДанные;
    Товары = Элементы.Товары;
    
    Если ТекДанные = Неопределено Тогда
        Если Товары.ОтборСтрок <> Неопределено Тогда
            Товары.ОтборСтрок = Неопределено;
        КонецЕсли;
        Возврат;
    КонецЕсли;
    
    РазделОтбора = ТекДанные.НомерРаздела;
    
    // Включаем или обновляем отбор, только если значение изменилось
    Если Товары.ОтборСтрок = Неопределено Или Товары.ОтборСтрок.НомерРаздела <> РазделОтбора Тогда
        Товары.ОтборСтрок = Новый ФиксированнаяСтруктура("НомерРаздела", РазделОтбора);
    КонецЕсли;
    
КонецПроцедуры

Особенности и ограничения свойства ОтборСтрок, о которых важно помнить

При использовании платформенного свойства ОтборСтрок необходимо учитывать несколько строгих правил:

  1. Только строгое равенство: Свойство поддерживает исключительно условие «равно» (оператор =). Нельзя передать условие вхождения в массив («в списке»), логическое «НЕ» или сравнение больше/меньше.
  2. Только реквизиты самой табличной части: В структуру можно передавать только те поля, которые непосредственно присутствуют в реквизитах исходной табличной части объекта. Нельзя использовать реквизиты, полученные через точку (например, Номенклатура.ВидНоменклатуры), или искусственные колонки формы.
  3. Автоматическое заполнение новых строк: Если на табличную часть наложен ОтборСтрок, то при интерактивном добавлении новой строки (по кнопке «Добавить» или клавише Insert) платформа автоматически подставит в соответствующие колонки новой строки те значения, по которым установлен фильтр.
  4. Контроль значения ТекущиеДанные: Если пользователь удалит все строки из ведущей таблицы или снимет фокус с таблицы, свойство ТекущиеДанные вернет Неопределено. Программный код обязательно должен содержать ветку для сброса отбора: Элементы.ТаблицаПриемник.ОтборСтрок = Неопределено.
← На главную