При разработке печатных форм в среде «1С:Предприятие 8» программисты часто сталкиваются с ситуацией, когда попытка вывести значение в макет заканчивается ошибкой «Поле объекта не обнаружено». Чаще всего это происходит при работе с табличными частями документов, когда разработчик пытается использовать имя колонки, увиденное в конфигураторе на форме, вместо реального пути к данным в базе. В этой статье мы подробно разберем, почему возникает эта ошибка, как правильно обращаться к реквизитам через точку и как оптимизировать этот процесс для повышения производительности системы.
Рассмотрим ситуацию, описанную в обращении: разработчик пытается заполнить параметр макета ЕдИзм, используя конструкцию Стр.ТоварыНоменклатураЕдиницаИзмерения. Программа выдает ошибку, так как такого реквизита в строке табличной части не существует.
Выясним причину этой путаницы. В управляемых формах 1С имена элементов (колонок в таблице на форме) часто генерируются автоматически и выглядят как ТоварыНоменклатураЕдиницаИзмерения. Однако это лишь визуальный идентификатор элемента управления на форме. Он нужен для того, чтобы программно изменить цвет текста в колонке, скрыть её или заблокировать для редактирования.
Для получения же данных из базы необходимо использовать Путь к данным. В нашем случае данные «живут» внутри справочника «Номенклатура», ссылка на который хранится в строке табличной части. Таким образом, чтобы добраться до единицы измерения, нам нужно пройти по цепочке: СтрокаТЧ -> Номенклатура -> ЕдиницаИзмерения.
Проанализируем исправленный код. Чтобы программа «увидела» нужное поле, необходимо обратиться к реквизиту ссылки на номенклатуру. Правильный синтаксис в цикле обхода табличной части будет выглядеть следующим образом:
Для Каждого Стр Из Ссылка.Товары Цикл
ОбластьСтрока1.Параметры.ЕдИзм = Стр.Номенклатура.ЕдиницаИзмерения;
ОбластьСтрока1.Параметры.Кол = Стр.Количество;
// Другие параметры...
ТабДок.Вывести(ОбластьСтрока1);
КонецЦикла;
В данном примере Стр является объектом типа ЧисловаяСтрокаТабличнойЧасти. У этого объекта есть реквизит Номенклатура, который является ссылкой. Обращаясь через точку к Номенклатура.ЕдиницаИзмерения, мы заставляем систему считать данные из соответствующего справочника.
Хотя решение Стр.Номенклатура.ЕдиницаИзмерения является рабочим и часто используется в простых обработках, профессиональная разработка требует учета производительности. Рассмотрим подробнее, что происходит «под капотом» системы 1С.
Когда вы выполняете код Стр.Номенклатура.ЕдиницаИзмерения внутри цикла, платформа выполняет отдельный неявный SQL-запрос к базе данных на каждой итерации цикла. Если в вашем документе 100 строк с разной номенклатурой, система сделает 100 дополнительных обращений к серверу БД. Это значительно замедляет формирование печатной формы, особенно в клиент-серверном варианте работы или при медленном интернет-соединении.
Рассмотрим, как сделать правильно:
Для формирования качественной печатной формы данные лучше получать одним общим запросом. Это позволяет извлечь всю необходимую информацию (наименование, артикул, единицу измерения) за один «поход» в базу данных.
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДокТовары.НомерСтроки КАК Номер,
| ДокТовары.Номенклатура.Наименование КАК ТоварНаименование,
| ДокТовары.Номенклатура.ЕдиницаИзмерения КАК ЕдИзм,
| ДокТовары.Количество КАК Количество
|ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК ДокТовары
|ГДЕ
| ДокТовары.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
ОбластьСтрока1.Параметры.Заполнить(Выборка);
ТабДок.Вывести(ОбластьСтрока1);
КонецЦикла;
Использование запроса исключает лишнюю нагрузку на сервер и является стандартом разработки в типовых конфигурациях (УТ 11, БП 3.0, ERP).
В коде автора часто встречается метод Параметры.Заполнить(Стр). Разберем по шагам, как он работает. Этот метод берет все свойства переданного объекта (строки таблицы или выборки запроса) и ищет в макете параметры с точно такими же именами. Если имена совпадают, значение подставляется автоматически.
Если вы хотите, чтобы единица измерения заполнялась автоматически через Заполнить(), вам нужно в макете назвать параметр именно так, как называется поле в данных. Однако, если поле получается «через точку», автоматического сопоставления не произойдет, так как в структуре Стр (строки ТЧ) нет поля с именем НоменклатураЕдиницаИзмерения. Именно поэтому ручное присвоение ОбластьСтрока1.Параметры.ЕдИзм = ... становится необходимым, если вы не используете запрос с псевдонимами полей.
Выясним причину, по которой иногда трудно угадать название поля. В разных конфигурациях реквизит может называться по-разному. Например:
ЕдиницаИзмерения.Упаковка или Номенклатура.ЕдиницаИзмерения.ЕдиницаХранения или ОКЕИ.Чтобы не тратить время на гадание, воспользуемся отладчиком. Поставим точку останова (клавиша F9) на строке внутри цикла и запустим формирование печатной формы. Когда программа остановится:
Стр.Номенклатура, разверните её и посмотрите, как именно называется поле с единицей измерения.Проанализируем нюанс, который часто ставит в тупик новичков в конфигурациях на базе «1С:ERP» или «УТ 11». В этих системах понятие единицы измерения тесно связано с упаковками. В табличной части документа часто хранится ссылка на Упаковку. Если упаковка не задана, то товар отгружается в базовых единицах хранения.
Поэтому в коде для таких конфигураций часто можно встретить проверку:
Если ЗначениеЗаполнено(Стр.Упаковка) Тогда
ОбластьСтрока1.Параметры.ЕдИзм = Стр.Упаковка.ЕдиницаИзмерения;
Иначе
ОбластьСтрока1.Параметры.ЕдИзм = Стр.Номенклатура.ЕдиницаИзмерения;
КонецЕсли;
Это еще раз подчеркивает важность понимания структуры метаданных конкретной конфигурации, в которой вы ведете разработку.
Подведем итог нашему разбору. Ошибка «Поле не найдено» — это сигнал о том, что вы обращаетесь к объекту по имени, которого нет в его структуре данных. Для успешного решения задачи придерживайтесь следующих правил:
Ссылка.Товары.ЕдиницаИзмерения, ЕдиницаХранения и т.д.).Стр.Номенклатура.ЕдиницаИзмерения), используйте запрос. Это ускорит работу программы и снизит нагрузку на сервер.Заполнить(), убедитесь, что имена параметров в макете совпадают с именами полей в выборке вашего запроса.Следуя этим принципам, вы сможете создавать надежные и быстрые печатные формы, избегая досадных ошибок на этапе выполнения кода.