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

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

При разработке в среде 1С:Предприятие 8 часто возникает задача создания универсальной печатной формы, которая должна собирать данные из нескольких видов документов. Например, трудовой договор может печататься как из документа ПриемНаРаботу, так и из ПриемНаРаботуСписком или КадровыйПеревод. Основная сложность заключается в том, что структура хранения данных в этих документах различается: в одном случае данные находятся в шапке, в другом — в табличной части.

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

Анализ проблемы: почему запрос возвращает пустую выборку?

Рассмотрим ситуацию, когда разработчик использует метод СтрЗаменить для модификации текста запроса в зависимости от типа документа. Проблема часто кроется в том, что при переходе от одиночного документа к списочному меняется сам источник данных. Если для одиночного документа источником является Документ.ПриемНаРаботу, то для списочного — Документ.ПриемНаРаботуСписком.Сотрудники.

Проанализируем типичные причины ошибок:

  1. Различие в именах полей: Поле, которое в шапке документа называется Организация, в табличной части может отсутствовать. Вместо этого к нему нужно обращаться через владельца: Ссылка.Организация.
  2. Несоответствие контекста СсылкаНаОбъект: При использовании механизма дополнительных отчетов и обработок (БСП) в процедуру печати часто передается не одна ссылка, а массив ссылок. Если код ожидает одиночное значение, проверка ТипЗнч(СсылканаОбъект) может отработать не так, как ожидалось.
  3. Ошибки при строковых заменах: Метод СтрЗаменить крайне чувствителен к именам псевдонимов. Если заменить «Документ.ПриемНаРаботу» на «Документ.ПриемНаРаботуСписком.Сотрудники», все последующие обращения к полям должны быть пересмотрены.

Способ 1. Динамическое формирование текста запроса

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

Рассмотрим пример правильной логики замены:


Если ТипЗнч(СсылканаОбъект) = Тип("ДокументСсылка.ПриемНаРаботуСписком") Тогда
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "Документ.ПриемНаРаботу", "Документ.ПриемНаРаботуСписком.Сотрудники");
    // Важно заменить обращения к реквизитам шапки, так как в табличной части их нет
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПриемНаРаботу.Дата", "ПриемНаРаботу.Ссылка.Дата");
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПриемНаРаботу.Организация", "ПриемНаРаботу.Ссылка.Организация");
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "ПриемНаРаботу.ТрудовойДоговорНомер", "ПриемНаРаботу.ТрудовойДоговорНомер"); // Если поле в ТЧ
КонецЕсли;

Совет: Всегда проверяйте итоговый текст запроса через Сообщить() или в отладчике. Скопируйте полученную строку в Консоль запросов — это самый быстрый способ увидеть синтаксическую ошибку или отсутствие данных из-за неверного соединения.

Способ 2. Использование временных таблиц для типизации данных

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

Выполним следующие шаги:

  1. Создадим массив ссылок (даже если печатаем один документ).
  2. В зависимости от типа документа выгрузим данные в таблицу значений с унифицированными именами колонок: ФизЛицо, Организация, ДатаДокумента, Ссылка.
  3. Передадим эту таблицу в запрос как параметр.

Рассмотрим пример подготовки данных:


Запрос = Новый Запрос;
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Ссылка", Новый ОписаниеТипов("УдалитьЭтоИПоставитьНужныеТипы"));
ТаблицаДанных.Колонки.Добавить("ФизическоеЛицо");
ТаблицаДанных.Колонки.Добавить("Организация");

// Заполняем таблицу в зависимости от типа
Если ТипЗнч(СсылканаОбъект) = Тип("ДокументСсылка.ПриемНаРаботуСписком") Тогда
    Для Каждого СтрокаТЧ Из СсылканаОбъект.Сотрудники Цикл
        НоваяСтрока = ТаблицаДанных.Добавить();
        НоваяСтрока.Ссылка = СсылканаОбъект;
        НоваяСтрока.ФизическоеЛицо = СтрокаТЧ.ФизическоеЛицо;
        НоваяСтрока.Организация = СсылканаОбъект.Организация;
    КонецЦикла;
Иначе
    НоваяСтрока = ТаблицаДанных.Добавить();
    ЗаполнитьЗначенияСвойств(НоваяСтрока, СсылканаОбъект);
КонецЕсли;

Запрос.УстановитьПараметр("ТаблицаДанных", ТаблицаДанных);
ТекстЗапроса = "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТаблицаДанных КАК ТаблицаДанных; ...";

Особенности соединений с виртуальными таблицами

В запросе автора используются левые соединения с регистрами сведений, например, РегистрСведений.ДокументыФизическихЛиц.СрезПоследних. Проанализируем критичный момент: если документ списочный, и вы соединяете его по полю ФизическоеЛицо, убедитесь, что в параметрах виртуальной таблицы СрезПоследних передана правильная дата.

Использование ЕСТЬNULL — обязательное условие. Если для сотрудника не заполнена контактная информация или паспортные данные, левое соединение вернет NULL. Если это поле участвует в дальнейших расчетах или условиях ГДЕ без обработки NULL, вся строка результата может исчезнуть из выборки.

Пример безопасного соединения:


ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ДокументыФизическихЛиц.СрезПоследних(&Период, ) КАК Документы
ПО ВТ_Документ.ФизическоеЛицо = Документы.Физлицо
И Документы.ВидДокумента = ЗНАЧЕНИЕ(Справочник.ВидыДокументовФизическихЛиц.ПаспортРФ)

Рекомендации по отладке универсальных форм

Чтобы ваша печатная форма работала стабильно, придерживайтесь следующих правил:

Таким образом, для создания качественной универсальной формы лучше уйти от прямого редактирования текста запроса методом СтрЗаменить в пользу предварительного формирования таблицы исходных данных. Это сделает ваш код прозрачным, а логику работы с разными типами документов — предсказуемой.

← На главную