При разработке в среде 1С:Предприятие 8.3 на управляемых формах, особенно в таких сложных типовых конфигурациях, как «1С:Управление торговлей, ред. 11» (УТ 11) или «1С:ERP Управление предприятием», программисты часто сталкиваются с неочевидным поведением отчетов. Типичный сценарий: требуется настроить вызов отчета из документа с автоматической установкой фильтра по определенному реквизиту (например, по контрагенту или складу).
В процессе реализации этой задачи могут возникать ошибки вида «Поле не найдено» или ситуации, когда отчет открывается, но формируется пустым, несмотря на наличие данных в информационной базе. В этой статье мы подробно разберем, почему возникают такие сложности, проанализируем архитектуру справочников УТ 11 и научимся правильно передавать параметры и отборы в отчеты, включая сложные цепочки реквизитов.
Давайте детально разберем ситуацию, когда разработчик пытается передать в структуру отбора ключ "Поставщик", ориентируясь на то, что видит на форме отчета. При открытии формы отчета система выдает ошибку: «Поле Поставщик не найдено». Выясним причину этого поведения.
Главное правило при программной установке отборов через параметры формы: ключи структуры отбора должны строго соответствовать именам полей в Схеме компоновки данных (СКД), а не визуальным заголовкам элементов на форме управляемого приложения. Пользователь видит на форме поле с приятным человекочитаемым заголовком «Поставщик». Однако внутри Схемы компоновки данных (в наборе данных запроса СКД) это поле носит системное имя Партнер. Когда платформа пытается применить отбор по несуществующему полю "Поставщик", закономерно возникает ошибка инициализации компоновщика.
Рассмотрим стандартный шаблон вызова отчета, который часто используют разработчики:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
Отбор = Новый Структура;
// ОШИБКА: Поля "Поставщик" нет в схеме компоновки данных!
Отбор.Вставить("Поставщик", ПараметрыВыполненияКоманды.Источник.Объект.Контрагент);
ПараметрыФормы = Новый Структура("Отбор, СформироватьПриОткрытии", Отбор, Истина);
ОткрытьФорму("Отчет.РасчетыСПоставщиками.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник);
КонецПроцедуры
Для исправления этой ошибки нам необходимо использовать реальное имя поля компоновки — Партнер или Контрагент. Но здесь мы сталкиваемся со второй, более глубокой архитектурной особенностью УТ 11.
В конфигурациях, построенных на современной платформе ERP-решений от 1С (УТ 11, КА 2, ERP 2), учет контрагентов разделен на две сущности:
СправочникСсылка.Партнеры. Это холдинги, группы компаний, бренды или просто фактические клиенты и поставщики, с которыми ведется управленческое взаимодействие.СправочникСсылка.Контрагенты. Это конкретные юридические лица, индивидуальные предприниматели и физические лица с ИНН/КПП, с которыми заключаются официальные договоры и ведутся взаиморасчеты.Даже если в настройках системы (НСИ и администрирование -> CRM и маркетинг) снят флаг «Независимо вести партнеров и контрагентов», это не означает, что справочники объединились. Проанализируем, что происходит при отключении этой опции:
Приобретение товаров и услуг) по-прежнему присутствуют оба реквизита: и Партнер, и Контрагент.Почему при передаче "Контрагента" вместо "Партнера" отчет выводится пустым? Отчет «Ведомость расчетов с поставщиками» (как и большинство отчетов по взаиморасчетам и продажам в УТ 11) в качестве основного разреза аналитики использует именно поле Партнер. Если мы передаем в структуру отбора по полю Партнер ссылку на справочник Контрагенты, типы данных не совпадают. СКД выполняет сравнение разнотипных ссылок, отбор накладывается некорректно, и результатом выполнения отчета становится пустой набор данных.
Правильный вариант заполнения отбора для открытия отчета "Ведомость расчетов с поставщиками" выглядит следующим образом:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
Отбор = Новый Структура;
// Указываем истинное имя поля СКД "Партнер"
// и передаем ссылку именно на справочник Партнеры
Отбор.Вставить("Партнер", ПараметрыВыполненияКоманды.Источник.Объект.Партнер);
ПараметрыФормы = Новый Структура("Отбор, СформироватьПриОткрытии", Отбор, Истина);
ОткрытьФорму("Отчет.РасчетыСПоставщиками.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник);
КонецПроцедуры
Если в вашем документе-источнике доступен только реквизит Контрагент, то перед вызовом отчета необходимо получить связанного с ним партнера. Сделать это можно через обращение к реквизиту контрагента (на сервере или через точку в транзакции базы данных): Контрагент.Партнер.
Рассмотрим вторую практическую задачу: необходимо вызвать отчет из документа и передать в отбор реквизит «Поклажедержатель» по цепочке взаимосвязей: Документ -> Склад -> Поклажедержатель.
В конфигурации УТ 11 функционал ответственного хранения привязан к справочнику Склады. Если склад настроен как склад ответственного хранения, у него заполняется реквизит, определяющий хранителя груза. В зависимости от релиза конфигурации, этот реквизит в метаданных может называться ОрганизацияХранитель, Поклажедержатель или Хранитель.
Давайте разберем по шагам, как правильно реализовать передачу такого отбора:
Поскольку нам нужно вытащить реквизит справочника через другой справочник, нам необходимо сначала получить ссылку на поклажедержателя. На клиенте обращение через несколько точек (Объект.Склад.ОрганизацияХранитель) может работать не всегда эффективно или вызывать лишние серверные вызовы. Безопаснее получить это значение на сервере или использовать надежную проверку заполнения:
// Пример получения значения на клиенте (если реквизиты склада закэшированы)
ПоклажедержательЗначение = ПараметрыВыполненияКоманды.Источник.Объект.Склад.ОрганизацияХранитель;
При передаче отбора в СКД нам необязательно иметь на форме отчета отдельное явное поле «Поклажедержатель». Мощный механизм компоновки данных 1С позволяет накладывать отборы на реквизиты связанных объектов через точку. Главное, чтобы в СКД было доступно само поле Склад.
Посмотрим, как выглядит программный код для реализации такого отбора:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
// 1. Получаем склад из документа-источника
СкладДокумента = ПараметрыВыполненияКоманды.Источник.Объект.Склад;
// 2. Для надежности получаем организацию-хранителя (поклажедержателя)
// В реальной задаче лучше получить этот реквизит безопасным способом
ПоклажедержательЗначение = ПолучитьПоклажедержателяСклада(СкладДокумента);
Отбор = Новый Структура;
// Сценарий А: Если в отчете есть прямое поле "Поклажедержатель"
Отбор.Вставить("Поклажедержатель", ПоклажедержательЗначение);
// Сценарий Б: Если в отчете есть только поле "Склад",
// мы можем установить отбор через точку по его реквизиту:
// Отбор.Вставить("Склад.ОрганизацияХранитель", ПоклажедержательЗначение);
ПараметрыФормы = Новый Структура("Отбор, СформироватьПриОткрытии", Отбор, Истина);
ОткрытьФорму("Отчет.ДвижениеТоваровНаСкладахИсполнителей.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьПоклажедержателяСклада(СкладСсылка)
// Извлекаем значение реквизита склада на сервере
Возврат ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СкладСсылка, "ОрганизацияХранитель");
КонецФункции
Поскольку современные версии «1С:Управление торговлей 11» построены с использованием библиотек БСП (Библиотека стандартных подсистем), обычная передача структуры Отбор в параметрах формы может не сработать. Это происходит из-за того, что БСП кэширует настройки отчетов, сделанные пользователем ранее, и восстанавливает их при открытии формы, затирая переданные параметры.
Чтобы гарантированно установить отбор в отчетах на базе БСП, рекомендуется передавать его через параметры пользовательских настроек компоновщика БСП. Проанализируем правильный шаблон интеграции с подсистемой «Варианты отчетов» БСП:
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
// Формируем структуру пользовательских настроек по стандартам БСП
ПользовательскиеНастройки = Новый Структура;
Отбор = Новый Структура;
Отбор.Вставить("Партнер", ПараметрыВыполненияКоманды.Источник.Объект.Партнер);
// Заворачиваем отбор в параметры, которые понимает отчет БСП
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("Отбор", Отбор);
ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
// Открываем форму отчета с передачей структуры настроек
ОткрытьФорму("Отчет.РасчетыСПоставщиками.Форма", ПараметрыФормы, ПараметрыВыполненияКоманды.Источник);
КонецПроцедуры
Использование этого подхода гарантирует, что переданные нами значения не будут перекрыты старыми сохраненными настройками пользователя, и отчет всегда будет открываться с актуальными и корректными данными.