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