При работе в конфигурации 1С:Управление производственным предприятием 1.3 (на платформе 8.3 с использованием обычных форм) программисты часто сталкиваются с ограничением: стандартный механизм отборов в форме списка не позволяет фильтровать данные по реквизитам табличных частей. Это связано с архитектурой хранения данных в СУБД, где документы и их строки находятся в разных физических таблицах. Попытка вывести данные ТЧ через событие ПриВыводеСтроки решает задачу визуализации, но кнопка отбора остается неактивной.
В этой статье мы подробно разберем несколько эффективных способов решения этой задачи, проанализируем их плюсы и минусы, а также напишем необходимый программный код.
Разберем ситуацию с технической точки зрения. Когда мы открываем форму списка, система выполняет запрос к таблице документов. Если мы добавим колонку, которая вычисляется динамически (например, берет первую строку из табличной части в момент отрисовки), платформа не может применить к ней индекс или выполнить эффективную фильтрацию на уровне SQL-запроса без использования соединений (JOIN). Именно поэтому стандартный отбор «по значению в текущей колонке» в таких случаях неактивен.
Этот метод считается наиболее практичным, так как он обеспечивает максимальную скорость работы отбора. Суть заключается в создании дополнительного реквизита в самом документе, который будет зеркально отображать значение из табличной части.
Шаг 1. Изменение структуры метаданных
Для начала добавим в документ (например, ПлатежноеПоручениеВходящее) новый реквизит СтатьяДДСДляОтбора. Тип должен соответствовать типу реквизита в табличной части (СправочникСсылка.СтатьиДвиженияДенежныхСредств).
Важный момент: Чтобы поиск и отбор работали быстро, в свойствах этого реквизита обязательно установите значение Индексировать или Индексировать с дополнительным упорядочиванием. Это создаст индекс в базе данных, и отбор даже по сотням тысяч документов будет мгновенным.
Шаг 2. Автоматизация заполнения реквизита
Теперь нам нужно гарантировать, что при каждой записи документа новый реквизит будет актуализироваться. Рассмотрим, почему лучше использовать модуль объекта и событие ПередЗаписью.
Проанализируем пример кода, который необходимо разместить в модуле документа:
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
// Проверяем, что запись происходит не в режиме загрузки данных (например, через обмен)
Если ОбменДанными.Загрузка Тогда
Возврат;
КонецЕсли;
// Проверяем наличие строк в табличной части
Если РасшифровкаПлатежа.Количество() > 0 Тогда
// Заполняем реквизит шапки значением из первой строки табличной части
СтатьяДДСДляОтбора = РасшифровкаПлатежа[0].СтатьяДвиженияДенежныхСредств;
Иначе
// Если строк нет, очищаем реквизит
СтатьяДДСДляОтбора = Справочники.СтатьиДвиженияДенежныхСредств.ПустаяСсылка();
КонецЕсли;
КонецПроцедуры
Использование обработчика ПередЗаписью в модуле объекта критически важно. Это гарантирует заполнение данных при любом способе записи: будь то ручной ввод пользователем, программное создание или использование групповой обработки справочников и документов. Если поместить этот код в форму, он не сработает при записи без открытия формы.
Шаг 3. Обработка исторических данных
После внесения изменений в конфигурацию новый реквизит у старых документов останется пустым. Нам потребуется написать разовую обработку для заполнения этих данных. Разберем пример логики такой обработки:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ПлатежноеПоручениеВходящее.Ссылка КАК Ссылка
|ИЗ
| Документ.ПлатежноеПоручениеВходящее КАК ПлатежноеПоручениеВходящее
|ГДЕ
| ПлатежноеПоручениеВходящее.СтатьяДДСДляОтбора = ЗНАЧЕНИЕ(Справочник.СтатьиДвиженияДенежныхСредств.ПустаяСсылка)";
Результат = Запрос.Выполнить().Выбрать();
Пока Результат.Следующий() Цикл
ОбъектДок = Результат.Ссылка.ПолучитьОбъект();
// При вызове Записать() сработает наш код в ПередЗаписью()
ОбъектДок.Записать(РежимЗаписиДокумента.Запись);
КонецЦикла;
Если «корежить» конфигурацию добавлением новых реквизитов в каждый документ не хочется, можно воспользоваться механизмом Критерии отбора. Это специальный объект метаданных, предназначенный как раз для таких задач.
Рассмотрим порядок действий:
ПоСтатьеДДС.После этого у пользователя появится возможность нажать на кнопку «Связанные данные» или открыть форму критерия отбора, выбрать статью и увидеть полный список документов, в которых она встречается (даже если в одном документе несколько разных статей). Плюс этого метода в том, что он не раздувает размер базы данных дублированием полей.
Иногда требуется решить задачу динамически на форме, не меняя структуру метаданных. Мы можем программно собрать массив ссылок на документы, подходящие под условие, и передать их в отбор списка.
Проанализируем ситуацию: этот метод хорош только в том случае, если выборка документов невелика. Если документов в базе десятки тысяч, отбор Ссылка В Списке будет работать крайне медленно.
Пример программной реализации в обработчике нажатия кнопки:
Запрос = Новый Запрос;
Запрос.УстановитьПараметр("ВыбраннаяСтатья", ПоискСтатьяДДС);
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| РасшифровкаПлатежа.Ссылка
|ИЗ
| Документ.ПлатежноеПоручениеВходящее.РасшифровкаПлатежа КАК РасшифровкаПлатежа
|ГДЕ
| РасшифровкаПлатежа.СтатьяДвиженияДенежныхСредств = &ВыбраннаяСтатья";
СписокСсылок = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");
// Устанавливаем отбор в элементе формы "Список"
ДокументСписок.Отбор.Ссылка.Использование = Истина;
ДокументСписок.Отбор.Ссылка.ВидСравнения = ВидСравнения.ВСписке;
ДокументСписок.Отбор.Ссылка.Значение.ЗагрузитьЗначения(СписокСсылок);
Подведем итоги нашего исследования. Мы рассмотрели три основных подхода:
ПередЗаписью). Недостаток — если в документе две разные статьи в ТЧ, отбор найдет документ только по первой.Выясним причину, почему автор вопроса остановился именно на первом методе: в УПП 1.3 специфика бизнес-процессов часто подразумевает, что одно платежное поручение относится к одной статье ДДС. В этом случае дублирование в шапку с индексацией является «золотым стандартом» разработки, обеспечивающим комфортную работу пользователей без ожидания формирования сложных запросов.
Помните, что при реализации любого из этих методов важно протестировать работу системы под нагрузкой и убедиться, что новые индексы не замедляют процесс записи документов в периоды пиковой активности.