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