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

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

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

Почему Соединение не подходит для этой задачи

Разберем типичную ошибку начинающих разработчиков. Часто пытаются использовать ЛЕВОЕ СОЕДИНЕНИЕ или ПОЛНОЕ СОЕДИНЕНИЕ табличных частей. Проанализируем, почему это не сработает в нашем случае. При соединении таблиц система пытается сопоставить строки по какому-либо условию (например, по совпадению номенклатуры). Если мы соединим «Товары» и «Материалы», мы получим «широкую» таблицу, где данные будут располагаться в разных колонках в рамках одной строки, либо строки будут дублироваться, если одна и та же номенклатура есть в обеих таблицах. Нам же нужно «вертикальное» наращивание таблицы — чтобы строки из «Материалов» просто добавились в конец списка строк из «Товаров».

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

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

  1. Количество полей: Во всех объединяемых запросах количество выбираемых полей должно быть строго одинаковым.
  2. Порядок полей: Поля сопоставляются по их порядковому номеру в списке ВЫБРАТЬ, а не по именам.
  3. Типы данных: Типы данных в соответствующих колонках должны быть совместимы.
  4. Имена колонок (Псевдонимы): Итоговые имена полей всей выборки определяются псевдонимами, заданными в первом запросе объединения.

Проанализируем пример реализации запроса для печатной формы:


|ВЫБРАТЬ
|    РасходнаяНакладнаяЗапасы.Ссылка КАК Ссылка,
|    РасходнаяНакладнаяЗапасы.Номенклатура КАК Номенклатура,
|    РасходнаяНакладнаяЗапасы.Количество КАК Количество
|ИЗ
|    Документ.РасходнаяНакладная.Запасы КАК РасходнаяНакладнаяЗапасы
|ГДЕ
|    РасходнаяНакладнаяЗапасы.Ссылка = &Ссылка
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|    РасходнаяНакладнаяМатериалы.Ссылка,
|    РасходнаяНакладнаяМатериалы.Материал,
|    РасходнаяНакладнаяМатериалы.Количество
|ИЗ
|    Документ.РасходнаяНакладная.Материалы КАК РасходнаяНакладнаяМатериалы
|ГДЕ
|    РасходнаяНакладнаяМатериалы.Ссылка = &Ссылка

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

Разница между ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ

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

Работа с отсутствующими полями через NULL и 0

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

Рассмотрим пример, где мы выводим цену для товаров, но для материалов цена не предусмотрена:


|ВЫБРАТЬ
|    Т.Ссылка,
|    Т.Номенклатура,
|    Т.Цена КАК Цена
|ИЗ
|    Документ.РасходнаяНакладная.Товары КАК Т
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|    М.Ссылка,
|    М.Материал,
|    0  // Вместо цены подставляем числовой ноль
|ИЗ
|    Документ.РасходнаяНакладная.Материалы КАК М

Использование 0 вместо NULL для числовых полей предпочтительнее, если в дальнейшем вы планируете суммировать эти данные в итогах или макете. Если же поле ссылочное (например, Склад), можно использовать NULL или ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка).

Как настроить объединение в Конструкторе запросов

Если вы предпочитаете использовать визуальный конструктор, выполните следующие шаги:

  1. Откройте Конструктор запроса.
  2. На первой вкладке выберите первую таблицу (например, Запасы) и нужные поля.
  3. Перейдите на вкладку Объединения/Псевдонимы.
  4. Нажмите кнопку с белым плюсом на зеленом фоне (в левой верхней части вкладки). Система создаст второй вложенный запрос.
  5. Перейдите обратно на вкладку Таблицы и поля. Вы увидите, что в списке запросов (слева) появился «Запрос 2».
  6. Выберите вторую таблицу (Материалы) и перетащите соответствующие поля в правую колонку. Убедитесь, что они стоят в том же порядке, что и в первом запросе.
  7. На вкладке Объединения/Псевдонимы убедитесь, что галочка «Все» установлена для каждого объединения.

Сортировка и Итоги

Проанализируем ситуацию, когда нам важно сохранить порядок: сначала товары, потом материалы. При использовании ОБЪЕДИНИТЬ ВСЕ СУБД не гарантирует порядок строк. Чтобы управлять им, добавим искусственное поле сортировки:


|ВЫБРАТЬ
|    1 КАК ПорядокВывода,
|    Товары.Номенклатура
|ИЗ
|    Документ.РасходнаяНакладная.Товары КАК Товары
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|    2,
|    Материалы.Материал
|ИЗ
|    Документ.РасходнаяНакладная.Материалы КАК Материалы
|
|УПОРЯДОЧИТЬ ПО
|    ПорядокВывода,
|    Номенклатура

Также не забывайте про секцию ИТОГИ, если ваша печатная форма предполагает группировку по Ссылке документа (актуально при пакетной печати нескольких документов одним запросом):


|ИТОГИ
|    СУММА(Количество)
|ПО
|    Ссылка

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

← На главную