Как настроить выборку данных из разных типов документов для внешней печатной формы?

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

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

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

Способ 1. Использование оператора ОБЪЕДИНИТЬ ВСЕ в запросе

Это наиболее прямолинейный и эффективный способ, который позволяет получить данные в одном пакете запроса. Мы разделяем логику выборки на два блока: первый выбирает накладные через табличную часть Маршрутных листов, а второй — напрямую из ссылок на накладные.

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


ВЫБРАТЬ
    МаршрутныйЛистЗаказы.Ссылка КАК ДокументОснование,
    МаршрутныйЛистЗаказы.РасходнаяНакладная КАК РасходнаяНакладная
ПОМЕСТИТЬ втДанные
ИЗ
    Документ.МаршрутныйЛист.Заказы КАК МаршрутныйЛистЗаказы
ГДЕ
    МаршрутныйЛистЗаказы.Ссылка В(&МассивОбъектов)

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    ЗНАЧЕНИЕ(Документ.МаршрутныйЛист.ПустаяСсылка),
    РасходнаяНакладная.Ссылка
ИЗ
    Документ.РасходнаяНакладная КАК РасходнаяНакладная
ГДЕ
    РасходнаяНакладная.Ссылка В(&МассивОбъектов)
;

Важные замечания к этому способу:

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

Способ 2. Предварительная нормализация массива в коде (BSL)

Иногда проще подготовить данные до передачи в запрос. Мы можем перебрать входящий МассивОбъектов и сформировать новый массив, который будет содержать только ссылки на Расходные накладные, независимо от того, что пришло на вход.

Рассмотрим пример кода для модуля обработки:


НовыйМассивОбъектов = Новый Массив;

Для Каждого Ссылка Из МассивОбъектов Цикл
    Если ТипЗнч(Ссылка) = Тип("ДокументСсылка.МаршрутныйЛист") Тогда
        // Извлекаем накладные из табличной части
        Запрос = Новый Запрос;
        Запрос.Текст = 
            "ВЫБРАТЬ РАЗЛИЧНЫЕ
            |	МаршрутныйЛистЗаказы.РасходнаяНакладная
            |ИЗ
            |	Документ.МаршрутныйЛист.Заказы КАК МаршрутныйЛистЗаказы
            |ГДЕ
            |	МаршрутныйЛистЗаказы.Ссылка = &Ссылка";
        Запрос.УстановитьПараметр("Ссылка", Ссылка);
        Выборка = Запрос.Выполнить().Выбрать();
        Пока Выборка.Следующий() Цикл
            НовыйМассивОбъектов.Добавить(Выборка.РасходнаяНакладная);
        КонецЦикла;
    ИначеЕсли ТипЗнч(Ссылка) = Тип("ДокументСсылка.РасходнаяНакладная") Тогда
        НовыйМассивОбъектов.Добавить(Ссылка);
    КонецЕсли;
КонецЦикла;

// Далее передаем НовыйМассивОбъектов в основной запрос печати

Этот подход делает основной запрос печатной формы значительно проще, так как он будет работать только с одним типом документа. Однако стоит учитывать, что если печатная форма должна выводить данные самого Маршрутного листа (например, его номер), то этот метод потребует доработки для сохранения связи.

Способ 3. Использование оператора ССЫЛКА в запросе

Если мы хотим оставить логику внутри одного запроса, но сделать её более "чистой", проанализируем возможность использования оператора ССЫЛКА. Это позволяет фильтровать данные по типам прямо в секции ГДЕ.

Пример реализации:


ВЫБРАТЬ
    Ссылка КАК ОбъектПечати,
    ТИПЗНАЧЕНИЯ(Ссылка) КАК ТипОбъекта
ПОМЕСТИТЬ втИсходныеСсылки
ИЗ
    ДанныеДокументов // Условная таблица или передача через параметр
ГДЕ
    Ссылка В(&МассивОбъектов)
;

ВЫБРАТЬ
    МаршрутныйЛистЗаказы.РасходнаяНакладная
ИЗ
    Документ.МаршрутныйЛист.Заказы КАК МаршрутныйЛистЗаказы
ГДЕ
    МаршрутныйЛистЗаказы.Ссылка В (ВЫБРАТЬ Ссылка ИЗ втИсходныеСсылки ГДЕ Ссылка ССЫЛКА Документ.МаршрутныйЛист)

Этот метод удобен тем, что платформа 1С на уровне SQL-запроса эффективно отсекает ненужные типы данных, что положительно сказывается на производительности при больших объемах данных.

Нюансы производительности и прав доступа

Разберем важные моменты, которые часто упускают начинающие разработчики:

  1. Индексация временных таблиц: Если вы помещаете ссылки во временную таблицу (ПОМЕСТИТЬ втМаршрутный), всегда добавляйте ИНДЕКСИРОВАТЬ ПО Ссылка. Это значительно ускорит последующие соединения с реальными таблицами документов.
  2. Работа с RLS: Помните, что если у пользователя настроены права доступа на уровне записей (RLS), запрос к Документ.МаршрутныйЛист.Заказы может вернуть пустой результат, если у пользователя нет прав на этот конкретный тип документа, даже если права на Расходную накладную у него есть.
  3. Метод "Различные": При выборке из табличных частей (как в Сообщении 18 обсуждения) всегда используйте ВЫБРАТЬ РАЗЛИЧНЫЕ. В реальных базах данных после различных обработок или объединений дублей в табличных частях могут оказаться дублирующиеся строки, что приведет к задвоению данных в печатной форме.

Использование возможностей БСП

Проанализируем архитектуру БСП (Библиотеки Стандартных Подсистем). При регистрации ВПФ в функции СведенияОВнешнейОбработке мы указываем массив документов, для которых предназначена эта форма. Если логика печати для разных документов сильно отличается, иногда правильнее создать две разные команды печати в рамках одной обработки. Это позволит БСП передавать в процедуру печати однородный массив данных, что исключит необходимость сложных проверок типов внутри кода.

Резюмируя: для решения задачи наиболее сбалансированным является Способ 1 с использованием ОБЪЕДИНИТЬ ВСЕ, при условии корректной обработки пустых ссылок и группировки данных для исключения дублей. Это сохраняет всю логику в одном месте и обеспечивает высокую скорость работы формы.

← На главную