Как реализовать сложную выборку документов и программную обработку таблицы значений в 1С 8.3

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

В практике разработчика 1С часто возникают задачи, требующие не просто получения данных, а многоступенчатой фильтрации с учетом условий в табличных частях и связанных регистрах. Разберем комплексный пример создания внешней обработки, которая анализирует документы «Ведомость», сопоставляет даты их договоров и проверяет статусы в независимом регистре сведений. Мы научимся работать с пакетными запросами, программно управлять строками таблицы значений и настраивать визуальное выделение данных.

Проектирование интерфейса и реквизитов формы

Прежде чем переходить к коду, проанализируем структуру необходимых данных. Нам потребуется внешняя обработка с таблицей на форме. Для обеспечения гибкости условий (минимальная/максимальная дата, равно/не равно) важно правильно настроить реквизиты формы. Рассмотрим состав основных реквизитов:

  1. Результат (Тип: ТаблицаЗначений) — основная таблица, куда будут попадать найденные ведомости.
  2. АкцептованныеВедомости (Тип: Массив) — вспомогательный список для хранения ссылок на документы с определенным статусом.
  3. Равно и Максимальная (Тип: Булево) — флаги, определяющие логику фильтрации в запросе.
  4. СообщениеОбУдалении (Тип: Строка) — для вывода информационного текста пользователю.

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

Реализация основной логики выборки данных

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

Сначала подготовим временную таблицу со всеми строками табличных частей документов Ведомость:


ВЫБРАТЬ
    ТабличнаяЧасть.Ссылка КАК Ведомость,
    ТабличнаяЧасть.НомерСтроки КАК НомерСтроки,
    ТабличнаяЧасть.Договор.Активен КАК ДоговорАктивен,
    ТабличнаяЧасть.Договор.НачалоДействия КАК НачалоДействия
ПОМЕСТИТЬ ВТ_Строки
ИЗ
    Документ.Ведомость.Договоры КАК ТабличнаяЧасть
;

Затем определим первый активный договор для каждой ведомости. Важный момент: под «первым» здесь подразумевается договор с минимальным номером строки, у которого флаг Активен установлен в значение Истина.


ВЫБРАТЬ
    ВТ_Строки.Ведомость КАК Ведомость,
    МИНИМУМ(ВТ_Строки.НомерСтроки) КАК НомерПервогоАктивного
ПОМЕСТИТЬ ВТ_ПервыйАктивный
ИЗ
    ВТ_Строки КАК ВТ_Строки
ГДЕ
    ВТ_Строки.ДоговорАктивен = ИСТИНА
СГРУППИРОВАТЬ ПО
    ВТ_Строки.Ведомость
;

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


ГДЕ
    (
        (&Максимальная = ЛОЖЬ И &Равно = ИСТИНА И ПервыйАктивный.НачалоПервогоАктивного = Границы.МинДата)
        ИЛИ (&Максимальная = ЛОЖЬ И &Равно = ЛОЖЬ И ПервыйАктивный.НачалоПервогоАктивного <> Границы.МинДата)
        ИЛИ (&Максимальная = ИСТИНА И &Равно = ИСТИНА И ПервыйАктивный.НачалоПервогоАктивного = Границы.МаксДата)
        ИЛИ (&Максимальная = ИСТИНА И &Равно = ЛОЖЬ И ПервыйАктивный.НачалоПервогоАктивного <> Границы.МаксДата)
    )

Работа со статусами из независимого регистра

Поскольку регистр сведений ИсторияСтатусовДокументов является непериодическим, мы не можем использовать виртуальную таблицу СрезПоследних. Рассмотрим, как получить последний статус программным путем через запрос. Нам нужно сгруппировать записи регистра по документу и найти МАКСИМУМ(ДатаЗаписи). Затем, соединив полученный результат с основной таблицей регистра, мы извлечем конкретное значение статуса на этот момент.

Если последний статус равен значению Перечисления.СтатусыДокументов.Акцептован, мы помечаем такую ведомость в специальном массиве. Это позволит нам в дальнейшем раскрасить строки таблицы на форме.

Программная очистка и удаление строк

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

  1. Сначала мы собираем все ведомости, уже находящиеся в нашей таблице на форме, в массив.
  2. Выполняем запрос к табличной части Договоры документа Ведомость, используя оператор СГРУППИРОВАТЬ ПО и агрегатную функцию КОЛИЧЕСТВО(НомерСтроки).
  3. В цикле обходим нашу таблицу значений с конца (используя шаг -1). Это критически важно, так как при удалении строки индексы последующих элементов смещаются.
  4. Проверяем условие четности: КоличествоДоговоров % 2 = 0. Если оно истинно — удаляем строку и запоминаем номер ведомости для итогового сообщения.

Для Индекс = Результат.Количество - 1 По 0 Шаг -1 Цикл
    Строка = Результат[Индекс];
    КоличествоДоговоров = СоответствиеКоличеств.Получить(Строка.Ведомость);
    Если КоличествоДоговоров % 2 = 0 Тогда
        // Код сбора номера ведомости для отчета
        Результат.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;

Визуальное оформление и оптимизация

Для выделения строк цветом в управляемых формах существует два подхода. Рассмотрим их преимущества и недостатки:

Способ 1: Обработчик ПриВыводеСтроки. Позволяет динамически менять оформление каждой ячейки. В нашем примере мы проверяем наличие ссылки в массиве АкцептованныеВедомости и устанавливаем ЦветФона.

Способ 2: Условное оформление (Рекомендуемый). Настраивается в свойствах формы или программно в ПриСозданииНаСервере. Работает быстрее на стороне платформы. Для этого в таблицу значений стоит добавить скрытую колонку ЭтоАкцептован (Булево) и установить правило оформления: если ЭтоАкцептован = Истина, то фон строки — светло-зеленый.

Также обратим внимание на формирование финальной строки сообщения. Для удобства чтения списка удаленных номеров рекомендуется использовать функцию СтрСоединить или СтрШаблон. Это делает код более лаконичным и позволяет избежать лишних проверок на наличие запятой перед следующим номером.

Выясним еще один важный технический нюанс: при работе с составными типами данных в регистре сведений (измерение «Документ») для повышения производительности запроса всегда рекомендуется использовать оператор ВЫРАЗИТЬ(История.Документ КАК Документ.Ведомость). Это помогает СУБД быстрее строить план выполнения запроса, не обращаясь к лишним таблицам других типов документов.

← На главную