Как исправить ошибку «Поле объекта не обнаружено» при обращении к реквизитам отчета в управляемой форме 1С 8.3?

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

При переходе с платформы 1С 8.2 (или конфигураций вроде ЗУП 2.5) на современную платформу 1С 8.3 с управляемыми формами разработчики часто сталкиваются с проблемой доступа к данным формы в серверном коде. Ошибка вида Поле объекта не обнаружено (Дата1) возникает из-за изменения архитектуры работы с данными. Рассмотрим подробно, как правильно организовать получение параметров для отчетов и обработок, чтобы ваш код работал стабильно.

Анализируем причину возникновения ошибки

В обычных формах (8.2) мы привыкли обращаться к реквизитам обработки или отчета напрямую через ЭтотОбъект или ЭтаФорма. В управляемом приложении (8.3) ситуация изменилась. Если вы создали внешний отчет и добавили в него реквизиты Дата1, Дата2 и Организация, то в модуле формы эти данные не являются «родными» реквизитами самой формы. Они принадлежат объекту метаданных «Отчет».

Проанализируем ситуацию: когда мы вызываем серверную процедуру или функцию с директивой &НаСервере, платформа передает контекст формы на сервер. Однако обращение к данным отчета должно происходить через специальный программный интерфейс. Если мы пишем ЭтаФорма.Дата1, система ищет реквизит именно в объекте формы, не находя его там, так как он находится внутри структуры основного реквизита Отчет.

Решение 1: Правильное обращение к реквизитам объекта

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

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


&НаСервере
Функция ВыполнитьКомандуНаСервере()
    ЗапросБанк = Новый Запрос;
    // Вместо ЭтаФорма.Дата1 используем Отчет.Дата1
    ЗапросБанк.УстановитьПараметр("Дата1", Отчет.Дата1);
    ЗапросБанк.УстановитьПараметр("Дата2", Отчет.Дата2);    
    ЗапросБанк.УстановитьПараметр("Организация", Отчет.Организация);
    
    // Дальнейший текст запроса...
КонецФункции

Важный момент: если вы используете директиву &НаСервереБезКонтекста, то ни ЭтаФорма, ни Отчет вам доступны не будут. В таком случае параметры необходимо передавать явно из клиентской процедуры в серверную функцию.

Решение 2: Использование метода РеквизитФормыВЗначение

Иногда нам нужно не просто получить значения примитивных типов (дата, строка, число), а вызвать экспортный метод из модуля объекта отчета или получить доступ к его макетам. В управляемых формах для этого используется метод РеквизитФормыВЗначение. Рассмотрим, как правильно получить макет отчета, так как старый метод ЭтаФорма.ПолучитьМакет() в 8.3 может работать некорректно или отсутствовать в контексте.

Выясним, как преобразовать данные формы в полноценный объект обработки:


&НаСервере
Функция СформироватьОтчетНаСервере()
    // Преобразуем данные формы в объект "ВнешнийОтчет"
    ОбъектОтчет = РеквизитФормыВЗначение("Отчет");
    
    // Теперь мы можем получить макет прямо из объекта
    Макет = ОбъектОтчет.ПолучитьМакет("Макет");
    
    // И использовать параметры напрямую из объекта, если они там заполнены
    Запрос = Новый Запрос;
    Запрос.УстановитьПараметр("ДатаНачала", ОбъектОтчет.Дата1);
    
    // ... логика формирования табличного документа
КонецФункции

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

Оптимизация запроса для журнала ведомостей (Т-53А)

Проанализируем исходный код автора. В нем выполняются два раздельных запроса к разным типам документов: ВедомостьНаВыплатуЗарплатыВБанк и ВедомостьНаВыплатуЗарплатыВКассу. Это не самый эффективный способ. Рассмотрим, как объединить эти данные в один запрос, что упростит вывод в макет и ускорит работу отчета.

Выполним объединение данных с помощью конструкции ОБЪЕДИНИТЬ ВСЕ и добавим обязательный фильтр по организации и признаку проведения документа:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Ведомость.Дата КАК Дата,
    |	Ведомость.Номер КАК Номер,
    |	Ведомость.СпособВыплаты КАК СпособВыплаты,
    |	Ведомость.Подразделение КАК Подразделение,
    |	Ведомость.СуммаПоДокументу КАК СуммаПоДокументу
    |ИЗ
    |	Документ.ВедомостьНаВыплатуЗарплатыВБанк КАК Ведомость
    |ГДЕ
    |	Ведомость.Дата МЕЖДУ &Дата1 И &Дата2
    |	И Ведомость.Организация = &Организация
    |	И Ведомость.Проведен = ИСТИНА
    |
    |ОБЪЕДИНИТЬ ВСЕ
    |
    |ВЫБРАТЬ
    |	ВедомостьКасса.Дата,
    |	ВедомостьКасса.Номер,
    |	ВедомостьКасса.СпособВыплаты,
    |	ВедомостьКасса.Подразделение,
    |	ВедомостьКасса.СуммаПоДокументу
    |ИЗ
    |	Документ.ВедомостьНаВыплатуЗарплатыВКассу КАК ВедомостьКасса
    |ГДЕ
    |	ВедомостьКасса.Дата МЕЖДУ &Дата1 И &Дата2
    |	И ВедомостьКасса.Организация = &Организация
    |	И ВедомостьКасса.Проведен = ИСТИНА
    |
    |УПОРЯДОЧИТЬ ПО
    |	Дата";

Запрос.УстановитьПараметр("Дата1", Отчет.Дата1);
Запрос.УстановитьПараметр("Дата2", КонецДня(Отчет.Дата2));
Запрос.УстановитьПараметр("Организация", Отчет.Организация);

РезультатЗапроса = Запрос.Выполнить();

Обратите внимание: использование КонецДня() для второй даты крайне важно, иначе документы, созданные в последний день периода после 00:00:00, не попадут в отчет.

Рекомендации по выводу в табличный документ

В управляемом приложении работа с табличным документом имеет свои особенности. Если вы формируете отчет вручную через макет, следуйте проверенному алгоритму:

  1. Создайте новый объект ТабличныйДокумент на сервере.
  2. Получите макет (как мы разобрали выше, через РеквизитФормыВЗначение).
  3. В цикле обхода выборки запроса заполняйте параметры областей макета.
  4. Используйте метод Вывести() для добавления строк в итоговый документ.
  5. Верните готовый ТабличныйДокумент на клиент и отобразите его пользователю.

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


Выборка = РезультатЗапроса.Выбрать();
НомерСтроки = 0;
Пока Выборка.Следующий() Цикл
    НомерСтроки = НомерСтроки + 1;
    ОбластьСтроки = Макет.ПолучитьОбласть("Строка");
    ОбластьСтроки.Параметры.Заполнить(Выборка);
    ОбластьСтроки.Параметры.НомерСтроки = НомерСтроки;
    ТабДок.Вывести(ОбластьСтроки);
КонецЦикла;

Использование метода Заполнить() позволяет автоматически сопоставить имена полей в выборке запроса с именами параметров в макете, что значительно сокращает объем кода и уменьшает вероятность ошибок.

Заключение

Подведем итог. Ошибка получения данных из формы в 1С 8.3 чаще всего связана с попыткой использовать старые методы обращения к контексту. Для успешной разработки отчетов на управляемых формах всегда помните:

Соблюдение этих правил позволит вам быстро адаптировать старые отчеты из ЗУП 2.5 под современные требования платформы 8.3 и избежать досадных ошибок исполнения.

← На главную